Blame SOURCES/0001-rh1177964-fallback-semantics.patch

23842f
From 1b8db6c27f2f3909b55fc2902d2fd0431b066058 Mon Sep 17 00:00:00 2001
23842f
From: Dan Winship <danw@gnome.org>
23842f
Date: Sun, 26 Oct 2014 12:25:15 -0400
23842f
Subject: [PATCH 1/2] gnutls: loosen the semantics of "use-ssl3"
23842f
23842f
If SSL 3.0 is disabled, then make "use-ssl3" mean "use the lowest
23842f
available TLS version" instead, so that, eg, TLS 1.2 -> TLS 1.0
23842f
fallback is still possible.
23842f
23842f
https://bugzilla.gnome.org/show_bug.cgi?id=738633
23842f
---
23842f
 tls/gnutls/gtlsconnection-gnutls.c | 55 +++++++++++++++++-------
23842f
 tls/tests/connection.c             | 88 ++++++++++++++++++++++++++++++++++++++
23842f
 2 files changed, 127 insertions(+), 16 deletions(-)
23842f
23842f
diff --git a/tls/gnutls/gtlsconnection-gnutls.c b/tls/gnutls/gtlsconnection-gnutls.c
23842f
index 7e63412..444ca36 100644
23842f
--- a/tls/gnutls/gtlsconnection-gnutls.c
23842f
+++ b/tls/gnutls/gtlsconnection-gnutls.c
23842f
@@ -194,15 +194,16 @@ g_tls_connection_gnutls_init (GTlsConnectionGnutls *gnutls)
23842f
   g_mutex_init (&gnutls->priv->op_mutex);
23842f
 }
23842f
 
23842f
-/* First field is "ssl3 only", second is "allow unsafe rehandshaking" */
23842f
+/* First field is "fallback", second is "allow unsafe rehandshaking" */
23842f
 static gnutls_priority_t priorities[2][2];
23842f
 
23842f
 static void
23842f
 g_tls_connection_gnutls_init_priorities (void)
23842f
 {
23842f
   const gchar *base_priority;
23842f
-  gchar *ssl3_priority, *unsafe_rehandshake_priority, *ssl3_unsafe_rehandshake_priority;
23842f
-  int ret;
23842f
+  gchar *fallback_priority, *unsafe_rehandshake_priority, *fallback_unsafe_rehandshake_priority;
23842f
+  const guint *protos;
23842f
+  int ret, i, nprotos, fallback_proto;
23842f
 
23842f
   base_priority = g_getenv ("G_TLS_GNUTLS_PRIORITY");
23842f
   if (!base_priority)
23842f
@@ -215,31 +216,53 @@ g_tls_connection_gnutls_init_priorities (void)
23842f
       gnutls_priority_init (&priorities[FALSE][FALSE], base_priority, NULL);
23842f
     }
23842f
 
23842f
-  ssl3_priority = g_strdup_printf ("%s:!VERS-TLS1.2:!VERS-TLS1.1:!VERS-TLS1.0", base_priority);
23842f
   unsafe_rehandshake_priority = g_strdup_printf ("%s:%%UNSAFE_RENEGOTIATION", base_priority);
23842f
-  ssl3_unsafe_rehandshake_priority = g_strdup_printf ("%s:!VERS-TLS1.2:!VERS-TLS1.1:!VERS-TLS1.0:%%UNSAFE_RENEGOTIATION", base_priority);
23842f
-
23842f
-  gnutls_priority_init (&priorities[TRUE][FALSE], ssl3_priority, NULL);
23842f
-  gnutls_priority_init (&priorities[FALSE][TRUE], unsafe_rehandshake_priority, NULL);
23842f
-  gnutls_priority_init (&priorities[TRUE][TRUE], ssl3_unsafe_rehandshake_priority, NULL);
23842f
-
23842f
-  g_free (ssl3_priority);
23842f
+  ret = gnutls_priority_init (&priorities[FALSE][TRUE], unsafe_rehandshake_priority, NULL);
23842f
+  g_warn_if_fail (ret == 0);
23842f
   g_free (unsafe_rehandshake_priority);
