From 39f7e80a52c3b23b36015dcf0d3655af43a70f49 Mon Sep 17 00:00:00 2001 From: Fabian Frank Date: Sun, 19 Jan 2014 00:47:31 -0800 Subject: disable GnuTLS insecure ciphers Make GnuTLS old and new consistent, specify the desired protocol, cipher and certificate type in always in both modes. Disable insecure ciphers as reported by howsmyssl.com. Honor not only --sslv3, but also the --tlsv1[.N] switches. Related Bug: http://curl.haxx.se/bug/view.cgi?id=1323 --- lib/vtls/gtls.c | 110 ++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 87 insertions(+), 23 deletions(-) (limited to 'lib/vtls/gtls.c') diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c index 425b0f817..cd410551c 100644 --- a/lib/vtls/gtls.c +++ b/lib/vtls/gtls.c @@ -350,9 +350,6 @@ static CURLcode gtls_connect_step1(struct connectdata *conn, int sockindex) { -#ifndef USE_GNUTLS_PRIORITY_SET_DIRECT - static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 }; -#endif struct SessionHandle *data = conn->data; gnutls_session session; int rc; @@ -364,6 +361,19 @@ gtls_connect_step1(struct connectdata *conn, #else struct in_addr addr; #endif +#ifndef USE_GNUTLS_PRIORITY_SET_DIRECT + static int cipher_priority[] = { GNUTLS_CIPHER_AES_128_GCM, + GNUTLS_CIPHER_AES_256_GCM, GNUTLS_CIPHER_AES_128_CBC, + GNUTLS_CIPHER_AES_256_CBC, GNUTLS_CIPHER_CAMELLIA_128_CBC, + GNUTLS_CIPHER_CAMELLIA_256_CBC, GNUTLS_CIPHER_3DES_CBC, + }; + static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 }; + static int protocol_priority[] = { 0, 0, 0, 0 }; +#else +#define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509" + const char* prioritylist; + const char *err; +#endif if(conn->ssl[sockindex].state == ssl_connection_complete) /* to make us tolerant against being called more than once for the @@ -471,34 +481,88 @@ gtls_connect_step1(struct connectdata *conn, if(rc != GNUTLS_E_SUCCESS) return CURLE_SSL_CONNECT_ERROR; - if(data->set.ssl.version == CURL_SSLVERSION_SSLv3) { #ifndef USE_GNUTLS_PRIORITY_SET_DIRECT - static const int protocol_priority[] = { GNUTLS_SSL3, 0 }; - rc = gnutls_protocol_set_priority(session, protocol_priority); -#else - const char *err; - /* the combination of the cipher ARCFOUR with SSL 3.0 and TLS 1.0 is not - vulnerable to attacks such as the BEAST, why this code now explicitly - asks for that - */ - rc = gnutls_priority_set_direct(session, - "NORMAL:-VERS-TLS-ALL:+VERS-SSL3.0:" - "-CIPHER-ALL:+ARCFOUR-128", - &err); -#endif - if(rc != GNUTLS_E_SUCCESS) - return CURLE_SSL_CONNECT_ERROR; - } + rc = gnutls_cipher_set_priority(session, cipher_priority); + if(rc != GNUTLS_E_SUCCESS) + return CURLE_SSL_CONNECT_ERROR; -#ifndef USE_GNUTLS_PRIORITY_SET_DIRECT /* Sets the priority on the certificate types supported by gnutls. Priority - is higher for types specified before others. After specifying the types - you want, you must append a 0. */ + is higher for types specified before others. After specifying the types + you want, you must append a 0. */ rc = gnutls_certificate_type_set_priority(session, cert_type_priority); if(rc != GNUTLS_E_SUCCESS) return CURLE_SSL_CONNECT_ERROR; + + if(data->set.ssl.cipher_list != NULL) { + failf(data, "can't pass a custom cipher list to older GnuTLS" + " versions"); + return CURLE_SSL_CONNECT_ERROR; + } + + switch (data->set.ssl.version) { + case CURL_SSLVERSION_SSLv3: + protocol_priority[0] = GNUTLS_SSL3; + break; + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + protocol_priority[0] = GNUTLS_TLS1_0; + protocol_priority[1] = GNUTLS_TLS1_1; + 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_SSLv2: + default: + failf(data, "GnuTLS does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + break; + } + rc = gnutls_protocol_set_priority(session, protocol_priority); +#else + switch (data->set.ssl.version) { + case CURL_SSLVERSION_SSLv3: + prioritylist = GNUTLS_CIPHERS ":-VERS-TLS-ALL:+VERS-SSL3.0"; + sni = false; + break; + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0"; + break; + case CURL_SSLVERSION_TLSv1_0: + prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.0"; + break; + case CURL_SSLVERSION_TLSv1_1: + prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.1"; + break; + case CURL_SSLVERSION_TLSv1_2: + prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.2"; + break; + case CURL_SSLVERSION_SSLv2: + default: + failf(data, "GnuTLS does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + break; + } + rc = gnutls_priority_set_direct(session, prioritylist, &err); #endif + + if(rc != GNUTLS_E_SUCCESS) { + failf(data, "Did you pass a valid GnuTLS cipher list?"); + return CURLE_SSL_CONNECT_ERROR; + } + + if(data->set.str[STRING_CERT]) { if(gnutls_certificate_set_x509_key_file( conn->ssl[sockindex].cred, -- cgit v1.2.3