]> granicus.if.org Git - curl/commitdiff
disable GnuTLS insecure ciphers
authorFabian Frank <frankfa@yahoo-inc.com>
Sun, 19 Jan 2014 08:47:31 +0000 (00:47 -0800)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 20 Jan 2014 10:32:55 +0000 (11:32 +0100)
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

index 425b0f8173d44121e35176c53d3fabd5fa721404..cd410551c8975d2a542ddcc542b5ddd84f93e9a0 100644 (file)
@@ -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,