23842f
-  g_free (ssl3_unsafe_rehandshake_priority);
23842f
+
23842f
+  /* Figure out the lowest SSl/TLS version supported by base_priority */
23842f
+  nprotos = gnutls_priority_protocol_list (priorities[FALSE][FALSE], &protos);
23842f
+  fallback_proto = G_MAXUINT;
23842f
+  for (i = 0; i < nprotos; i++)
23842f
+    {
23842f
+      if (protos[i] < fallback_proto)
23842f
+	fallback_proto = protos[i];
23842f
+    }
23842f
+  if (fallback_proto == G_MAXUINT)
23842f
+    {
23842f
+      g_warning ("All GNUTLS protocol versions disabled?");
23842f
+      fallback_priority = g_strdup (base_priority);
23842f
+    }
23842f
+  else
23842f
+    {
23842f
+      fallback_priority = g_strdup_printf ("%s:!VERS-TLS-ALL:+VERS-%s",
23842f
+					   base_priority,
23842f
+					   gnutls_protocol_get_name (fallback_proto));
23842f
+    }
23842f
+  fallback_unsafe_rehandshake_priority = g_strdup_printf ("%s:%%UNSAFE_RENEGOTIATION",
23842f
+							  fallback_priority);
23842f
+
23842f
+  ret = gnutls_priority_init (&priorities[TRUE][FALSE], fallback_priority, NULL);
23842f
+  g_warn_if_fail (ret == 0);
23842f
+  ret = gnutls_priority_init (&priorities[TRUE][TRUE], fallback_unsafe_rehandshake_priority, NULL);
23842f
+  g_warn_if_fail (ret == 0);
23842f
+  g_free (fallback_priority);
23842f
+  g_free (fallback_unsafe_rehandshake_priority);
23842f
 }
23842f
 
23842f
 static void
23842f
 g_tls_connection_gnutls_set_handshake_priority (GTlsConnectionGnutls *gnutls)
23842f
 {
23842f
-  gboolean use_ssl3, unsafe_rehandshake;
23842f
+  gboolean fallback, unsafe_rehandshake;
23842f
 
23842f
   if (G_IS_TLS_CLIENT_CONNECTION (gnutls))
23842f
-    use_ssl3 = g_tls_client_connection_get_use_ssl3 (G_TLS_CLIENT_CONNECTION (gnutls));
23842f
+    fallback = g_tls_client_connection_get_use_ssl3 (G_TLS_CLIENT_CONNECTION (gnutls));
23842f
   else
23842f
-    use_ssl3 = FALSE;
23842f
+    fallback = FALSE;
23842f
   unsafe_rehandshake = (gnutls->priv->rehandshake_mode == G_TLS_REHANDSHAKE_UNSAFELY);
23842f
   gnutls_priority_set (gnutls->priv->session,
23842f
-		       priorities[use_ssl3][unsafe_rehandshake]);
23842f
+		       priorities[fallback][unsafe_rehandshake]);
23842f
 }
23842f
 
23842f
 static gboolean
23842f
diff --git a/tls/tests/connection.c b/tls/tests/connection.c
23842f
index 0df8bb1..0e7b706 100644
23842f
--- a/tls/tests/connection.c
23842f
+++ b/tls/tests/connection.c
23842f
@@ -1377,11 +1377,90 @@ test_async_implicit_handshake (TestConnection *test, gconstpointer   data)
23842f
   test->client_connection = NULL;
23842f
 }
23842f
 
