summaryrefslogtreecommitdiff
path: root/Utilities/cmcurl/lib/vtls
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2017-05-11 10:55:44 -0400
committerBrad King <brad.king@kitware.com>2017-05-11 11:27:21 -0400
commit299975908ada992800791fac7f3739050e0ae2a9 (patch)
tree38cd8fb04ce84196dfa04d514eb92649900a1bc5 /Utilities/cmcurl/lib/vtls
parent5af9c8e2451afd8e63d6b05e69cd141af543a164 (diff)
parentfd7d521c9d70655618db8232d45e5aaf81700f91 (diff)
downloadcmake-299975908ada992800791fac7f3739050e0ae2a9.tar.gz
Merge branch 'upstream-curl' into update-curl
* upstream-curl: curl 2017-04-19 (d957e218) Resolve conflicts in `CMakeLists.txt` in favor of the upstream version. We will re-apply our logic as needed in following commits.
Diffstat (limited to 'Utilities/cmcurl/lib/vtls')
-rw-r--r--Utilities/cmcurl/lib/vtls/axtls.c28
-rw-r--r--Utilities/cmcurl/lib/vtls/axtls.h8
-rw-r--r--Utilities/cmcurl/lib/vtls/cyassl.c47
-rw-r--r--Utilities/cmcurl/lib/vtls/cyassl.h10
-rw-r--r--Utilities/cmcurl/lib/vtls/darwinssl.c218
-rw-r--r--Utilities/cmcurl/lib/vtls/darwinssl.h6
-rw-r--r--Utilities/cmcurl/lib/vtls/gskit.c52
-rw-r--r--Utilities/cmcurl/lib/vtls/gtls.c173
-rw-r--r--Utilities/cmcurl/lib/vtls/gtls.h8
-rw-r--r--Utilities/cmcurl/lib/vtls/mbedtls.c166
-rw-r--r--Utilities/cmcurl/lib/vtls/mbedtls.h12
-rw-r--r--Utilities/cmcurl/lib/vtls/nss.c181
-rw-r--r--Utilities/cmcurl/lib/vtls/nssg.h8
-rw-r--r--Utilities/cmcurl/lib/vtls/openssl.c364
-rw-r--r--Utilities/cmcurl/lib/vtls/openssl.h6
-rw-r--r--Utilities/cmcurl/lib/vtls/polarssl.c100
-rw-r--r--Utilities/cmcurl/lib/vtls/polarssl.h3
-rw-r--r--Utilities/cmcurl/lib/vtls/schannel.c81
-rw-r--r--Utilities/cmcurl/lib/vtls/schannel.h4
-rw-r--r--Utilities/cmcurl/lib/vtls/vtls.c63
20 files changed, 1058 insertions, 480 deletions
diff --git a/Utilities/cmcurl/lib/vtls/axtls.c b/Utilities/cmcurl/lib/vtls/axtls.c
index ff4634e5b7..f0e376640c 100644
--- a/Utilities/cmcurl/lib/vtls/axtls.c
+++ b/Utilities/cmcurl/lib/vtls/axtls.c
@@ -6,7 +6,7 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2010, DirecTV, Contact: Eric Hu, <ehu@directv.com>.
- * Copyright (C) 2010 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2010 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -156,6 +156,12 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
same connection */
return CURLE_OK;
+ if(SSL_CONN_CONFIG(version_max) != CURL_SSLVERSION_MAX_NONE) {
+ failf(data, "axtls does not support CURL_SSLVERSION_MAX");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+
/* axTLS only supports TLSv1 */
/* check to see if we've been told to use an explicit SSL/TLS version */
switch(SSL_CONN_CONFIG(version)) {
@@ -256,7 +262,7 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
* 2) setting up callbacks. these seem gnutls specific
*/
- if(data->set.general_ssl.sessionid) {
+ if(SSL_SET_OPTION(primary.sessionid)) {
const uint8_t *ssl_sessionid;
size_t ssl_idsize;
@@ -267,13 +273,13 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
/* we got a session id, use it! */
infof(data, "SSL re-using session ID\n");
ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex],
- ssl_sessionid, (uint8_t)ssl_idsize);
+ ssl_sessionid, (uint8_t)ssl_idsize, NULL);
}
Curl_ssl_sessionid_unlock(conn);
}
if(!ssl)
- ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], NULL, 0);
+ ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], NULL, 0, NULL);
conn->ssl[sockindex].ssl = ssl;
return CURLE_OK;
@@ -386,9 +392,9 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex)
conn->send[sockindex] = axtls_send;
/* Put our freshly minted SSL session in cache */
- if(data->set.general_ssl.sessionid) {
- const uint8_t *ssl_sessionid = ssl_get_session_id_size(ssl);
- size_t ssl_idsize = ssl_get_session_id(ssl);
+ if(SSL_SET_OPTION(primary.sessionid)) {
+ const uint8_t *ssl_sessionid = ssl_get_session_id(ssl);
+ size_t ssl_idsize = ssl_get_session_id_size(ssl);
Curl_ssl_sessionid_lock(conn);
if(Curl_ssl_addsessionid(conn, (void *) ssl_sessionid, ssl_idsize,
sockindex) != CURLE_OK)
@@ -680,9 +686,9 @@ size_t Curl_axtls_version(char *buffer, size_t size)
return snprintf(buffer, size, "axTLS/%s", ssl_version());
}
-int Curl_axtls_random(struct Curl_easy *data,
- unsigned char *entropy,
- size_t length)
+CURLcode Curl_axtls_random(struct Curl_easy *data,
+ unsigned char *entropy,
+ size_t length)
{
static bool ssl_seeded = FALSE;
(void)data;
@@ -694,7 +700,7 @@ int Curl_axtls_random(struct Curl_easy *data,
RNG_initialize();
}
get_random((int)length, entropy);
- return 0;
+ return CURLE_OK;
}
#endif /* USE_AXTLS */
diff --git a/Utilities/cmcurl/lib/vtls/axtls.h b/Utilities/cmcurl/lib/vtls/axtls.h
index b16d051aac..53797eadbb 100644
--- a/Utilities/cmcurl/lib/vtls/axtls.h
+++ b/Utilities/cmcurl/lib/vtls/axtls.h
@@ -8,7 +8,7 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2010, DirecTV, Contact: Eric Hu <ehu@directv.com>
- * Copyright (C) 2010 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2010 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -42,9 +42,9 @@ void Curl_axtls_session_free(void *ptr);
size_t Curl_axtls_version(char *buffer, size_t size);
int Curl_axtls_shutdown(struct connectdata *conn, int sockindex);
int Curl_axtls_check_cxn(struct connectdata *conn);
-int Curl_axtls_random(struct Curl_easy *data,
- unsigned char *entropy,
- size_t length);
+CURLcode Curl_axtls_random(struct Curl_easy *data,
+ unsigned char *entropy,
+ size_t length);
/* Set the API backend definition to axTLS */
#define CURL_SSL_BACKEND CURLSSLBACKEND_AXTLS
diff --git a/Utilities/cmcurl/lib/vtls/cyassl.c b/Utilities/cmcurl/lib/vtls/cyassl.c
index fc4dde4a1a..5f51ad5f99 100644
--- a/Utilities/cmcurl/lib/vtls/cyassl.c
+++ b/Utilities/cmcurl/lib/vtls/cyassl.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -134,6 +134,7 @@ cyassl_connect_step1(struct connectdata *conn,
int sockindex)
{
char error_buffer[CYASSL_MAX_ERROR_SZ];
+ char *ciphers;
struct Curl_easy *data = conn->data;
struct ssl_connect_data* conssl = &conn->ssl[sockindex];
SSL_METHOD* req_method = NULL;
@@ -148,6 +149,11 @@ cyassl_connect_step1(struct connectdata *conn,
if(conssl->state == ssl_connection_complete)
return CURLE_OK;
+ if(SSL_CONN_CONFIG(version_max) != CURL_SSLVERSION_MAX_NONE) {
+ failf(data, "CyaSSL does not support to set maximum SSL/TLS version");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
/* check to see if we've been told to use an explicit SSL/TLS version */
switch(SSL_CONN_CONFIG(version)) {
case CURL_SSLVERSION_DEFAULT:
@@ -229,6 +235,15 @@ cyassl_connect_step1(struct connectdata *conn,
break;
}
+ ciphers = SSL_CONN_CONFIG(cipher_list);
+ if(ciphers) {
+ if(!SSL_CTX_set_cipher_list(conssl->ctx, ciphers)) {
+ failf(data, "failed setting cipher list: %s", ciphers);
+ return CURLE_SSL_CIPHER;
+ }
+ infof(data, "Cipher selection: %s\n", ciphers);
+ }
+
#ifndef NO_FILESYSTEM
/* load trusted cacert */
if(SSL_CONN_CONFIG(CAfile)) {
@@ -383,7 +398,7 @@ cyassl_connect_step1(struct connectdata *conn,
#endif /* HAVE_ALPN */
/* Check if there's a cached ID we can/should use here! */
- if(data->set.general_ssl.sessionid) {
+ if(SSL_SET_OPTION(primary.sessionid)) {
void *ssl_sessionid = NULL;
Curl_ssl_sessionid_lock(conn);
@@ -581,7 +596,13 @@ cyassl_connect_step2(struct connectdata *conn,
#endif /* HAVE_ALPN */
conssl->connecting_state = ssl_connect_3;
+#if (LIBCYASSL_VERSION_HEX >= 0x03009010)
+ infof(data, "SSL connection using %s / %s\n",
+ wolfSSL_get_version(conssl->handle),
+ wolfSSL_get_cipher_name(conssl->handle));
+#else
infof(data, "SSL connected\n");
+#endif
return CURLE_OK;
}
@@ -597,7 +618,7 @@ cyassl_connect_step3(struct connectdata *conn,
DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
- if(data->set.general_ssl.sessionid) {
+ if(SSL_SET_OPTION(primary.sessionid)) {
bool incache;
SSL_SESSION *our_ssl_sessionid;
void *old_ssl_sessionid = NULL;
@@ -720,7 +741,9 @@ void Curl_cyassl_session_free(void *ptr)
size_t Curl_cyassl_version(char *buffer, size_t size)
{
-#ifdef WOLFSSL_VERSION
+#if LIBCYASSL_VERSION_HEX >= 0x03006000
+ return snprintf(buffer, size, "wolfSSL/%s", wolfSSL_lib_version());
+#elif defined(WOLFSSL_VERSION)
return snprintf(buffer, size, "wolfSSL/%s", WOLFSSL_VERSION);
#elif defined(CYASSL_VERSION)
return snprintf(buffer, size, "CyaSSL/%s", CYASSL_VERSION);
@@ -772,7 +795,7 @@ cyassl_connect_common(struct connectdata *conn,
struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
curl_socket_t sockfd = conn->sock[sockindex];
- long timeout_ms;
+ time_t timeout_ms;
int what;
/* check if the connection has already been established */
@@ -901,19 +924,19 @@ Curl_cyassl_connect(struct connectdata *conn,
return CURLE_OK;
}
-int Curl_cyassl_random(struct Curl_easy *data,
- unsigned char *entropy,
- size_t length)
+CURLcode Curl_cyassl_random(struct Curl_easy *data,
+ unsigned char *entropy,
+ size_t length)
{
RNG rng;
(void)data;
if(InitRng(&rng))
- return 1;
+ return CURLE_FAILED_INIT;
if(length > UINT_MAX)
- return 1;
+ return CURLE_FAILED_INIT;
if(RNG_GenerateBlock(&rng, entropy, (unsigned)length))
- return 1;
- return 0;
+ return CURLE_FAILED_INIT;
+ return CURLE_OK;
}
void Curl_cyassl_sha256sum(const unsigned char *tmp, /* input */
diff --git a/Utilities/cmcurl/lib/vtls/cyassl.h b/Utilities/cmcurl/lib/vtls/cyassl.h
index 508dfaaf07..f47719e4e7 100644
--- a/Utilities/cmcurl/lib/vtls/cyassl.h
+++ b/Utilities/cmcurl/lib/vtls/cyassl.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -51,15 +51,15 @@ int Curl_cyassl_init(void);
CURLcode Curl_cyassl_connect_nonblocking(struct connectdata *conn,
int sockindex,
bool *done);
-int Curl_cyassl_random(struct Curl_easy *data,
- unsigned char *entropy,
- size_t length);
+CURLcode Curl_cyassl_random(struct Curl_easy *data,
+ unsigned char *entropy,
+ size_t length);
void Curl_cyassl_sha256sum(const unsigned char *tmp, /* input */
size_t tmplen,
unsigned char *sha256sum, /* output */
size_t unused);
-/* Set the API backend definition to Schannel */
+/* Set the API backend definition to CyaSSL */
#define CURL_SSL_BACKEND CURLSSLBACKEND_CYASSL
/* this backend supports CURLOPT_SSL_CTX_* */
diff --git a/Utilities/cmcurl/lib/vtls/darwinssl.c b/Utilities/cmcurl/lib/vtls/darwinssl.c
index a43e391258..5533dfe2f7 100644
--- a/Utilities/cmcurl/lib/vtls/darwinssl.c
+++ b/Utilities/cmcurl/lib/vtls/darwinssl.c
@@ -6,7 +6,7 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2012 - 2014, Nick Zitzmann, <nickzman@gmail.com>.
- * Copyright (C) 2012 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -219,6 +219,7 @@ static OSStatus SocketWrite(SSLConnectionRef connection,
return ortn;
}
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
CF_INLINE const char *SSLCipherNameForNumber(SSLCipherSuite cipher)
{
switch(cipher) {
@@ -776,6 +777,7 @@ CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher)
}
return "TLS_NULL_WITH_NULL_NULL";
}
+#endif /* !CURL_DISABLE_VERBOSE_STRINGS */
#if CURL_BUILD_MAC
CF_INLINE void GetDarwinVersionNumber(int *major, int *minor)
@@ -885,12 +887,13 @@ static OSStatus CopyIdentityWithLabel(char *label,
SecIdentityRef *out_cert_and_key)
{
OSStatus status = errSecItemNotFound;
+
+#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
CFArrayRef keys_list;
CFIndex keys_list_count;
CFIndex i;
CFStringRef common_name;
-#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
/* SecItemCopyMatching() was introduced in iOS and Snow Leopard.
kSecClassIdentity was introduced in Lion. If both exist, let's use them
to find the certificate. */
@@ -929,28 +932,35 @@ static OSStatus CopyIdentityWithLabel(char *label,
if(status == noErr) {
keys_list_count = CFArrayGetCount(keys_list);
*out_cert_and_key = NULL;
+ status = 1;
for(i=0; i<keys_list_count; i++) {
OSStatus err = noErr;
SecCertificateRef cert = NULL;
- *out_cert_and_key =
+ SecIdentityRef identity =
(SecIdentityRef) CFArrayGetValueAtIndex(keys_list, i);
- err = SecIdentityCopyCertificate(*out_cert_and_key, &cert);
+ err = SecIdentityCopyCertificate(identity, &cert);
if(err == noErr) {
+#if CURL_BUILD_IOS
+ common_name = SecCertificateCopySubjectSummary(cert);
+#elif CURL_BUILD_MAC_10_7
SecCertificateCopyCommonName(cert, &common_name);
+#endif
if(CFStringCompare(common_name, label_cf, 0) == kCFCompareEqualTo) {
CFRelease(cert);
CFRelease(common_name);
+ CFRetain(identity);
+ *out_cert_and_key = identity;
status = noErr;
break;
}
CFRelease(common_name);
}
- *out_cert_and_key = NULL;
- status = 1;
CFRelease(cert);
}
}
+ if(keys_list)
+ CFRelease(keys_list);
CFRelease(query_dict);
CFRelease(label_cf);
}
@@ -1034,6 +1044,109 @@ CF_INLINE bool is_file(const char *filename)
return false;
}
+#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
+static CURLcode darwinssl_version_from_curl(long *darwinver, long ssl_version)
+{
+ switch(ssl_version) {
+ case CURL_SSLVERSION_TLSv1_0:
+ *darwinver = kTLSProtocol1;
+ return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_1:
+ *darwinver = kTLSProtocol11;
+ return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_2:
+ *darwinver = kTLSProtocol12;
+ return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_3:
+ break;
+ }
+ return CURLE_SSL_CONNECT_ERROR;
+}
+#endif
+
+static CURLcode
+set_ssl_version_min_max(struct connectdata *conn, int sockindex)
+{
+ struct Curl_easy *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ long ssl_version = SSL_CONN_CONFIG(version);
+ long ssl_version_max = SSL_CONN_CONFIG(version_max);
+
+ switch(ssl_version) {
+ case CURL_SSLVERSION_DEFAULT:
+ case CURL_SSLVERSION_TLSv1:
+ ssl_version = CURL_SSLVERSION_TLSv1_0;
+ ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
+ break;
+ }
+
+ switch(ssl_version_max) {
+ case CURL_SSLVERSION_MAX_NONE:
+ ssl_version_max = ssl_version << 16;
+ break;
+ case CURL_SSLVERSION_MAX_DEFAULT:
+ ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
+ break;
+ }
+
+#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
+ if(SSLSetProtocolVersionMax != NULL) {
+ SSLProtocol darwin_ver_min = kTLSProtocol1;
+ SSLProtocol darwin_ver_max = kTLSProtocol1;
+ CURLcode result = darwinssl_version_from_curl(&darwin_ver_min,
+ ssl_version);
+ if(result) {
+ failf(data, "unsupported min version passed via CURLOPT_SSLVERSION");
+ return result;
+ }
+ result = darwinssl_version_from_curl(&darwin_ver_max,
+ ssl_version_max >> 16);
+ if(result) {
+ failf(data, "unsupported max version passed via CURLOPT_SSLVERSION");
+ return result;
+ }
+
+ (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, darwin_ver_min);
+ (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, darwin_ver_max);
+ return result;
+ }
+ else {
+#if CURL_SUPPORT_MAC_10_8
+ long i = ssl_version;
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kSSLProtocolAll,
+ false);
+ for(; i <= (ssl_version_max >> 16); i++) {
+ switch(i) {
+ case CURL_SSLVERSION_TLSv1_0:
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kTLSProtocol1,
+ true);
+ break;
+ case CURL_SSLVERSION_TLSv1_1:
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kTLSProtocol11,
+ true);
+ break;
+ case CURL_SSLVERSION_TLSv1_2:
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kTLSProtocol12,
+ true);
+ break;
+ case CURL_SSLVERSION_TLSv1_3:
+ failf(data, "DarwinSSL: TLS 1.3 is not yet supported");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+ return CURLE_OK;
+#endif /* CURL_SUPPORT_MAC_10_8 */
+ }
+#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
+ failf(data, "DarwinSSL: cannot set SSL protocol");
+ return CURLE_SSL_CONNECT_ERROR;
+}
+
+
static CURLcode darwinssl_connect_step1(struct connectdata *conn,
int sockindex)
{
@@ -1103,20 +1216,15 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
(void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12);
break;
case CURL_SSLVERSION_TLSv1_0:
- (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1);
- (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol1);
- break;
case CURL_SSLVERSION_TLSv1_1:
- (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol11);
- (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol11);
- break;
case CURL_SSLVERSION_TLSv1_2:
- (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol12);
- (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12);
- break;
case CURL_SSLVERSION_TLSv1_3:
- failf(data, "DarwinSSL: TLS 1.3 is not yet supported");
- return CURLE_SSL_CONNECT_ERROR;
+ {
+ CURLcode result = set_ssl_version_min_max(conn, sockindex);
+ if(result != CURLE_OK)
+ return result;
+ break;
+ }
case CURL_SSLVERSION_SSLv3:
err = SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol3);
if(err != noErr) {
@@ -1157,23 +1265,15 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
true);
break;
case CURL_SSLVERSION_TLSv1_0:
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
- kTLSProtocol1,
- true);
- break;
case CURL_SSLVERSION_TLSv1_1:
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
- kTLSProtocol11,
- true);
- break;
case CURL_SSLVERSION_TLSv1_2:
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
- kTLSProtocol12,
- true);
- break;
case CURL_SSLVERSION_TLSv1_3:
- failf(data, "DarwinSSL: TLS 1.3 is not yet supported");
- return CURLE_SSL_CONNECT_ERROR;
+ {
+ CURLcode result = set_ssl_version_min_max(conn, sockindex);
+ if(result != CURLE_OK)
+ return result;
+ break;
+ }
case CURL_SSLVERSION_SSLv3:
err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
kSSLProtocol3,
@@ -1199,6 +1299,11 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
#endif /* CURL_SUPPORT_MAC_10_8 */
}
#else
+ if(conn->ssl_config.version_max != CURL_SSLVERSION_MAX_NONE) {
+ failf(data, "Your version of the OS does not support to set maximum"
+ " SSL/TLS version");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
(void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kSSLProtocolAll, false);
switch(conn->ssl_config.version) {
case CURL_SSLVERSION_DEFAULT:
@@ -1385,18 +1490,13 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
}
#endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */
- if(ssl_cafile) {
+ if(ssl_cafile && verifypeer) {
bool is_cert_file = is_file(ssl_cafile);
if(!is_cert_file) {
failf(data, "SSL: can't load CA certificate file %s", ssl_cafile);
return CURLE_SSL_CACERT_BADFILE;
}
- if(!verifypeer) {
- failf(data, "SSL: CA certificate set, but certificate verification "
- "is disabled");
- return CURLE_SSL_CONNECT_ERROR;
- }
}
/* Configure hostname check. SNI is used if available.
@@ -1420,6 +1520,9 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
"the OS.\n");
}
}
+ else {
+ infof(data, "WARNING: disabling hostname validation also disables SNI.\n");
+ }
/* Disable cipher suites that ST supports but are not safe. These ciphers
are unlikely to be used in any case since ST gives other ciphers a much
@@ -1541,7 +1644,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
/* Check if there's a cached ID we can/should use here! */
- if(data->set.general_ssl.sessionid) {
+ if(SSL_SET_OPTION(primary.sessionid)) {
char *ssl_sessionid;
size_t ssl_sessionid_len;
@@ -1921,7 +2024,7 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
/* The below is errSSLServerAuthCompleted; it's not defined in
Leopard's headers */
case -9841:
- if(SSL_CONN_CONFIG(CAfile)) {
+ if(SSL_CONN_CONFIG(CAfile) && SSL_CONN_CONFIG(verifypeer)) {
int res = verify_cert(SSL_CONN_CONFIG(CAfile), data,
connssl->ssl_ctx);
if(res != CURLE_OK)
@@ -2034,9 +2137,11 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
}
}
-static CURLcode
-darwinssl_connect_step3(struct connectdata *conn,
- int sockindex)
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+/* This should be called during step3 of the connection at the earliest */
+static void
+show_verbose_server_cert(struct connectdata *conn,
+ int sockindex)
{
struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
@@ -2048,9 +2153,9 @@ darwinssl_connect_step3(struct connectdata *conn,
CFIndex i, count;
SecTrustRef trust = NULL;
- /* There is no step 3!
- * Well, okay, if verbose mode is on, let's print the details of the
- * server certificates. */
+ if(!connssl->ssl_ctx)
+ return;
+
#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
#if CURL_BUILD_IOS
#pragma unused(server_certs)
@@ -2147,6 +2252,23 @@ darwinssl_connect_step3(struct connectdata *conn,
CFRelease(server_certs);
}
#endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
+}
+#endif /* !CURL_DISABLE_VERBOSE_STRINGS */
+
+static CURLcode
+darwinssl_connect_step3(struct connectdata *conn,
+ int sockindex)
+{
+ struct Curl_easy *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+
+ /* There is no step 3!
+ * Well, okay, if verbose mode is on, let's print the details of the
+ * server certificates. */
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ if(data->set.verbose)
+ show_verbose_server_cert(conn, sockindex);
+#endif
connssl->connecting_state = ssl_connect_done;
return CURLE_OK;
@@ -2424,8 +2546,8 @@ bool Curl_darwinssl_data_pending(const struct connectdata *conn,
return false;
}
-int Curl_darwinssl_random(unsigned char *entropy,
- size_t length)
+CURLcode Curl_darwinssl_random(unsigned char *entropy,
+ size_t length)
{
/* arc4random_buf() isn't available on cats older than Lion, so let's
do this manually for the benefit of the older cats. */
@@ -2439,7 +2561,7 @@ int Curl_darwinssl_random(unsigned char *entropy,
random_number >>= 8;
}
i = random_number = 0;
- return 0;
+ return CURLE_OK;
}
void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */
diff --git a/Utilities/cmcurl/lib/vtls/darwinssl.h b/Utilities/cmcurl/lib/vtls/darwinssl.h
index 8b185b67fc..4bd41ca470 100644
--- a/Utilities/cmcurl/lib/vtls/darwinssl.h
+++ b/Utilities/cmcurl/lib/vtls/darwinssl.h
@@ -8,7 +8,7 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2012 - 2014, Nick Zitzmann, <nickzman@gmail.com>.
- * Copyright (C) 2012 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -42,8 +42,8 @@ int Curl_darwinssl_check_cxn(struct connectdata *conn);
bool Curl_darwinssl_data_pending(const struct connectdata *conn,
int connindex);
-int Curl_darwinssl_random(unsigned char *entropy,
- size_t length);
+CURLcode Curl_darwinssl_random(unsigned char *entropy,
+ size_t length);
void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */
size_t tmplen,
unsigned char *md5sum, /* output */
diff --git a/Utilities/cmcurl/lib/vtls/gskit.c b/Utilities/cmcurl/lib/vtls/gskit.c
index a0d462b70a..bf75bddc2c 100644
--- a/Utilities/cmcurl/lib/vtls/gskit.c
+++ b/Utilities/cmcurl/lib/vtls/gskit.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -320,7 +320,7 @@ static CURLcode set_ciphers(struct connectdata *conn,
/* We allocate GSKit buffers of the same size as the input string: since
GSKit tokens are always shorter than their cipher names, allocated buffers
- will always be large enough to accomodate the result. */
+ will always be large enough to accommodate the result. */
l = strlen(cipherlist) + 1;
memset((char *) ciphers, 0, sizeof ciphers);
for(i = 0; i < CURL_GSKPROTO_LAST; i++) {
@@ -748,6 +748,40 @@ static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf,
return (ssize_t) nread;
}
+static CURLcode
+set_ssl_version_min_max(unsigned int *protoflags, struct connectdata *conn)
+{
+ struct Curl_easy *data = conn->data;
+ long ssl_version = SSL_CONN_CONFIG(version);
+ long ssl_version_max = SSL_CONN_CONFIG(version_max);
+ long i = ssl_version;
+ switch(ssl_version_max) {
+ case CURL_SSLVERSION_MAX_NONE:
+ ssl_version_max = ssl_version;
+ break;
+ case CURL_SSLVERSION_MAX_DEFAULT:
+ ssl_version_max = CURL_SSLVERSION_TLSv1_2;
+ break;
+ }
+ for(; i <= (ssl_version_max >> 16); ++i) {
+ switch(i) {
+ case CURL_SSLVERSION_TLSv1_0:
+ *protoflags |= CURL_GSKPROTO_TLSV10_MASK;
+ break;
+ case CURL_SSLVERSION_TLSv1_1:
+ *protoflags |= CURL_GSKPROTO_TLSV11_MASK;
+ break;
+ case CURL_SSLVERSION_TLSv1_2:
+ *protoflags |= CURL_GSKPROTO_TLSV11_MASK;
+ break;
+ case CURL_SSLVERSION_TLSv1_3:
+ failf(data, "GSKit: TLS 1.3 is not yet supported");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+
+ return CURLE_OK;
+}
static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
{
@@ -764,7 +798,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
const char * const hostname = SSL_IS_PROXY()? conn->http_proxy.host.name:
conn->host.name;
const char *sni;
- unsigned int protoflags;
+ unsigned int protoflags = 0;
long timeout;
Qso_OverlappedIO_t commarea;
int sockpair[2];
@@ -849,17 +883,13 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK;
break;
case CURL_SSLVERSION_TLSv1_0:
- protoflags = CURL_GSKPROTO_TLSV10_MASK;
- break;
case CURL_SSLVERSION_TLSv1_1:
- protoflags = CURL_GSKPROTO_TLSV11_MASK;
- break;
case CURL_SSLVERSION_TLSv1_2:
- protoflags = CURL_GSKPROTO_TLSV12_MASK;
- break;
case CURL_SSLVERSION_TLSv1_3:
- failf(data, "GSKit: TLS 1.3 is not yet supported");
- return CURLE_SSL_CONNECT_ERROR;
+ result = set_ssl_version_min_max(&protoflags, conn);
+ if(result != CURLE_OK)
+ return result;
+ break;
default:
failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
return CURLE_SSL_CONNECT_ERROR;
diff --git a/Utilities/cmcurl/lib/vtls/gtls.c b/Utilities/cmcurl/lib/vtls/gtls.c
index 0e308cb79f..0230778e2b 100644
--- a/Utilities/cmcurl/lib/vtls/gtls.c
+++ b/Utilities/cmcurl/lib/vtls/gtls.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -92,11 +92,11 @@ static bool gtls_inited = FALSE;
# define GNUTLS_MAPS_WINSOCK_ERRORS 1
# endif
-# if (GNUTLS_VERSION_NUMBER >= 0x030200)
+# if HAVE_GNUTLS_ALPN_SET_PROTOCOLS
# define HAS_ALPN
# endif
-# if (GNUTLS_VERSION_NUMBER >= 0x03020d)
+# if HAVE_GNUTLS_OCSP_REQ_INIT
# define HAS_OCSP
# endif
@@ -278,7 +278,7 @@ static CURLcode handshake(struct connectdata *conn,
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
gnutls_session_t session = conn->ssl[sockindex].session;
curl_socket_t sockfd = conn->sock[sockindex];
- long timeout_ms;
+ time_t timeout_ms;
int rc;
int what;
@@ -314,7 +314,7 @@ static CURLcode handshake(struct connectdata *conn,
return CURLE_OK;
else if(timeout_ms) {
/* timeout */
- failf(data, "SSL connection timeout at %ld", timeout_ms);
+ failf(data, "SSL connection timeout at %ld", (long)timeout_ms);
return CURLE_OPERATION_TIMEDOUT;
}
}
@@ -375,11 +375,106 @@ static gnutls_x509_crt_fmt_t do_file_type(const char *type)
return -1;
}
+#ifndef USE_GNUTLS_PRIORITY_SET_DIRECT
+static CURLcode
+set_ssl_version_min_max(int *list, size_t list_size, struct connectdata *conn)
+{
+ struct Curl_easy *data = conn->data;
+ long ssl_version = SSL_CONN_CONFIG(version);
+ long ssl_version_max = SSL_CONN_CONFIG(version_max);
+ long i = ssl_version;
+ long protocol_priority_idx = 0;
+
+ switch(ssl_version_max) {
+ case CURL_SSLVERSION_MAX_NONE:
+ ssl_version_max = ssl_version << 16;
+ break;
+ case CURL_SSLVERSION_MAX_DEFAULT:
+ ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
+ break;
+ }
+
+ for(; i <= (ssl_version_max >> 16) &&
+ protocol_priority_idx < list_size; ++i) {
+ switch(i) {
+ case CURL_SSLVERSION_TLSv1_0:
+ protocol_priority[protocol_priority_idx++] = GNUTLS_TLS1_0;
+ break;
+ case CURL_SSLVERSION_TLSv1_1:
+ protocol_priority[protocol_priority_idx++] = GNUTLS_TLS1_1;
+ break;
+ case CURL_SSLVERSION_TLSv1_2:
+ protocol_priority[protocol_priority_idx++] = GNUTLS_TLS1_2;
+ break;
+ case CURL_SSLVERSION_TLSv1_3:
+ failf(data, "GnuTLS: TLS 1.3 is not yet supported");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+ return CURLE_OK;
+}
+#else
+#define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509"
+/* If GnuTLS was compiled without support for SRP it will error out if SRP is
+ requested in the priority string, so treat it specially
+ */
+#define GNUTLS_SRP "+SRP"
+
+static CURLcode
+set_ssl_version_min_max(const char **prioritylist, struct connectdata *conn)
+{
+ struct Curl_easy *data = conn->data;
+ long ssl_version = SSL_CONN_CONFIG(version);
+ long ssl_version_max = SSL_CONN_CONFIG(version_max);
+ if(ssl_version == CURL_SSLVERSION_TLSv1_3 ||
+ ssl_version_max == CURL_SSLVERSION_MAX_TLSv1_3) {
+ failf(data, "GnuTLS: TLS 1.3 is not yet supported");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ if(ssl_version_max == CURL_SSLVERSION_MAX_NONE) {
+ ssl_version_max = ssl_version << 16;
+ }
+ switch(ssl_version | ssl_version_max) {
+ case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_0:
+ *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
+ "+VERS-TLS1.0:" GNUTLS_SRP;
+ return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_1:
+ *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
+ "+VERS-TLS1.0:+VERS-TLS1.1:" GNUTLS_SRP;
+ return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_2:
+ case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_DEFAULT:
+ *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
+ "+VERS-TLS1.0:+VERS-TLS1.1:+VERS-TLS1.2:" GNUTLS_SRP;
+ return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_1:
+ *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
+ "+VERS-TLS1.1:" GNUTLS_SRP;
+ return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_2:
+ case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_DEFAULT:
+ *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
+ "+VERS-TLS1.1:+VERS-TLS1.2:" GNUTLS_SRP;
+ return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_2:
+ case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_DEFAULT:
+ *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
+ "+VERS-TLS1.2:" GNUTLS_SRP;
+ return CURLE_OK;
+ }
+
+ failf(data, "GnuTLS: cannot set ssl protocol");
+ return CURLE_SSL_CONNECT_ERROR;
+}
+#endif
+
static CURLcode
gtls_connect_step1(struct connectdata *conn,
int sockindex)
{
struct Curl_easy *data = conn->data;
+ unsigned int init_flags;
gnutls_session_t session;
int rc;
bool sni = TRUE; /* default is SNI enabled */
@@ -405,13 +500,8 @@ gtls_connect_step1(struct connectdata *conn,
GNUTLS_CIPHER_3DES_CBC,
};
static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 };
- static int protocol_priority[] = { 0, 0, 0, 0 };
+ int protocol_priority[] = { 0, 0, 0, 0 };
#else
-#define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509"
-/* If GnuTLS was compiled without support for SRP it will error out if SRP is
- requested in the priority string, so treat it specially
- */
-#define GNUTLS_SRP "+SRP"
const char *prioritylist;
const char *err = NULL;
#endif
@@ -526,7 +616,14 @@ gtls_connect_step1(struct connectdata *conn,
}
/* Initialize TLS session as a client */
- rc = gnutls_init(&conn->ssl[sockindex].session, GNUTLS_CLIENT);
+ init_flags = GNUTLS_CLIENT;
+
+#if defined(GNUTLS_NO_TICKETS)
+ /* Disable TLS session tickets */
+ init_flags |= GNUTLS_NO_TICKETS;
+#endif
+
+ rc = gnutls_init(&conn->ssl[sockindex].session, init_flags);
if(rc != GNUTLS_E_SUCCESS) {
failf(data, "gnutls_init() failed: %d", rc);
return CURLE_SSL_CONNECT_ERROR;
@@ -568,7 +665,7 @@ gtls_connect_step1(struct connectdata *conn,
return CURLE_SSL_CONNECT_ERROR;
}
- switch(SSL_CONN_CONFIG(version) {
+ switch(SSL_CONN_CONFIG(version)) {
case CURL_SSLVERSION_SSLv3:
protocol_priority[0] = GNUTLS_SSL3;
break;
@@ -579,17 +676,16 @@ gtls_connect_step1(struct connectdata *conn,
protocol_priority[2] = GNUTLS_TLS1_2;
break;
case CURL_SSLVERSION_TLSv1_0:
- protocol_priority[0] = GNUTLS_TLS1_0;
- break;
case CURL_SSLVERSION_TLSv1_1:
- protocol_priority[0] = GNUTLS_TLS1_1;
- break;
case CURL_SSLVERSION_TLSv1_2:
- protocol_priority[0] = GNUTLS_TLS1_2;
- break;
case CURL_SSLVERSION_TLSv1_3:
- failf(data, "GnuTLS: TLS 1.3 is not yet supported");
- return CURLE_SSL_CONNECT_ERROR;
+ {
+ CURLcode result = set_ssl_version_min_max(protocol_priority,
+ sizeof(protocol_priority)/sizeof(protocol_priority[0]), conn);
+ if(result != CURLE_OK)
+ return result;
+ break;
+ }
case CURL_SSLVERSION_SSLv2:
failf(data, "GnuTLS does not support SSLv2");
return CURLE_SSL_CONNECT_ERROR;
@@ -617,20 +713,15 @@ gtls_connect_step1(struct connectdata *conn,
prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:" GNUTLS_SRP;
break;
case CURL_SSLVERSION_TLSv1_0:
- prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
- "+VERS-TLS1.0:" GNUTLS_SRP;
- break;
case CURL_SSLVERSION_TLSv1_1:
- prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
- "+VERS-TLS1.1:" GNUTLS_SRP;
- break;
case CURL_SSLVERSION_TLSv1_2:
- prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
- "+VERS-TLS1.2:" GNUTLS_SRP;
- break;
case CURL_SSLVERSION_TLSv1_3:
- failf(data, "GnuTLS: TLS 1.3 is not yet supported");
- return CURLE_SSL_CONNECT_ERROR;
+ {
+ CURLcode result = set_ssl_version_min_max(&prioritylist, conn);
+ if(result != CURLE_OK)
+ return result;
+ break;
+ }
case CURL_SSLVERSION_SSLv2:
failf(data, "GnuTLS does not support SSLv2");
return CURLE_SSL_CONNECT_ERROR;
@@ -782,7 +873,7 @@ gtls_connect_step1(struct connectdata *conn,
/* This might be a reconnect, so we check for a session ID in the cache
to speed up things */
- if(data->set.general_ssl.sessionid) {
+ if(SSL_SET_OPTION(primary.sessionid)) {
void *ssl_sessionid;
size_t ssl_idsize;
@@ -882,7 +973,9 @@ gtls_connect_step3(struct connectdata *conn,
gnutls_datum_t proto;
#endif
CURLcode result = CURLE_OK;
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
gnutls_protocol_t version = gnutls_protocol_get_version(session);
+#endif
const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
conn->host.name;
@@ -1311,7 +1404,7 @@ gtls_connect_step3(struct connectdata *conn,
conn->recv[sockindex] = gtls_recv;
conn->send[sockindex] = gtls_send;
- if(data->set.general_ssl.sessionid) {
+ if(SSL_SET_OPTION(primary.sessionid)) {
/* we always unconditionally get the session id here, as even if we
already got it from the cache and asked to use it in the connection, it
might've been rejected and then a new one is in use now and we need to
@@ -1625,19 +1718,21 @@ static int Curl_gtls_seed(struct Curl_easy *data)
#endif
/* data might be NULL! */
-int Curl_gtls_random(struct Curl_easy *data,
- unsigned char *entropy,
- size_t length)
+CURLcode Curl_gtls_random(struct Curl_easy *data,
+ unsigned char *entropy,
+ size_t length)
{
#if defined(USE_GNUTLS_NETTLE)
+ int rc;
(void)data;
- gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length);
+ rc = gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length);
+ return rc?CURLE_FAILED_INIT:CURLE_OK;
#elif defined(USE_GNUTLS)
if(data)
Curl_gtls_seed(data); /* Initiate the seed if not already done */
gcry_randomize(entropy, length, GCRY_STRONG_RANDOM);
#endif
- return 0;
+ return CURLE_OK;
}
void Curl_gtls_md5sum(unsigned char *tmp, /* input */
diff --git a/Utilities/cmcurl/lib/vtls/gtls.h b/Utilities/cmcurl/lib/vtls/gtls.h
index 65312017ed..462c04853e 100644
--- a/Utilities/cmcurl/lib/vtls/gtls.h
+++ b/Utilities/cmcurl/lib/vtls/gtls.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -43,9 +43,9 @@ void Curl_gtls_close(struct connectdata *conn, int sockindex);
void Curl_gtls_session_free(void *ptr);
size_t Curl_gtls_version(char *buffer, size_t size);
int Curl_gtls_shutdown(struct connectdata *conn, int sockindex);
-int Curl_gtls_random(struct Curl_easy *data,
- unsigned char *entropy,
- size_t length);
+CURLcode Curl_gtls_random(struct Curl_easy *data,
+ unsigned char *entropy,
+ size_t length);
void Curl_gtls_md5sum(unsigned char *tmp, /* input */
size_t tmplen,
unsigned char *md5sum, /* output */
diff --git a/Utilities/cmcurl/lib/vtls/mbedtls.c b/Utilities/cmcurl/lib/vtls/mbedtls.c
index 8bcaddd25a..3ffa95752c 100644
--- a/Utilities/cmcurl/lib/vtls/mbedtls.c
+++ b/Utilities/cmcurl/lib/vtls/mbedtls.c
@@ -6,7 +6,7 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com>
- * Copyright (C) 2012 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -157,6 +157,71 @@ const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_fr =
static Curl_recv mbed_recv;
static Curl_send mbed_send;
+static CURLcode mbedtls_version_from_curl(int *mbedver, long version)
+{
+ switch(version) {
+ case CURL_SSLVERSION_TLSv1_0:
+ *mbedver = MBEDTLS_SSL_MINOR_VERSION_1;
+ return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_1:
+ *mbedver = MBEDTLS_SSL_MINOR_VERSION_2;
+ return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_2:
+ *mbedver = MBEDTLS_SSL_MINOR_VERSION_3;
+ return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_3:
+ break;
+ }
+ return CURLE_SSL_CONNECT_ERROR;
+}
+
+static CURLcode
+set_ssl_version_min_max(struct connectdata *conn, int sockindex)
+{
+ struct Curl_easy *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ int mbedtls_ver_min = MBEDTLS_SSL_MINOR_VERSION_1;
+ int mbedtls_ver_max = MBEDTLS_SSL_MINOR_VERSION_1;
+ long ssl_version = SSL_CONN_CONFIG(version);
+ long ssl_version_max = SSL_CONN_CONFIG(version_max);
+ CURLcode result = CURLE_OK;
+
+ switch(ssl_version) {
+ case CURL_SSLVERSION_DEFAULT:
+ case CURL_SSLVERSION_TLSv1:
+ ssl_version = CURL_SSLVERSION_TLSv1_0;
+ ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
+ break;
+ }
+
+ switch(ssl_version_max) {
+ case CURL_SSLVERSION_MAX_NONE:
+ ssl_version_max = ssl_version << 16;
+ break;
+ case CURL_SSLVERSION_MAX_DEFAULT:
+ ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
+ break;
+ }
+
+ result = mbedtls_version_from_curl(&mbedtls_ver_min, ssl_version);
+ if(result) {
+ failf(data, "unsupported min version passed via CURLOPT_SSLVERSION");
+ return result;
+ }
+ result = mbedtls_version_from_curl(&mbedtls_ver_max, ssl_version_max >> 16);
+ if(result) {
+ failf(data, "unsupported max version passed via CURLOPT_SSLVERSION");
+ return result;
+ }
+
+ mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
+ mbedtls_ver_min);
+ mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
+ mbedtls_ver_max);
+
+ return result;
+}
+
static CURLcode
mbed_connect_step1(struct connectdata *conn,
int sockindex)
@@ -333,29 +398,15 @@ mbed_connect_step1(struct connectdata *conn,
infof(data, "mbedTLS: Set SSL version to SSLv3\n");
break;
case CURL_SSLVERSION_TLSv1_0:
- mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
- MBEDTLS_SSL_MINOR_VERSION_1);
- mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
- MBEDTLS_SSL_MINOR_VERSION_1);
- infof(data, "mbedTLS: Set SSL version to TLS 1.0\n");
- break;
case CURL_SSLVERSION_TLSv1_1:
- mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
- MBEDTLS_SSL_MINOR_VERSION_2);
- mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
- MBEDTLS_SSL_MINOR_VERSION_2);
- infof(data, "mbedTLS: Set SSL version to TLS 1.1\n");
- break;
case CURL_SSLVERSION_TLSv1_2:
- mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
- MBEDTLS_SSL_MINOR_VERSION_3);
- mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
- MBEDTLS_SSL_MINOR_VERSION_3);
- infof(data, "mbedTLS: Set SSL version to TLS 1.2\n");
- break;
case CURL_SSLVERSION_TLSv1_3:
- failf(data, "mbedTLS: TLS 1.3 is not yet supported");
- return CURLE_SSL_CONNECT_ERROR;
+ {
+ CURLcode result = set_ssl_version_min_max(conn, sockindex);
+ if(result != CURLE_OK)
+ return result;
+ break;
+ }
default:
failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
return CURLE_SSL_CONNECT_ERROR;
@@ -373,8 +424,13 @@ mbed_connect_step1(struct connectdata *conn,
mbedtls_ssl_conf_ciphersuites(&connssl->config,
mbedtls_ssl_list_ciphersuites());
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+ mbedtls_ssl_conf_session_tickets(&connssl->config,
+ MBEDTLS_SSL_SESSION_TICKETS_DISABLED);
+#endif
+
/* Check if there's a cached ID we can/should use here! */
- if(data->set.general_ssl.sessionid) {
+ if(SSL_SET_OPTION(primary.sessionid)) {
void *old_session = NULL;
Curl_ssl_sessionid_lock(conn);
@@ -439,6 +495,16 @@ mbed_connect_step1(struct connectdata *conn,
mbedtls_debug_set_threshold(4);
#endif
+ /* give application a chance to interfere with mbedTLS set up. */
+ if(data->set.ssl.fsslctx) {
+ ret = (*data->set.ssl.fsslctx)(data, &connssl->config,
+ data->set.ssl.fsslctxp);
+ if(ret) {
+ failf(data, "error signaled by ssl ctx callback");
+ return ret;
+ }
+ }
+
connssl->connecting_state = ssl_connect_2;
return CURLE_OK;
@@ -618,7 +684,7 @@ mbed_connect_step3(struct connectdata *conn,
DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
- if(data->set.general_ssl.sessionid) {
+ if(SSL_SET_OPTION(primary.sessionid)) {
int ret;
mbedtls_ssl_session *our_ssl_sessionid;
void *old_ssl_sessionid = NULL;
@@ -631,6 +697,7 @@ mbed_connect_step3(struct connectdata *conn,
ret = mbedtls_ssl_get_session(&connssl->ssl, our_ssl_sessionid);
if(ret) {
+ free(our_ssl_sessionid);
failf(data, "mbedtls_ssl_get_session returned -0x%x", -ret);
return CURLE_SSL_CONNECT_ERROR;
}
@@ -729,6 +796,55 @@ size_t Curl_mbedtls_version(char *buffer, size_t size)
(version>>16)&0xff, (version>>8)&0xff);
}
+CURLcode Curl_mbedtls_random(struct Curl_easy *data, unsigned char *entropy,
+ size_t length)
+{
+#if defined(MBEDTLS_CTR_DRBG_C)
+ int ret = -1;
+ char errorbuf[128];
+ mbedtls_entropy_context ctr_entropy;
+ mbedtls_ctr_drbg_context ctr_drbg;
+ mbedtls_entropy_init(&ctr_entropy);
+ mbedtls_ctr_drbg_init(&ctr_drbg);
+ errorbuf[0]=0;
+
+ ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func,
+ &ctr_entropy, NULL, 0);
+
+ if(ret) {
+#ifdef MBEDTLS_ERROR_C
+ mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
+#endif /* MBEDTLS_ERROR_C */
+ failf(data, "Failed - mbedTLS: ctr_drbg_seed returned (-0x%04X) %s\n",
+ -ret, errorbuf);
+ }
+ else {
+ ret = mbedtls_ctr_drbg_random(&ctr_drbg, entropy, length);
+
+ if(ret) {
+#ifdef MBEDTLS_ERROR_C
+ mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
+#endif /* MBEDTLS_ERROR_C */
+ failf(data, "mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n",
+ -ret, errorbuf);
+ }
+ }
+
+ mbedtls_ctr_drbg_free(&ctr_drbg);
+ mbedtls_entropy_free(&ctr_entropy);
+
+ return ret == 0 ? CURLE_OK : CURLE_FAILED_INIT;
+#elif defined(MBEDTLS_HAVEGE_C)
+ mbedtls_havege_state hs;
+ mbedtls_havege_init(&hs);
+ mbedtls_havege_random(&hs, entropy, length);
+ mbedtls_havege_free(&hs);
+ return CURLE_OK;
+#else
+ return CURLE_NOT_BUILT_IN;
+#endif
+}
+
static CURLcode
mbed_connect_common(struct connectdata *conn,
int sockindex,
@@ -883,9 +999,7 @@ void Curl_mbedtls_cleanup(void)
int Curl_mbedtls_data_pending(const struct connectdata *conn, int sockindex)
{
- mbedtls_ssl_context *ssl =
- (mbedtls_ssl_context *)&conn->ssl[sockindex].ssl;
- return ssl->in_msglen != 0;
+ return mbedtls_ssl_get_bytes_avail(&conn->ssl[sockindex].ssl) != 0;
}
#endif /* USE_MBEDTLS */
diff --git a/Utilities/cmcurl/lib/vtls/mbedtls.h b/Utilities/cmcurl/lib/vtls/mbedtls.h
index 1021d54616..71d17a491c 100644
--- a/Utilities/cmcurl/lib/vtls/mbedtls.h
+++ b/Utilities/cmcurl/lib/vtls/mbedtls.h
@@ -50,9 +50,15 @@ void Curl_mbedtls_session_free(void *ptr);
size_t Curl_mbedtls_version(char *buffer, size_t size);
int Curl_mbedtls_shutdown(struct connectdata *conn, int sockindex);
+CURLcode Curl_mbedtls_random(struct Curl_easy *data, unsigned char *entropy,
+ size_t length);
+
/* this backends supports CURLOPT_PINNEDPUBLICKEY */
#define have_curlssl_pinnedpubkey 1
+/* this backend supports CURLOPT_SSL_CTX_* */
+#define have_curlssl_ssl_ctx 1
+
/* API setup for mbedTLS */
#define curlssl_init() Curl_mbedtls_init()
#define curlssl_cleanup() Curl_mbedtls_cleanup()
@@ -70,11 +76,7 @@ int Curl_mbedtls_shutdown(struct connectdata *conn, int sockindex);
#define curlssl_data_pending(x,y) Curl_mbedtls_data_pending(x, y)
#define CURL_SSL_BACKEND CURLSSLBACKEND_MBEDTLS
#define curlssl_sha256sum(a,b,c,d) mbedtls_sha256(a,b,c,0)
-
-/* This might cause libcurl to use a weeker random!
- TODO: implement proper use of Polarssl's CTR-DRBG or HMAC-DRBG and use that
-*/
-#define curlssl_random(x,y,z) (x=x, y=y, z=z, CURLE_NOT_BUILT_IN)
+#define curlssl_random(x,y,z) Curl_mbedtls_random(x, y, z)
#endif /* USE_MBEDTLS */
#endif /* HEADER_CURL_MBEDTLS_H */
diff --git a/Utilities/cmcurl/lib/vtls/nss.c b/Utilities/cmcurl/lib/vtls/nss.c
index ba8d58260b..89a16d3feb 100644
--- a/Utilities/cmcurl/lib/vtls/nss.c
+++ b/Utilities/cmcurl/lib/vtls/nss.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -56,7 +56,8 @@
#include <base64.h>
#include <cert.h>
#include <prerror.h>
-#include <keyhi.h> /* for SECKEY_DestroyPublicKey() */
+#include <keyhi.h> /* for SECKEY_DestroyPublicKey() */
+#include <private/pprio.h> /* for PR_ImportTCPSocket */
#define NSSVERNUM ((NSS_VMAJOR<<16)|(NSS_VMINOR<<8)|NSS_VPATCH)
@@ -77,11 +78,10 @@
/* enough to fit the string "PEM Token #[0|1]" */
#define SLOTSIZE 13
-PRFileDesc *PR_ImportTCPSocket(PRInt32 osfd);
static PRLock *nss_initlock = NULL;
static PRLock *nss_crllock = NULL;
static PRLock *nss_findslot_lock = NULL;
-static struct curl_llist *nss_crl_list = NULL;
+static struct curl_llist nss_crl_list;
static NSSInitContext *nss_context = NULL;
static volatile int initialized = 0;
@@ -365,9 +365,9 @@ static char *dup_nickname(struct Curl_easy *data, const char *str)
static PK11SlotInfo* nss_find_slot_by_name(const char *slot_name)
{
PK11SlotInfo *slot;
- PR_Lock(nss_initlock);
+ PR_Lock(nss_findslot_lock);
slot = PK11_FindSlotByName(slot_name);
- PR_Unlock(nss_initlock);
+ PR_Unlock(nss_findslot_lock);
return slot;
}
@@ -401,7 +401,7 @@ static CURLcode nss_create_object(struct ssl_connect_data *ssl,
PK11_SETATTRS(attrs, attr_cnt, CKA_CLASS, &obj_class, sizeof(obj_class));
PK11_SETATTRS(attrs, attr_cnt, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL));
PK11_SETATTRS(attrs, attr_cnt, CKA_LABEL, (unsigned char *)filename,
- strlen(filename) + 1);
+ (CK_ULONG)strlen(filename) + 1);
if(CKO_CERTIFICATE == obj_class) {
CK_BBOOL *pval = (cacert) ? (&cktrue) : (&ckfalse);
@@ -413,7 +413,7 @@ static CURLcode nss_create_object(struct ssl_connect_data *ssl,
if(!obj)
return result;
- if(!Curl_llist_insert_next(ssl->obj_list, ssl->obj_list->tail, obj)) {
+ if(!Curl_llist_insert_next(&ssl->obj_list, ssl->obj_list.tail, obj)) {
PK11_DestroyGenericObject(obj);
return CURLE_OUT_OF_MEMORY;
}
@@ -496,7 +496,7 @@ static CURLcode nss_cache_crl(SECItem *crl_der)
PR_Lock(nss_crllock);
/* store the CRL item so that we can free it in Curl_nss_cleanup() */
- if(!Curl_llist_insert_next(nss_crl_list, nss_crl_list->tail, crl_der)) {
+ if(!Curl_llist_insert_next(&nss_crl_list, nss_crl_list.tail, crl_der)) {
SECITEM_FreeItem(crl_der, PR_TRUE);
PR_Unlock(nss_crllock);
return CURLE_OUT_OF_MEMORY;
@@ -1227,9 +1227,7 @@ static CURLcode nss_init(struct Curl_easy *data)
return CURLE_OK;
/* list of all CRL items we need to destroy in Curl_nss_cleanup() */
- nss_crl_list = Curl_llist_alloc(nss_destroy_crl_item);
- if(!nss_crl_list)
- return CURLE_OUT_OF_MEMORY;
+ Curl_llist_init(&nss_crl_list, nss_destroy_crl_item);
/* First we check if $SSL_DIR points to a valid dir */
cert_dir = getenv("SSL_DIR");
@@ -1336,8 +1334,7 @@ void Curl_nss_cleanup(void)
}
/* destroy all CRL items */
- Curl_llist_destroy(nss_crl_list, NULL);
- nss_crl_list = NULL;
+ Curl_llist_destroy(&nss_crl_list, NULL);
PR_Unlock(nss_initlock);
@@ -1385,8 +1382,7 @@ static void nss_close(struct ssl_connect_data *connssl)
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;
+ Curl_llist_destroy(&connssl->obj_list, NULL);
connssl->obj_clicert = NULL;
if(connssl->handle) {
@@ -1512,78 +1508,108 @@ static CURLcode nss_load_ca_certificates(struct connectdata *conn,
return CURLE_OK;
}
-static CURLcode nss_init_sslver(SSLVersionRange *sslver,
- struct Curl_easy *data,
- struct connectdata *conn)
+static CURLcode nss_sslver_from_curl(PRUint16 *nssver, long version)
{
- switch(SSL_CONN_CONFIG(version)) {
- case CURL_SSLVERSION_DEFAULT:
- /* map CURL_SSLVERSION_DEFAULT to NSS default */
- if(SSL_VersionRangeGetDefault(ssl_variant_stream, sslver) != SECSuccess)
- return CURLE_SSL_CONNECT_ERROR;
- /* ... but make sure we use at least TLSv1.0 according to libcurl API */
- if(sslver->min < SSL_LIBRARY_VERSION_TLS_1_0)
- sslver->min = SSL_LIBRARY_VERSION_TLS_1_0;
- return CURLE_OK;
-
+ switch(version) {
case CURL_SSLVERSION_TLSv1:
- sslver->min = SSL_LIBRARY_VERSION_TLS_1_0;
/* TODO: set sslver->max to SSL_LIBRARY_VERSION_TLS_1_3 once stable */
#ifdef SSL_LIBRARY_VERSION_TLS_1_2
- sslver->max = SSL_LIBRARY_VERSION_TLS_1_2;
+ *nssver = SSL_LIBRARY_VERSION_TLS_1_2;
#elif defined SSL_LIBRARY_VERSION_TLS_1_1
- sslver->max = SSL_LIBRARY_VERSION_TLS_1_1;
+ *nssver = SSL_LIBRARY_VERSION_TLS_1_1;
#else
- sslver->max = SSL_LIBRARY_VERSION_TLS_1_0;
+ *nssver = SSL_LIBRARY_VERSION_TLS_1_0;
#endif
return CURLE_OK;
case CURL_SSLVERSION_SSLv2:
- sslver->min = SSL_LIBRARY_VERSION_2;
- sslver->max = SSL_LIBRARY_VERSION_2;
+ *nssver = SSL_LIBRARY_VERSION_2;
return CURLE_OK;
case CURL_SSLVERSION_SSLv3:
- sslver->min = SSL_LIBRARY_VERSION_3_0;
- sslver->max = SSL_LIBRARY_VERSION_3_0;
+ *nssver = SSL_LIBRARY_VERSION_3_0;
return CURLE_OK;
case CURL_SSLVERSION_TLSv1_0:
- sslver->min = SSL_LIBRARY_VERSION_TLS_1_0;
- sslver->max = SSL_LIBRARY_VERSION_TLS_1_0;
+ *nssver = SSL_LIBRARY_VERSION_TLS_1_0;
return CURLE_OK;
case CURL_SSLVERSION_TLSv1_1:
#ifdef SSL_LIBRARY_VERSION_TLS_1_1
- sslver->min = SSL_LIBRARY_VERSION_TLS_1_1;
- sslver->max = SSL_LIBRARY_VERSION_TLS_1_1;
+ *nssver = SSL_LIBRARY_VERSION_TLS_1_1;
return CURLE_OK;
+#else
+ return CURLE_SSL_CONNECT_ERROR;
#endif
- break;
case CURL_SSLVERSION_TLSv1_2:
#ifdef SSL_LIBRARY_VERSION_TLS_1_2
- sslver->min = SSL_LIBRARY_VERSION_TLS_1_2;
- sslver->max = SSL_LIBRARY_VERSION_TLS_1_2;
+ *nssver = SSL_LIBRARY_VERSION_TLS_1_2;
return CURLE_OK;
+#else
+ return CURLE_SSL_CONNECT_ERROR;
#endif
- break;
case CURL_SSLVERSION_TLSv1_3:
#ifdef SSL_LIBRARY_VERSION_TLS_1_3
- sslver->min = SSL_LIBRARY_VERSION_TLS_1_3;
- sslver->max = SSL_LIBRARY_VERSION_TLS_1_3;
+ *nssver = SSL_LIBRARY_VERSION_TLS_1_3;
return CURLE_OK;
+#else
+ return CURLE_SSL_CONNECT_ERROR;
#endif
- break;
default:
- failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
return CURLE_SSL_CONNECT_ERROR;
}
+}
+
+static CURLcode nss_init_sslver(SSLVersionRange *sslver,
+ struct Curl_easy *data,
+ struct connectdata *conn)
+{
+ CURLcode result;
+ const long min = SSL_CONN_CONFIG(version);
+ const long max = SSL_CONN_CONFIG(version_max);
+
+ /* map CURL_SSLVERSION_DEFAULT to NSS default */
+ if(min == CURL_SSLVERSION_DEFAULT || max == CURL_SSLVERSION_MAX_DEFAULT) {
+ /* map CURL_SSLVERSION_DEFAULT to NSS default */
+ if(SSL_VersionRangeGetDefault(ssl_variant_stream, sslver) != SECSuccess)
+ return CURLE_SSL_CONNECT_ERROR;
+ /* ... but make sure we use at least TLSv1.0 according to libcurl API */
+ if(sslver->min < SSL_LIBRARY_VERSION_TLS_1_0)
+ sslver->min = SSL_LIBRARY_VERSION_TLS_1_0;
+ }
+
+ switch(min) {
+ case CURL_SSLVERSION_DEFAULT:
+ break;
+ case CURL_SSLVERSION_TLSv1:
+ sslver->min = SSL_LIBRARY_VERSION_TLS_1_0;
+ break;
+ default:
+ result = nss_sslver_from_curl(&sslver->min, min);
+ if(result) {
+ failf(data, "unsupported min version passed via CURLOPT_SSLVERSION");
+ return result;
+ }
+ if(max == CURL_SSLVERSION_MAX_NONE)
+ sslver->max = sslver->min;
+ }
+
+ switch(max) {
+ case CURL_SSLVERSION_MAX_NONE:
+ case CURL_SSLVERSION_MAX_DEFAULT:
+ break;
+ default:
+ result = nss_sslver_from_curl(&sslver->max, max >> 16);
+ if(result) {
+ failf(data, "unsupported max version passed via CURLOPT_SSLVERSION");
+ return result;
+ }
+ }
- failf(data, "TLS minor version cannot be set");
- return CURLE_SSL_CONNECT_ERROR;
+ return CURLE_OK;
}
static CURLcode nss_fail_connect(struct ssl_connect_data *connssl,
@@ -1606,19 +1632,19 @@ static CURLcode nss_fail_connect(struct ssl_connect_data *connssl,
}
/* cleanup on connection failure */
- Curl_llist_destroy(connssl->obj_list, NULL);
- connssl->obj_list = NULL;
+ Curl_llist_destroy(&connssl->obj_list, NULL);
return curlerr;
}
-/* Switch the SSL socket into non-blocking mode. */
-static CURLcode nss_set_nonblock(struct ssl_connect_data *connssl,
- struct Curl_easy *data)
+/* Switch the SSL socket into blocking or non-blocking mode. */
+static CURLcode nss_set_blocking(struct ssl_connect_data *connssl,
+ struct Curl_easy *data,
+ bool blocking)
{
static PRSocketOptionData sock_opt;
sock_opt.option = PR_SockOpt_Nonblocking;
- sock_opt.value.non_blocking = PR_TRUE;
+ sock_opt.value.non_blocking = !blocking;
if(PR_SetSocketOption(connssl->handle, &sock_opt) != PR_SUCCESS)
return nss_fail_connect(connssl, data, CURLE_SSL_CONNECT_ERROR);
@@ -1647,9 +1673,7 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
connssl->data = data;
/* list of all NSS objects we need to destroy in Curl_nss_close() */
- connssl->obj_list = Curl_llist_alloc(nss_destroy_object);
- if(!connssl->obj_list)
- return CURLE_OUT_OF_MEMORY;
+ Curl_llist_init(&connssl->obj_list, nss_destroy_object);
/* FIXME. NSS doesn't support multiple databases open at the same time. */
PR_Lock(nss_initlock);
@@ -1696,7 +1720,7 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
goto error;
/* do not use SSL cache if disabled or we are not going to verify peer */
- ssl_no_cache = (data->set.general_ssl.sessionid
+ ssl_no_cache = (SSL_SET_OPTION(primary.sessionid)
&& SSL_CONN_CONFIG(verifypeer)) ? PR_FALSE : PR_TRUE;
if(SSL_OptionSet(model, SSL_NO_CACHE, ssl_no_cache) != SECSuccess)
goto error;
@@ -1746,9 +1770,12 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
if(SSL_HandshakeCallback(model, HandshakeCallback, conn) != SECSuccess)
goto error;
- if(SSL_CONN_CONFIG(verifypeer)) {
+ {
const CURLcode rv = nss_load_ca_certificates(conn, sockindex);
- if(rv) {
+ if((rv == CURLE_SSL_CACERT_BADFILE) && !SSL_CONN_CONFIG(verifypeer))
+ /* not a fatal error because we are not going to verify the peer */
+ infof(data, "warning: CA certificates failed to load\n");
+ else if(rv) {
result = rv;
goto error;
}
@@ -1933,8 +1960,8 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
/* check timeout situation */
- const long time_left = Curl_timeleft(data, NULL, TRUE);
- if(time_left < 0L) {
+ const time_t time_left = Curl_timeleft(data, NULL, TRUE);
+ if(time_left < 0) {
failf(data, "timed out before SSL handshake");
result = CURLE_OPERATION_TIMEDOUT;
goto error;
@@ -2007,16 +2034,14 @@ static CURLcode nss_connect_common(struct connectdata *conn, int sockindex,
/* we do not expect CURLE_AGAIN from nss_setup_connect() */
return result;
- if(!blocking) {
- /* in non-blocking mode, set NSS non-blocking mode before handshake */
- result = nss_set_nonblock(connssl, data);
- if(result)
- return result;
- }
-
connssl->connecting_state = ssl_connect_2;
}
+ /* enable/disable blocking mode before handshake */
+ result = nss_set_blocking(connssl, data, blocking);
+ if(result)
+ return result;
+
result = nss_do_connect(conn, sockindex);
switch(result) {
case CURLE_OK:
@@ -2032,7 +2057,7 @@ static CURLcode nss_connect_common(struct connectdata *conn, int sockindex,
if(blocking) {
/* in blocking mode, set NSS non-blocking mode _after_ SSL handshake */
- result = nss_set_nonblock(connssl, data);
+ result = nss_set_blocking(connssl, data, /* blocking */ FALSE);
if(result)
return result;
}
@@ -2138,17 +2163,17 @@ int Curl_nss_seed(struct Curl_easy *data)
}
/* data might be NULL */
-int Curl_nss_random(struct Curl_easy *data,
- unsigned char *entropy,
- size_t length)
+CURLcode Curl_nss_random(struct Curl_easy *data,
+ unsigned char *entropy,
+ size_t length)
{
Curl_nss_seed(data); /* Initiate the seed if not already done */
if(SECSuccess != PK11_GenerateRandom(entropy, curlx_uztosi(length)))
/* signal a failure */
- return -1;
+ return CURLE_FAILED_INIT;
- return 0;
+ return CURLE_OK;
}
void Curl_nss_md5sum(unsigned char *tmp, /* input */
diff --git a/Utilities/cmcurl/lib/vtls/nssg.h b/Utilities/cmcurl/lib/vtls/nssg.h
index fd94003fb6..8c46929ff2 100644
--- a/Utilities/cmcurl/lib/vtls/nssg.h
+++ b/Utilities/cmcurl/lib/vtls/nssg.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -47,9 +47,9 @@ int Curl_nss_seed(struct Curl_easy *data);
/* initialize NSS library if not already */
CURLcode Curl_nss_force_init(struct Curl_easy *data);
-int Curl_nss_random(struct Curl_easy *data,
- unsigned char *entropy,
- size_t length);
+CURLcode Curl_nss_random(struct Curl_easy *data,
+ unsigned char *entropy,
+ size_t length);
void Curl_nss_md5sum(unsigned char *tmp, /* input */
size_t tmplen,
diff --git a/Utilities/cmcurl/lib/vtls/openssl.c b/Utilities/cmcurl/lib/vtls/openssl.c
index d92e71365f..58a014a4d7 100644
--- a/Utilities/cmcurl/lib/vtls/openssl.c
+++ b/Utilities/cmcurl/lib/vtls/openssl.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -55,7 +55,9 @@
#include <openssl/ssl.h>
#include <openssl/rand.h>
#include <openssl/x509v3.h>
+#ifndef OPENSSL_NO_DSA
#include <openssl/dsa.h>
+#endif
#include <openssl/dh.h>
#include <openssl/err.h>
#include <openssl/md5.h>
@@ -156,10 +158,56 @@ static unsigned long OpenSSL_version_num(void)
* Number of bytes to read from the random number seed file. This must be
* a finite value (because some entropy "files" like /dev/urandom have
* an infinite length), but must be large enough to provide enough
- * entopy to properly seed OpenSSL's PRNG.
+ * entropy to properly seed OpenSSL's PRNG.
*/
#define RAND_LOAD_LENGTH 1024
+static const char *SSL_ERROR_to_str(int err)
+{
+ switch(err) {
+ case SSL_ERROR_NONE:
+ return "SSL_ERROR_NONE";
+ case SSL_ERROR_SSL:
+ return "SSL_ERROR_SSL";
+ case SSL_ERROR_WANT_READ:
+ return "SSL_ERROR_WANT_READ";
+ case SSL_ERROR_WANT_WRITE:
+ return "SSL_ERROR_WANT_WRITE";
+ case SSL_ERROR_WANT_X509_LOOKUP:
+ return "SSL_ERROR_WANT_X509_LOOKUP";
+ case SSL_ERROR_SYSCALL:
+ return "SSL_ERROR_SYSCALL";
+ case SSL_ERROR_ZERO_RETURN:
+ return "SSL_ERROR_ZERO_RETURN";
+ case SSL_ERROR_WANT_CONNECT:
+ return "SSL_ERROR_WANT_CONNECT";
+ case SSL_ERROR_WANT_ACCEPT:
+ return "SSL_ERROR_WANT_ACCEPT";
+#if defined(SSL_ERROR_WANT_ASYNC)
+ case SSL_ERROR_WANT_ASYNC:
+ return "SSL_ERROR_WANT_ASYNC";
+#endif
+#if defined(SSL_ERROR_WANT_ASYNC_JOB)
+ case SSL_ERROR_WANT_ASYNC_JOB:
+ return "SSL_ERROR_WANT_ASYNC_JOB";
+#endif
+#if defined(SSL_ERROR_WANT_EARLY)
+ case SSL_ERROR_WANT_EARLY:
+ return "SSL_ERROR_WANT_EARLY";
+#endif
+ default:
+ return "SSL_ERROR unknown";
+ }
+}
+
+/* Return error string for last OpenSSL error
+ */
+static char *ossl_strerror(unsigned long error, char *buf, size_t size)
+{
+ ERR_error_string_n(error, buf, size);
+ return buf;
+}
+
static int passwd_callback(char *buf, int num, int encrypting,
void *global_passwd)
{
@@ -335,6 +383,7 @@ int cert_stuff(struct connectdata *conn,
char *key_passwd)
{
struct Curl_easy *data = conn->data;
+ char error_buffer[256];
int file_type = do_file_type(cert_type);
@@ -360,7 +409,8 @@ int cert_stuff(struct connectdata *conn,
"could not load PEM client certificate, " OSSL_PACKAGE
" error %s, "
"(no key found, wrong pass phrase, or wrong file format?)",
- ERR_error_string(ERR_get_error(), NULL) );
+ ossl_strerror(ERR_get_error(), error_buffer,
+ sizeof(error_buffer)) );
return 0;
}
break;
@@ -376,7 +426,8 @@ int cert_stuff(struct connectdata *conn,
"could not load ASN1 client certificate, " OSSL_PACKAGE
" error %s, "
"(no key found, wrong pass phrase, or wrong file format?)",
- ERR_error_string(ERR_get_error(), NULL) );
+ ossl_strerror(ERR_get_error(), error_buffer,
+ sizeof(error_buffer)) );
return 0;
}
break;
@@ -405,7 +456,8 @@ int cert_stuff(struct connectdata *conn,
0, &params, NULL, 1)) {
failf(data, "ssl engine cannot load client cert with id"
" '%s' [%s]", cert_file,
- ERR_error_string(ERR_get_error(), NULL));
+ ossl_strerror(ERR_get_error(), error_buffer,
+ sizeof(error_buffer)));
return 0;
}
@@ -461,7 +513,8 @@ int cert_stuff(struct connectdata *conn,
failf(data,
"could not parse PKCS12 file, check password, " OSSL_PACKAGE
" error %s",
- ERR_error_string(ERR_get_error(), NULL) );
+ ossl_strerror(ERR_get_error(), error_buffer,
+ sizeof(error_buffer)) );
PKCS12_free(p12);
return 0;
}
@@ -472,7 +525,8 @@ int cert_stuff(struct connectdata *conn,
failf(data,
"could not load PKCS12 client certificate, " OSSL_PACKAGE
" error %s",
- ERR_error_string(ERR_get_error(), NULL) );
+ ossl_strerror(ERR_get_error(), error_buffer,
+ sizeof(error_buffer)) );
goto fail;
}
@@ -493,21 +547,19 @@ int cert_stuff(struct connectdata *conn,
/*
* Note that sk_X509_pop() is used below to make sure the cert is
* removed from the stack properly before getting passed to
- * SSL_CTX_add_extra_chain_cert(). Previously we used
- * sk_X509_value() instead, but then we'd clean it in the subsequent
- * sk_X509_pop_free() call.
+ * SSL_CTX_add_extra_chain_cert(), which takes ownership. Previously
+ * we used sk_X509_value() instead, but then we'd clean it in the
+ * subsequent sk_X509_pop_free() call.
*/
X509 *x = sk_X509_pop(ca);
- if(!SSL_CTX_add_extra_chain_cert(ctx, x)) {
+ if(!SSL_CTX_add_client_CA(ctx, x)) {
X509_free(x);
- failf(data, "cannot add certificate to certificate chain");
+ failf(data, "cannot add certificate to client CA list");
goto fail;
}
- /* SSL_CTX_add_client_CA() seems to work with either sk_* function,
- * presumably because it duplicates what we pass to it.
- */
- if(!SSL_CTX_add_client_CA(ctx, x)) {
- failf(data, "cannot add certificate to client CA list");
+ if(!SSL_CTX_add_extra_chain_cert(ctx, x)) {
+ X509_free(x);
+ failf(data, "cannot add certificate to certificate chain");
goto fail;
}
}
@@ -541,6 +593,7 @@ int cert_stuff(struct connectdata *conn,
if(!key_file)
/* cert & key can only be in PEM case in the same file */
key_file=cert_file;
+ /* FALLTHROUGH */
case SSL_FILETYPE_ASN1:
if(SSL_CTX_use_PrivateKey_file(ctx, key_file, file_type) != 1) {
failf(data, "unable to set private key file: '%s' type %s",
@@ -664,17 +717,6 @@ static int x509_name_oneline(X509_NAME *a, char *buf, size_t size)
#endif
}
-/* Return error string for last OpenSSL error
- */
-static char *ossl_strerror(unsigned long error, char *buf, size_t size)
-{
- /* OpenSSL 0.9.6 and later has a function named
- ERR_error_string_n() that takes the size of the buffer as a
- third argument */
- ERR_error_string_n(error, buf, size);
- return buf;
-}
-
/**
* Global SSL init
*
@@ -776,7 +818,7 @@ int Curl_ossl_check_cxn(struct connectdata *conn)
(RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK);
if(nread == 0)
return 0; /* connection has been closed */
- else if(nread == 1)
+ if(nread == 1)
return 1; /* connection still in place */
else if(nread == -1) {
int err = SOCKERRNO;
@@ -981,8 +1023,10 @@ int Curl_ossl_shutdown(struct connectdata *conn, int sockindex)
default:
/* openssl/ssl.h says "look at error stack/return value/errno" */
sslerror = ERR_get_error();
- failf(conn->data, OSSL_PACKAGE " SSL read: %s, errno %d",
- ossl_strerror(sslerror, buf, sizeof(buf)),
+ failf(conn->data, OSSL_PACKAGE " SSL_read on shutdown: %s, errno %d",
+ (sslerror ?
+ ossl_strerror(sslerror, buf, sizeof(buf)) :
+ SSL_ERROR_to_str(err)),
SOCKERRNO);
done = 1;
break;
@@ -1609,7 +1653,7 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type,
#ifdef HAS_NPN
/*
- * in is a list of lenght prefixed strings. this function has to select
+ * in is a list of length prefixed strings. this function has to select
* the protocol we want to use from the list and write its string into out.
*/
@@ -1693,6 +1737,85 @@ get_ssl_version_txt(SSL *ssl)
return "unknown";
}
+static CURLcode
+set_ssl_version_min_max(long *ctx_options, struct connectdata *conn,
+ int sockindex)
+{
+#if (OPENSSL_VERSION_NUMBER < 0x1000100FL) || !defined(TLS1_3_VERSION)
+ /* convoluted #if condition just to avoid compiler warnings on unused
+ variable */
+ struct Curl_easy *data = conn->data;
+#endif
+ long ssl_version = SSL_CONN_CONFIG(version);
+ long ssl_version_max = SSL_CONN_CONFIG(version_max);
+
+ if(ssl_version_max == CURL_SSLVERSION_MAX_NONE) {
+ ssl_version_max = ssl_version << 16;
+ }
+
+ switch(ssl_version) {
+ case CURL_SSLVERSION_TLSv1_3:
+#ifdef TLS1_3_VERSION
+ {
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ SSL_CTX_set_max_proto_version(connssl->ctx, TLS1_3_VERSION);
+ *ctx_options |= SSL_OP_NO_TLSv1_2;
+ }
+#else
+ (void)sockindex;
+ failf(data, OSSL_PACKAGE " was built without TLS 1.3 support");
+ return CURLE_NOT_BUILT_IN;
+#endif
+ case CURL_SSLVERSION_TLSv1_2:
+#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
+ *ctx_options |= SSL_OP_NO_TLSv1_1;
+#else
+ failf(data, OSSL_PACKAGE " was built without TLS 1.2 support");
+ return CURLE_NOT_BUILT_IN;
+#endif
+ /* FALLTHROUGH */
+ case CURL_SSLVERSION_TLSv1_1:
+#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
+ *ctx_options |= SSL_OP_NO_TLSv1;
+#else
+ failf(data, OSSL_PACKAGE " was built without TLS 1.1 support");
+ return CURLE_NOT_BUILT_IN;
+#endif
+ /* FALLTHROUGH */
+ case CURL_SSLVERSION_TLSv1_0:
+ *ctx_options |= SSL_OP_NO_SSLv2;
+ *ctx_options |= SSL_OP_NO_SSLv3;
+ break;
+ }
+
+ switch(ssl_version_max) {
+ case CURL_SSLVERSION_MAX_TLSv1_0:
+#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
+ *ctx_options |= SSL_OP_NO_TLSv1_1;
+#endif
+ /* FALLTHROUGH */
+ case CURL_SSLVERSION_MAX_TLSv1_1:
+#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
+ *ctx_options |= SSL_OP_NO_TLSv1_2;
+#endif
+ /* FALLTHROUGH */
+ case CURL_SSLVERSION_MAX_TLSv1_2:
+ case CURL_SSLVERSION_MAX_DEFAULT:
+#ifdef TLS1_3_VERSION
+ *ctx_options |= SSL_OP_NO_TLSv1_3;
+#endif
+ break;
+ case CURL_SSLVERSION_MAX_TLSv1_3:
+#ifdef TLS1_3_VERSION
+ break;
+#else
+ failf(data, OSSL_PACKAGE " was built without TLS 1.3 support");
+ return CURLE_NOT_BUILT_IN;
+#endif
+ }
+ return CURLE_OK;
+}
+
static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
{
CURLcode result = CURLE_OK;
@@ -1702,9 +1825,11 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
X509_LOOKUP *lookup = NULL;
curl_socket_t sockfd = conn->sock[sockindex];
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- long ctx_options;
+ long ctx_options = 0;
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
bool sni;
+ const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+ conn->host.name;
#ifdef ENABLE_IPV6
struct in6_addr addr;
#else
@@ -1723,8 +1848,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
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;
+ char error_buffer[256];
DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
@@ -1790,7 +1914,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
if(!connssl->ctx) {
failf(data, "SSL: couldn't create a context: %s",
- ERR_error_string(ERR_peek_error(), NULL));
+ ossl_strerror(ERR_peek_error(), error_buffer, sizeof(error_buffer)));
return CURLE_OUT_OF_MEMORY;
}
@@ -1889,60 +2013,13 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
break;
case CURL_SSLVERSION_TLSv1_0:
- ctx_options |= SSL_OP_NO_SSLv2;
- ctx_options |= SSL_OP_NO_SSLv3;
-#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
- ctx_options |= SSL_OP_NO_TLSv1_1;
- ctx_options |= SSL_OP_NO_TLSv1_2;
-#ifdef TLS1_3_VERSION
- ctx_options |= SSL_OP_NO_TLSv1_3;
-#endif
-#endif
- break;
-
case CURL_SSLVERSION_TLSv1_1:
-#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
- ctx_options |= SSL_OP_NO_SSLv2;
- ctx_options |= SSL_OP_NO_SSLv3;
- ctx_options |= SSL_OP_NO_TLSv1;
- ctx_options |= SSL_OP_NO_TLSv1_2;
-#ifdef TLS1_3_VERSION
- ctx_options |= SSL_OP_NO_TLSv1_3;
-#endif
- break;
-#else
- failf(data, OSSL_PACKAGE " was built without TLS 1.1 support");
- return CURLE_NOT_BUILT_IN;
-#endif
-
case CURL_SSLVERSION_TLSv1_2:
-#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
- ctx_options |= SSL_OP_NO_SSLv2;
- ctx_options |= SSL_OP_NO_SSLv3;
- ctx_options |= SSL_OP_NO_TLSv1;
- ctx_options |= SSL_OP_NO_TLSv1_1;
-#ifdef TLS1_3_VERSION
- ctx_options |= SSL_OP_NO_TLSv1_3;
-#endif
- break;
-#else
- failf(data, OSSL_PACKAGE " was built without TLS 1.2 support");
- return CURLE_NOT_BUILT_IN;
-#endif
-
case CURL_SSLVERSION_TLSv1_3:
-#ifdef TLS1_3_VERSION
- SSL_CTX_set_max_proto_version(connssl->ctx, TLS1_3_VERSION);
- ctx_options |= SSL_OP_NO_SSLv2;
- ctx_options |= SSL_OP_NO_SSLv3;
- ctx_options |= SSL_OP_NO_TLSv1;
- ctx_options |= SSL_OP_NO_TLSv1_1;
- ctx_options |= SSL_OP_NO_TLSv1_2;
+ result = set_ssl_version_min_max(&ctx_options, conn, sockindex);
+ if(result != CURLE_OK)
+ return result;
break;
-#else
- failf(data, OSSL_PACKAGE " was built without TLS 1.3 support");
- return CURLE_NOT_BUILT_IN;
-#endif
case CURL_SSLVERSION_SSLv2:
#ifndef OPENSSL_NO_SSL2
@@ -2056,12 +2133,10 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
ssl_capath ? ssl_capath : "none");
return CURLE_SSL_CACERT_BADFILE;
}
- else {
- /* Just continue with a warning if no strict certificate verification
- is required. */
- infof(data, "error setting certificate verify locations,"
- " continuing anyway:\n");
- }
+ /* Just continue with a warning if no strict certificate verification
+ is required. */
+ infof(data, "error setting certificate verify locations,"
+ " continuing anyway:\n");
}
else {
/* Everything is fine. */
@@ -2091,12 +2166,11 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
failf(data, "error loading CRL file: %s", ssl_crlfile);
return CURLE_SSL_CRL_BADFILE;
}
- else {
- /* Everything is fine. */
- infof(data, "successfully load CRL file:\n");
- X509_STORE_set_flags(SSL_CTX_get_cert_store(connssl->ctx),
- X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
- }
+ /* Everything is fine. */
+ infof(data, "successfully load CRL file:\n");
+ X509_STORE_set_flags(SSL_CTX_get_cert_store(connssl->ctx),
+ X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
+
infof(data, " CRLfile: %s\n", ssl_crlfile);
}
@@ -2161,7 +2235,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
#endif
/* Check if there's a cached ID we can/should use here! */
- if(data->set.general_ssl.sessionid) {
+ if(SSL_SET_OPTION(primary.sessionid)) {
void *ssl_sessionid = NULL;
Curl_ssl_sessionid_lock(conn);
@@ -2170,7 +2244,8 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
if(!SSL_set_session(connssl->handle, ssl_sessionid)) {
Curl_ssl_sessionid_unlock(conn);
failf(data, "SSL: SSL_set_session failed: %s",
- ERR_error_string(ERR_get_error(), NULL));
+ ossl_strerror(ERR_get_error(), error_buffer,
+ sizeof(error_buffer)));
return CURLE_SSL_CONNECT_ERROR;
}
/* Informational message */
@@ -2190,7 +2265,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
else if(!SSL_set_fd(connssl->handle, (int)sockfd)) {
/* pass the raw socket into the SSL layers */
failf(data, "SSL: SSL_set_fd failed: %s",
- ERR_error_string(ERR_get_error(), NULL));
+ ossl_strerror(ERR_get_error(), error_buffer, sizeof(error_buffer)));
return CURLE_SSL_CONNECT_ERROR;
}
@@ -2224,15 +2299,14 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
connssl->connecting_state = ssl_connect_2_reading;
return CURLE_OK;
}
- else if(SSL_ERROR_WANT_WRITE == detail) {
+ if(SSL_ERROR_WANT_WRITE == detail) {
connssl->connecting_state = ssl_connect_2_writing;
return CURLE_OK;
}
else {
/* untreated error */
unsigned long errdetail;
- char error_buffer[256]=""; /* OpenSSL documents that this must be at
- least 256 bytes long. */
+ char error_buffer[256]="";
CURLcode result;
long lerr;
int lib;
@@ -2280,8 +2354,8 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
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 ",
- hostname, port);
+ failf(data, OSSL_PACKAGE " SSL_connect: %s in connection to %s:%ld ",
+ SSL_ERROR_to_str(detail), hostname, port);
return result;
}
@@ -2554,44 +2628,25 @@ static CURLcode get_cert_chain(struct connectdata *conn,
{
const BIGNUM *n;
const BIGNUM *e;
- const BIGNUM *d;
- const BIGNUM *p;
- const BIGNUM *q;
- const BIGNUM *dmp1;
- const BIGNUM *dmq1;
- const BIGNUM *iqmp;
- RSA_get0_key(rsa, &n, &e, &d);
- RSA_get0_factors(rsa, &p, &q);
- RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp);
+ RSA_get0_key(rsa, &n, &e, NULL);
BN_print(mem, n);
push_certinfo("RSA Public Key", i);
print_pubkey_BN(rsa, n, i);
print_pubkey_BN(rsa, e, i);
- print_pubkey_BN(rsa, d, i);
- print_pubkey_BN(rsa, p, i);
- print_pubkey_BN(rsa, q, i);
- print_pubkey_BN(rsa, dmp1, i);
- print_pubkey_BN(rsa, dmq1, i);
- print_pubkey_BN(rsa, iqmp, i);
}
#else
BIO_printf(mem, "%d", BN_num_bits(rsa->n));
push_certinfo("RSA Public Key", i);
print_pubkey_BN(rsa, n, i);
print_pubkey_BN(rsa, e, i);
- print_pubkey_BN(rsa, d, i);
- print_pubkey_BN(rsa, p, i);
- print_pubkey_BN(rsa, q, i);
- print_pubkey_BN(rsa, dmp1, i);
- print_pubkey_BN(rsa, dmq1, i);
- print_pubkey_BN(rsa, iqmp, i);
#endif
break;
}
case EVP_PKEY_DSA:
{
+#ifndef OPENSSL_NO_DSA
DSA *dsa;
#ifdef HAVE_OPAQUE_EVP_PKEY
dsa = EVP_PKEY_get0_DSA(pubkey);
@@ -2603,25 +2658,23 @@ static CURLcode get_cert_chain(struct connectdata *conn,
const BIGNUM *p;
const BIGNUM *q;
const BIGNUM *g;
- const BIGNUM *priv_key;
const BIGNUM *pub_key;
DSA_get0_pqg(dsa, &p, &q, &g);
- DSA_get0_key(dsa, &pub_key, &priv_key);
+ DSA_get0_key(dsa, &pub_key, NULL);
print_pubkey_BN(dsa, p, i);
print_pubkey_BN(dsa, q, i);
print_pubkey_BN(dsa, g, i);
- print_pubkey_BN(dsa, priv_key, i);
print_pubkey_BN(dsa, pub_key, i);
}
#else
print_pubkey_BN(dsa, p, i);
print_pubkey_BN(dsa, q, i);
print_pubkey_BN(dsa, g, i);
- print_pubkey_BN(dsa, priv_key, i);
print_pubkey_BN(dsa, pub_key, i);
#endif
+#endif /* !OPENSSL_NO_DSA */
break;
}
case EVP_PKEY_DH:
@@ -2637,20 +2690,17 @@ static CURLcode get_cert_chain(struct connectdata *conn,
const BIGNUM *p;
const BIGNUM *q;
const BIGNUM *g;
- const BIGNUM *priv_key;
const BIGNUM *pub_key;
DH_get0_pqg(dh, &p, &q, &g);
- DH_get0_key(dh, &pub_key, &priv_key);
+ DH_get0_key(dh, &pub_key, NULL);
print_pubkey_BN(dh, p, i);
print_pubkey_BN(dh, q, i);
print_pubkey_BN(dh, g, i);
- print_pubkey_BN(dh, priv_key, i);
print_pubkey_BN(dh, pub_key, i);
}
#else
print_pubkey_BN(dh, p, i);
print_pubkey_BN(dh, g, i);
- print_pubkey_BN(dh, priv_key, i);
print_pubkey_BN(dh, pub_key, i);
#endif
break;
@@ -2915,7 +2965,7 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex)
DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
- if(data->set.general_ssl.sessionid) {
+ if(SSL_SET_OPTION(primary.sessionid)) {
bool incache;
SSL_SESSION *our_ssl_sessionid;
void *old_ssl_sessionid = NULL;
@@ -3037,16 +3087,14 @@ static CURLcode ossl_connect_common(struct connectdata *conn,
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
return CURLE_SSL_CONNECT_ERROR;
}
- else if(0 == what) {
+ if(0 == what) {
if(nonblocking) {
*done = FALSE;
return CURLE_OK;
}
- else {
- /* timeout */
- failf(data, "SSL connection timeout");
- return CURLE_OPERATION_TIMEDOUT;
- }
+ /* timeout */
+ failf(data, "SSL connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
}
/* socket is readable or writable */
}
@@ -3116,8 +3164,7 @@ bool Curl_ossl_data_pending(const struct connectdata *conn, int connindex)
(conn->proxy_ssl[connindex].handle &&
0 != SSL_pending(conn->proxy_ssl[connindex].handle))) ?
TRUE : FALSE;
- else
- return FALSE;
+ return FALSE;
}
static ssize_t ossl_send(struct connectdata *conn,
@@ -3129,8 +3176,7 @@ static ssize_t ossl_send(struct connectdata *conn,
/* SSL_write() is said to return 'int' while write() and send() returns
'size_t' */
int err;
- char error_buffer[256]; /* OpenSSL documents that this must be at least 256
- bytes long. */
+ char error_buffer[256];
unsigned long sslerror;
int memlen;
int rc;
@@ -3176,7 +3222,8 @@ static ssize_t ossl_send(struct connectdata *conn,
return -1;
}
/* a true error */
- failf(conn->data, "SSL_write() return error %d", err);
+ failf(conn->data, OSSL_PACKAGE " SSL_write: %s, errno %d",
+ SSL_ERROR_to_str(err), SOCKERRNO);
*curlcode = CURLE_SEND_ERROR;
return -1;
}
@@ -3190,8 +3237,7 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */
size_t buffersize, /* max amount to read */
CURLcode *curlcode)
{
- char error_buffer[256]; /* OpenSSL documents that this must be at
- least 256 bytes long. */
+ char error_buffer[256];
unsigned long sslerror;
ssize_t nread;
int buffsize;
@@ -3221,8 +3267,10 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */
if((nread < 0) || sslerror) {
/* If the return code was negative or there actually is an error in the
queue */
- failf(conn->data, "SSL read: %s, errno %d",
- ossl_strerror(sslerror, error_buffer, sizeof(error_buffer)),
+ failf(conn->data, OSSL_PACKAGE " SSL_read: %s, errno %d",
+ (sslerror ?
+ ossl_strerror(sslerror, error_buffer, sizeof(error_buffer)) :
+ SSL_ERROR_to_str(err)),
SOCKERRNO);
*curlcode = CURLE_RECV_ERROR;
return -1;
@@ -3272,19 +3320,21 @@ size_t Curl_ossl_version(char *buffer, size_t size)
}
/* can be called with data == NULL */
-int Curl_ossl_random(struct Curl_easy *data, unsigned char *entropy,
- size_t length)
+CURLcode Curl_ossl_random(struct Curl_easy *data, unsigned char *entropy,
+ size_t length)
{
+ int rc;
if(data) {
if(Curl_ossl_seed(data)) /* Initiate the seed if not already done */
- return 1; /* couldn't seed for some reason */
+ return CURLE_FAILED_INIT; /* couldn't seed for some reason */
}
else {
if(!rand_enough())
- return 1;
+ return CURLE_FAILED_INIT;
}
- RAND_bytes(entropy, curlx_uztosi(length));
- return 0; /* 0 as in no problem */
+ /* RAND_bytes() returns 1 on success, 0 otherwise. */
+ rc = RAND_bytes(entropy, curlx_uztosi(length));
+ return (rc == 1 ? CURLE_OK : CURLE_FAILED_INIT);
}
void Curl_ossl_md5sum(unsigned char *tmp, /* input */
diff --git a/Utilities/cmcurl/lib/vtls/openssl.h b/Utilities/cmcurl/lib/vtls/openssl.h
index cff1e909cf..b9648d5147 100644
--- a/Utilities/cmcurl/lib/vtls/openssl.h
+++ b/Utilities/cmcurl/lib/vtls/openssl.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -66,8 +66,8 @@ bool Curl_ossl_data_pending(const struct connectdata *conn,
int connindex);
/* return 0 if a find random is filled in */
-int Curl_ossl_random(struct Curl_easy *data, unsigned char *entropy,
- size_t length);
+CURLcode Curl_ossl_random(struct Curl_easy *data, unsigned char *entropy,
+ size_t length);
void Curl_ossl_md5sum(unsigned char *tmp, /* input */
size_t tmplen,
unsigned char *md5sum /* output */,
diff --git a/Utilities/cmcurl/lib/vtls/polarssl.c b/Utilities/cmcurl/lib/vtls/polarssl.c
index 4bba3e3f28..669091cb53 100644
--- a/Utilities/cmcurl/lib/vtls/polarssl.c
+++ b/Utilities/cmcurl/lib/vtls/polarssl.c
@@ -140,6 +140,68 @@ static void polarssl_debug(void *context, int level, const char *line)
static Curl_recv polarssl_recv;
static Curl_send polarssl_send;
+static CURLcode polarssl_version_from_curl(int *polarver, long ssl_version)
+{
+ switch(ssl_version) {
+ case CURL_SSLVERSION_TLSv1_0:
+ *polarver = SSL_MINOR_VERSION_1;
+ return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_1:
+ *polarver = SSL_MINOR_VERSION_2;
+ return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_2:
+ *polarver = SSL_MINOR_VERSION_3;
+ return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_3:
+ break;
+ }
+ return CURLE_SSL_CONNECT_ERROR;
+}
+
+static CURLcode
+set_ssl_version_min_max(struct connectdata *conn, int sockindex)
+{
+ struct Curl_easy *data = conn->data;
+ struct ssl_connect_data* connssl = &conn->ssl[sockindex];
+ long ssl_version = SSL_CONN_CONFIG(version);
+ long ssl_version_max = SSL_CONN_CONFIG(version_max);
+ int ssl_min_ver = SSL_MINOR_VERSION_1;
+ int ssl_max_ver = SSL_MINOR_VERSION_1;
+ CURLcode result = CURLE_OK;
+
+ switch(ssl_version) {
+ case CURL_SSLVERSION_DEFAULT:
+ case CURL_SSLVERSION_TLSv1:
+ ssl_version = CURL_SSLVERSION_TLSv1_0;
+ ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
+ break;
+ }
+
+ switch(ssl_version_max) {
+ case CURL_SSLVERSION_MAX_NONE:
+ ssl_version_max = ssl_version << 16;
+ break;
+ case CURL_SSLVERSION_MAX_DEFAULT:
+ ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
+ break;
+ }
+
+ result = polarssl_version_from_curl(&ssl_min_ver, ssl_version);
+ if(result) {
+ failf(data, "unsupported min version passed via CURLOPT_SSLVERSION");
+ return result;
+ }
+ result = polarssl_version_from_curl(&ssl_max_ver, ssl_version_max >> 16);
+ if(result) {
+ failf(data, "unsupported max version passed via CURLOPT_SSLVERSION");
+ return result;
+ }
+
+ ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, ssl_min_ver);
+ ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3, ssl_max_ver);
+
+ return result;
+}
static CURLcode
polarssl_connect_step1(struct connectdata *conn,
@@ -287,29 +349,15 @@ polarssl_connect_step1(struct connectdata *conn,
infof(data, "PolarSSL: Forced min. SSL Version to be SSLv3\n");
break;
case CURL_SSLVERSION_TLSv1_0:
- ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
- SSL_MINOR_VERSION_1);
- ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
- SSL_MINOR_VERSION_1);
- infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.0\n");
- break;
case CURL_SSLVERSION_TLSv1_1:
- ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
- SSL_MINOR_VERSION_2);
- ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
- SSL_MINOR_VERSION_2);
- infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.1\n");
- break;
case CURL_SSLVERSION_TLSv1_2:
- ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
- SSL_MINOR_VERSION_3);
- ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
- SSL_MINOR_VERSION_3);
- infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.2\n");
- break;
case CURL_SSLVERSION_TLSv1_3:
- failf(data, "PolarSSL: TLS 1.3 is not yet supported");
- return CURLE_SSL_CONNECT_ERROR;
+ {
+ CURLcode result = set_ssl_version_min_max(conn, sockindex);
+ if(result != CURLE_OK)
+ return result;
+ break;
+ }
default:
failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
return CURLE_SSL_CONNECT_ERROR;
@@ -327,7 +375,7 @@ polarssl_connect_step1(struct connectdata *conn,
ssl_set_ciphersuites(&connssl->ssl, ssl_list_ciphersuites());
/* Check if there's a cached ID we can/should use here! */
- if(data->set.general_ssl.sessionid) {
+ if(SSL_SET_OPTION(primary.sessionid)) {
void *old_session = NULL;
Curl_ssl_sessionid_lock(conn);
@@ -555,7 +603,7 @@ polarssl_connect_step3(struct connectdata *conn,
DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
- if(data->set.general_ssl.sessionid) {
+ if(SSL_SET_OPTION(primary.sessionid)) {
int ret;
ssl_session *our_ssl_sessionid;
void *old_ssl_sessionid = NULL;
@@ -564,7 +612,7 @@ polarssl_connect_step3(struct connectdata *conn,
if(!our_ssl_sessionid)
return CURLE_OUT_OF_MEMORY;
- ssl_session_init(our_ssl_sessionid);
+ memset(our_ssl_sessionid, 0, sizeof(ssl_session));
ret = ssl_get_session(&connssl->ssl, our_ssl_sessionid);
if(ret) {
@@ -816,4 +864,10 @@ void Curl_polarssl_cleanup(void)
(void)Curl_polarsslthreadlock_thread_cleanup();
}
+
+int Curl_polarssl_data_pending(const struct connectdata *conn, int sockindex)
+{
+ return ssl_get_bytes_avail(&conn->ssl[sockindex].ssl) != 0;
+}
+
#endif /* USE_POLARSSL */
diff --git a/Utilities/cmcurl/lib/vtls/polarssl.h b/Utilities/cmcurl/lib/vtls/polarssl.h
index 7098b24a42..47af7b4173 100644
--- a/Utilities/cmcurl/lib/vtls/polarssl.h
+++ b/Utilities/cmcurl/lib/vtls/polarssl.h
@@ -31,6 +31,7 @@
/* Called on first use PolarSSL, setup threading if supported */
int Curl_polarssl_init(void);
void Curl_polarssl_cleanup(void);
+int Curl_polarssl_data_pending(const struct connectdata *conn, int sockindex);
CURLcode Curl_polarssl_connect(struct connectdata *conn, int sockindex);
@@ -69,7 +70,7 @@ int Curl_polarssl_shutdown(struct connectdata *conn, int sockindex);
#define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL)
#define curlssl_version Curl_polarssl_version
#define curlssl_check_cxn(x) ((void)x, -1)
-#define curlssl_data_pending(x,y) ((void)x, (void)y, 0)
+#define curlssl_data_pending(x,y) Curl_polarssl_data_pending(x, y)
#define curlssl_sha256sum(a,b,c,d) sha256(a,b,c,0)
/* This might cause libcurl to use a weeker random!
diff --git a/Utilities/cmcurl/lib/vtls/schannel.c b/Utilities/cmcurl/lib/vtls/schannel.c
index ac8b70556e..c9b513230a 100644
--- a/Utilities/cmcurl/lib/vtls/schannel.c
+++ b/Utilities/cmcurl/lib/vtls/schannel.c
@@ -7,7 +7,7 @@
*
* Copyright (C) 2012 - 2016, Marc Hoersken, <info@marc-hoersken.de>
* Copyright (C) 2012, Mark Salisbury, <mark.salisbury@hp.com>
- * Copyright (C) 2012 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -103,6 +103,41 @@ static void InitSecBufferDesc(SecBufferDesc *desc, SecBuffer *BufArr,
}
static CURLcode
+set_ssl_version_min_max(SCHANNEL_CRED *schannel_cred, struct connectdata *conn)
+{
+ struct Curl_easy *data = conn->data;
+ long ssl_version = SSL_CONN_CONFIG(version);
+ long ssl_version_max = SSL_CONN_CONFIG(version_max);
+ long i = ssl_version;
+
+ switch(ssl_version_max) {
+ case CURL_SSLVERSION_MAX_NONE:
+ ssl_version_max = ssl_version << 16;
+ break;
+ case CURL_SSLVERSION_MAX_DEFAULT:
+ ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
+ break;
+ }
+ for(; i <= (ssl_version_max >> 16); ++i) {
+ switch(i) {
+ case CURL_SSLVERSION_TLSv1_0:
+ schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_0_CLIENT;
+ break;
+ case CURL_SSLVERSION_TLSv1_1:
+ schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_1_CLIENT;
+ break;
+ case CURL_SSLVERSION_TLSv1_2:
+ schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_2_CLIENT;
+ break;
+ case CURL_SSLVERSION_TLSv1_3:
+ failf(data, "Schannel: TLS 1.3 is not yet supported");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+ return CURLE_OK;
+}
+
+static CURLcode
schannel_connect_step1(struct connectdata *conn, int sockindex)
{
ssize_t written = -1;
@@ -124,12 +159,20 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
#endif
TCHAR *host_name;
CURLcode result;
- const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+ char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
conn->host.name;
infof(data, "schannel: SSL/TLS connection with %s port %hu (step 1/3)\n",
hostname, conn->remote_port);
+ if(Curl_verify_windows_version(5, 1, PLATFORM_WINNT,
+ VERSION_LESS_THAN_EQUAL)) {
+ /* SChannel in Windows XP (OS version 5.1) uses legacy handshakes and
+ algorithms that may not be supported by all servers. */
+ infof(data, "schannel: WinSSL version is old and may not be able to "
+ "connect to some servers due to lack of SNI, algorithms, etc.\n");
+ }
+
#ifdef HAS_ALPN
/* ALPN is only supported on Windows 8.1 / Server 2012 R2 and above.
Also it doesn't seem to be supported for Wine, see curl bug #983. */
@@ -145,7 +188,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
connssl->cred = NULL;
/* check for an existing re-usable credential handle */
- if(data->set.general_ssl.sessionid) {
+ if(SSL_SET_OPTION(primary.sessionid)) {
Curl_ssl_sessionid_lock(conn);
if(!Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL, sockindex)) {
connssl->cred = old_cred;
@@ -197,7 +240,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
schannel_cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK;
infof(data, "schannel: verifyhost setting prevents Schannel from "
"comparing the supplied target name with the subject "
- "names in server certificates. Also disables SNI.\n");
+ "names in server certificates.\n");
}
switch(conn->ssl_config.version) {
@@ -208,17 +251,15 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
SP_PROT_TLS1_2_CLIENT;
break;
case CURL_SSLVERSION_TLSv1_0:
- schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_0_CLIENT;
- break;
case CURL_SSLVERSION_TLSv1_1:
- schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_1_CLIENT;
- break;
case CURL_SSLVERSION_TLSv1_2:
- schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_2_CLIENT;
- break;
case CURL_SSLVERSION_TLSv1_3:
- failf(data, "Schannel: TLS 1.3 is not yet supported");
- return CURLE_SSL_CONNECT_ERROR;
+ {
+ result = set_ssl_version_min_max(&schannel_cred, conn);
+ if(result != CURLE_OK)
+ return result;
+ break;
+ }
case CURL_SSLVERSION_SSLv3:
schannel_cred.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT;
break;
@@ -415,7 +456,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
TCHAR *host_name;
CURLcode result;
bool doread;
- const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+ char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
conn->host.name;
doread = (connssl->connecting_state != ssl_connect_2_writing) ? TRUE : FALSE;
@@ -649,8 +690,10 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
SECURITY_STATUS sspi_status = SEC_E_OK;
CERT_CONTEXT *ccert_context = NULL;
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
conn->host.name;
+#endif
#ifdef HAS_ALPN
SecPkgContext_ApplicationProtocol alpn_result;
#endif
@@ -714,7 +757,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
#endif
/* save the current session data for possible re-use */
- if(data->set.general_ssl.sessionid) {
+ if(SSL_SET_OPTION(primary.sessionid)) {
bool incache;
struct curl_schannel_cred *old_cred = NULL;
@@ -1391,7 +1434,7 @@ int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
*/
struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+ char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
conn->host.name;
infof(data, "schannel: shutting down SSL/TLS connection with %s port %hu\n",
@@ -1516,21 +1559,21 @@ size_t Curl_schannel_version(char *buffer, size_t size)
return size;
}
-int Curl_schannel_random(unsigned char *entropy, size_t length)
+CURLcode Curl_schannel_random(unsigned char *entropy, size_t length)
{
HCRYPTPROV hCryptProv = 0;
if(!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
- return 1;
+ return CURLE_FAILED_INIT;
if(!CryptGenRandom(hCryptProv, (DWORD)length, entropy)) {
CryptReleaseContext(hCryptProv, 0UL);
- return 1;
+ return CURLE_FAILED_INIT;
}
CryptReleaseContext(hCryptProv, 0UL);
- return 0;
+ return CURLE_OK;
}
#ifdef _WIN32_WCE
diff --git a/Utilities/cmcurl/lib/vtls/schannel.h b/Utilities/cmcurl/lib/vtls/schannel.h
index 8a4991ec83..8627c63c9e 100644
--- a/Utilities/cmcurl/lib/vtls/schannel.h
+++ b/Utilities/cmcurl/lib/vtls/schannel.h
@@ -8,7 +8,7 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2012, Marc Hoersken, <info@marc-hoersken.de>, et al.
- * Copyright (C) 2012 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -92,7 +92,7 @@ int Curl_schannel_init(void);
void Curl_schannel_cleanup(void);
size_t Curl_schannel_version(char *buffer, size_t size);
-int Curl_schannel_random(unsigned char *entropy, size_t length);
+CURLcode Curl_schannel_random(unsigned char *entropy, size_t length);
/* Set the API backend definition to Schannel */
#define CURL_SSL_BACKEND CURLSSLBACKEND_SCHANNEL
diff --git a/Utilities/cmcurl/lib/vtls/vtls.c b/Utilities/cmcurl/lib/vtls/vtls.c
index b808e1c5fe..d5d0971c45 100644
--- a/Utilities/cmcurl/lib/vtls/vtls.c
+++ b/Utilities/cmcurl/lib/vtls/vtls.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -95,6 +95,7 @@ Curl_ssl_config_matches(struct ssl_primary_config* data,
struct ssl_primary_config* needle)
{
if((data->version == needle->version) &&
+ (data->version_max == needle->version_max) &&
(data->verifypeer == needle->verifypeer) &&
(data->verifyhost == needle->verifyhost) &&
Curl_safe_strcasecompare(data->CApath, needle->CApath) &&
@@ -113,6 +114,7 @@ Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
dest->verifyhost = source->verifyhost;
dest->verifypeer = source->verifypeer;
dest->version = source->version;
+ dest->version_max = source->version_max;
CLONE_STRING(CAfile);
CLONE_STRING(CApath);
@@ -120,6 +122,9 @@ Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
CLONE_STRING(egdsocket);
CLONE_STRING(random_file);
CLONE_STRING(clientcert);
+
+ /* Disable dest sessionid cache if a client cert is used, CVE-2016-5419. */
+ dest->sessionid = (dest->clientcert ? false : source->sessionid);
return TRUE;
}
@@ -173,11 +178,24 @@ void Curl_ssl_cleanup(void)
static bool ssl_prefs_check(struct Curl_easy *data)
{
/* check for CURLOPT_SSLVERSION invalid parameter value */
- if((data->set.ssl.primary.version < 0)
- || (data->set.ssl.primary.version >= CURL_SSLVERSION_LAST)) {
+ const long sslver = data->set.ssl.primary.version;
+ if((sslver < 0) || (sslver >= CURL_SSLVERSION_LAST)) {
failf(data, "Unrecognized parameter value passed via CURLOPT_SSLVERSION");
return FALSE;
}
+
+ switch(data->set.ssl.primary.version_max) {
+ case CURL_SSLVERSION_MAX_NONE:
+ case CURL_SSLVERSION_MAX_DEFAULT:
+ break;
+
+ default:
+ if((data->set.ssl.primary.version_max >> 16) < sslver) {
+ failf(data, "CURL_SSLVERSION_MAX incompatible with CURL_SSLVERSION");
+ return FALSE;
+ }
+ }
+
return TRUE;
}
@@ -286,16 +304,16 @@ bool Curl_ssl_getsessionid(struct connectdata *conn,
const bool isProxy = CONNECT_PROXY_SSL();
struct ssl_primary_config * const ssl_config = isProxy ?
- &conn->proxy_ssl_config :
- &conn->ssl_config;
+ &conn->proxy_ssl_config :
+ &conn->ssl_config;
const char * const name = isProxy ? conn->http_proxy.host.name :
- conn->host.name;
+ conn->host.name;
int port = isProxy ? (int)conn->port : conn->remote_port;
*ssl_sessionid = NULL;
- DEBUGASSERT(data->set.general_ssl.sessionid);
+ DEBUGASSERT(SSL_SET_OPTION(primary.sessionid));
- if(!data->set.general_ssl.sessionid)
+ if(!SSL_SET_OPTION(primary.sessionid))
/* session ID re-use is disabled */
return TRUE;
@@ -394,10 +412,10 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
long *general_age;
const bool isProxy = CONNECT_PROXY_SSL();
struct ssl_primary_config * const ssl_config = isProxy ?
- &conn->proxy_ssl_config :
- &conn->ssl_config;
+ &conn->proxy_ssl_config :
+ &conn->ssl_config;
- DEBUGASSERT(data->set.general_ssl.sessionid);
+ DEBUGASSERT(SSL_SET_OPTION(primary.sessionid));
clone_host = strdup(isProxy ? conn->http_proxy.host.name : conn->host.name);
if(!clone_host)
@@ -447,7 +465,7 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
store->sessionid = ssl_sessionid;
store->idsize = idsize;
store->age = *general_age; /* set current age */
- /* free it if there's one already present */
+ /* free it if there's one already present */
free(store->name);
free(store->conn_to_host);
store->name = clone_host; /* clone host name */
@@ -484,9 +502,9 @@ void Curl_ssl_close_all(struct Curl_easy *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. */
+#if defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \
+ defined(USE_DARWINSSL) || defined(USE_POLARSSL) || defined(USE_NSS) || \
+ defined(USE_MBEDTLS)
int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks,
int numsocks)
{
@@ -500,7 +518,7 @@ int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks,
socks[0] = conn->sock[FIRSTSOCKET];
return GETSOCK_WRITESOCK(0);
}
- else if(connssl->connecting_state == ssl_connect_2_reading) {
+ if(connssl->connecting_state == ssl_connect_2_reading) {
/* read mode */
socks[0] = conn->sock[FIRSTSOCKET];
return GETSOCK_READSOCK(0);
@@ -510,15 +528,15 @@ int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks,
}
#else
int Curl_ssl_getsock(struct connectdata *conn,
- curl_socket_t *socks,
- int numsocks)
+ 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 */
+/* USE_OPENSSL || USE_GNUTLS || USE_SCHANNEL || USE_DARWINSSL || USE_NSS */
#endif
void Curl_ssl_close(struct connectdata *conn, int sockindex)
@@ -703,12 +721,7 @@ CURLcode Curl_ssl_random(struct Curl_easy *data,
unsigned char *entropy,
size_t length)
{
- int rc = curlssl_random(data, entropy, length);
- if(rc) {
- failf(data, "PRNG seeding failed");
- return CURLE_FAILED_INIT; /* possibly weird return code */
- }
- return CURLE_OK;
+ return curlssl_random(data, entropy, length);
}
/*