23842f
+static void
23842f
+quit_on_handshake_complete (GObject      *object,
23842f
+			    GAsyncResult *result,
23842f
+			    gpointer      user_data)
23842f
+{
23842f
+  TestConnection *test = user_data;
23842f
+  GError *error = NULL;
23842f
+
23842f
+  g_tls_connection_handshake_finish (G_TLS_CONNECTION (object), result, &error);
23842f
+  g_assert_no_error (error);
23842f
+
23842f
+  g_main_loop_quit (test->loop);
23842f
+  return;
23842f
+}
23842f
+
23842f
+#define PRIORITY_SSL_FALLBACK "NORMAL:+VERS-SSL3.0"
23842f
+#define PRIORITY_TLS_FALLBACK "NORMAL:+VERS-TLS-ALL:-VERS-SSL3.0"
23842f
+
23842f
+static void
23842f
+test_fallback (gconstpointer data)
23842f
+{
23842f
+  const char *priority_string = (const char *) data;
23842f
+  char *test_name;
23842f
+
23842f
+  test_name = g_strdup_printf ("/tls/connection/fallback/subprocess/%s", priority_string);
23842f
+  g_test_trap_subprocess (test_name, 0, 0);
23842f
+  g_test_trap_assert_passed ();
23842f
+  g_free (test_name);
23842f
+}
23842f
+
23842f
+static void
23842f
+test_fallback_subprocess (TestConnection *test,
23842f
+			  gconstpointer   data)
23842f
+{
23842f
+  GIOStream *connection;
23842f
+  GTlsConnection *tlsconn;
23842f
+  GError *error = NULL;
23842f
+
23842f
+  connection = start_echo_server_and_connect_to_it (test);
23842f
+  test->client_connection = g_tls_client_connection_new (connection, NULL, &error);
23842f
+  g_assert_no_error (error);
23842f
+  tlsconn = G_TLS_CONNECTION (test->client_connection);
23842f
+  g_object_unref (connection);
23842f
+
23842f
+  g_tls_client_connection_set_validation_flags (G_TLS_CLIENT_CONNECTION (test->client_connection),
23842f
+                                                0);
23842f
+  g_tls_client_connection_set_use_ssl3 (G_TLS_CLIENT_CONNECTION (test->client_connection),
23842f
+					TRUE);
23842f
+  g_tls_connection_handshake_async (tlsconn, G_PRIORITY_DEFAULT, NULL,
23842f
+				    quit_on_handshake_complete, test);
23842f
+  g_main_loop_run (test->loop);
23842f
+
23842f
+  /* In 2.42 we don't have the API to test that the correct version was negotiated,
23842f
+   * so we merely test that the connection succeeded at all.
23842f
+   */
23842f
+
23842f
+  g_io_stream_close (test->client_connection, NULL, &error);
23842f
+  g_assert_no_error (error);
23842f
+}
23842f
+
23842f
 int
23842f
 main (int   argc,
23842f
       char *argv[])
23842f
 {
23842f
   int ret;
23842f
+  int i;
23842f
+
23842f
+  /* Check if this is a subprocess, and set G_TLS_GNUTLS_PRIORITY
23842f
+   * appropriately if so.
23842f
+   */
23842f
+  for (i = 1; i < argc - 1; i++)
23842f
+    {
23842f
+      if (!strcmp (argv[i], "-p"))
23842f
+	{
23842f
+	  const char *priority = argv[i + 1];
23842f
+
23842f
+	  priority = strrchr (priority, '/');
23842f
+	  if (priority++ &&
23842f
+	      (g_str_has_prefix (priority, "NORMAL:") ||
23842f
+	       g_str_has_prefix (priority, "NONE:")))
23842f
+	    g_setenv ("G_TLS_GNUTLS_PRIORITY", priority, TRUE);
23842f
+	  break;
23842f
+	}
23842f
+    }
23842f
 
23842f
   g_test_init (&argc, &argv, NULL);
23842f
   g_test_bug_base ("http://bugzilla.gnome.org/");
23842f
@@ -1431,6 +1510,15 @@ main (int   argc,
23842f
   g_test_add ("/tls/connection/async-implicit-handshake", TestConnection, NULL,
23842f
               setup_connection, test_async_implicit_handshake, teardown_connection);
23842f
 
23842f
+  g_test_add_data_func ("/tls/connection/fallback/SSL", PRIORITY_SSL_FALLBACK, test_fallback);
23842f
+  g_test_add ("/tls/connection/fallback/subprocess/" PRIORITY_SSL_FALLBACK,
23842f
+	      TestConnection, NULL,
23842f
+              setup_connection, test_fallback_subprocess, teardown_connection);
23842f
+  g_test_add_data_func ("/tls/connection/fallback/TLS", PRIORITY_TLS_FALLBACK, test_fallback);
23842f
+  g_test_add ("/tls/connection/fallback/subprocess/" PRIORITY_TLS_FALLBACK,
23842f
+	      TestConnection, NULL,
23842f
+              setup_connection, test_fallback_subprocess, teardown_connection);
23842f
+
23842f
   ret = g_test_run();
23842f
 
23842f
   /* for valgrinding */
23842f
-- 
23842f
2.1.0
23842f