[glib-networking/f21] Improve priority string and fallback rules for the post-POODLE world (#1177964)

Dan Winship danw at fedoraproject.org
Fri Mar 6 18:34:14 UTC 2015


commit 03a3d354a0a7d7c1cdc28a9c38892901e1984264
Author: Dan Winship <danw at redhat.com>
Date:   Fri Mar 6 13:33:51 2015 -0500

    Improve priority string and fallback rules for the post-POODLE world (#1177964)

 0001-rh1177964-fallback-semantics.patch | 220 ++++++++++++++++++++++++++++++++
 0002-rh1177964-priority-string.patch    |  78 +++++++++++
 glib-networking.spec                    |  10 +-
 3 files changed, 307 insertions(+), 1 deletion(-)
---
diff --git a/0001-rh1177964-fallback-semantics.patch b/0001-rh1177964-fallback-semantics.patch
new file mode 100644
index 0000000..bb25172
--- /dev/null
+++ b/0001-rh1177964-fallback-semantics.patch
@@ -0,0 +1,220 @@
+From 1b8db6c27f2f3909b55fc2902d2fd0431b066058 Mon Sep 17 00:00:00 2001
+From: Dan Winship <danw at gnome.org>
+Date: Sun, 26 Oct 2014 12:25:15 -0400
+Subject: [PATCH 1/2] gnutls: loosen the semantics of "use-ssl3"
+
+If SSL 3.0 is disabled, then make "use-ssl3" mean "use the lowest
+available TLS version" instead, so that, eg, TLS 1.2 -> TLS 1.0
+fallback is still possible.
+
+https://bugzilla.gnome.org/show_bug.cgi?id=738633
+---
+ tls/gnutls/gtlsconnection-gnutls.c | 55 +++++++++++++++++-------
+ tls/tests/connection.c             | 88 ++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 127 insertions(+), 16 deletions(-)
+
+diff --git a/tls/gnutls/gtlsconnection-gnutls.c b/tls/gnutls/gtlsconnection-gnutls.c
+index 7e63412..444ca36 100644
+--- a/tls/gnutls/gtlsconnection-gnutls.c
++++ b/tls/gnutls/gtlsconnection-gnutls.c
+@@ -194,15 +194,16 @@ g_tls_connection_gnutls_init (GTlsConnectionGnutls *gnutls)
+   g_mutex_init (&gnutls->priv->op_mutex);
+ }
+ 
+-/* First field is "ssl3 only", second is "allow unsafe rehandshaking" */
++/* First field is "fallback", second is "allow unsafe rehandshaking" */
+ static gnutls_priority_t priorities[2][2];
+ 
+ static void
+ g_tls_connection_gnutls_init_priorities (void)
+ {
+   const gchar *base_priority;
+-  gchar *ssl3_priority, *unsafe_rehandshake_priority, *ssl3_unsafe_rehandshake_priority;
+-  int ret;
++  gchar *fallback_priority, *unsafe_rehandshake_priority, *fallback_unsafe_rehandshake_priority;
++  const guint *protos;
++  int ret, i, nprotos, fallback_proto;
+ 
+   base_priority = g_getenv ("G_TLS_GNUTLS_PRIORITY");
+   if (!base_priority)
+@@ -215,31 +216,53 @@ g_tls_connection_gnutls_init_priorities (void)
+       gnutls_priority_init (&priorities[FALSE][FALSE], base_priority, NULL);
+     }
+ 
+-  ssl3_priority = g_strdup_printf ("%s:!VERS-TLS1.2:!VERS-TLS1.1:!VERS-TLS1.0", base_priority);
+   unsafe_rehandshake_priority = g_strdup_printf ("%s:%%UNSAFE_RENEGOTIATION", base_priority);
+-  ssl3_unsafe_rehandshake_priority = g_strdup_printf ("%s:!VERS-TLS1.2:!VERS-TLS1.1:!VERS-TLS1.0:%%UNSAFE_RENEGOTIATION", base_priority);
+-
+-  gnutls_priority_init (&priorities[TRUE][FALSE], ssl3_priority, NULL);
+-  gnutls_priority_init (&priorities[FALSE][TRUE], unsafe_rehandshake_priority, NULL);
+-  gnutls_priority_init (&priorities[TRUE][TRUE], ssl3_unsafe_rehandshake_priority, NULL);
+-
+-  g_free (ssl3_priority);
++  ret = gnutls_priority_init (&priorities[FALSE][TRUE], unsafe_rehandshake_priority, NULL);
++  g_warn_if_fail (ret == 0);
+   g_free (unsafe_rehandshake_priority);
+-  g_free (ssl3_unsafe_rehandshake_priority);
++
++  /* Figure out the lowest SSl/TLS version supported by base_priority */
++  nprotos = gnutls_priority_protocol_list (priorities[FALSE][FALSE], &protos);
++  fallback_proto = G_MAXUINT;
++  for (i = 0; i < nprotos; i++)
++    {
++      if (protos[i] < fallback_proto)
++	fallback_proto = protos[i];
++    }
++  if (fallback_proto == G_MAXUINT)
++    {
++      g_warning ("All GNUTLS protocol versions disabled?");
++      fallback_priority = g_strdup (base_priority);
++    }
++  else
++    {
++      fallback_priority = g_strdup_printf ("%s:!VERS-TLS-ALL:+VERS-%s",
++					   base_priority,
++					   gnutls_protocol_get_name (fallback_proto));
++    }
++  fallback_unsafe_rehandshake_priority = g_strdup_printf ("%s:%%UNSAFE_RENEGOTIATION",
++							  fallback_priority);
++
++  ret = gnutls_priority_init (&priorities[TRUE][FALSE], fallback_priority, NULL);
++  g_warn_if_fail (ret == 0);
++  ret = gnutls_priority_init (&priorities[TRUE][TRUE], fallback_unsafe_rehandshake_priority, NULL);
++  g_warn_if_fail (ret == 0);
++  g_free (fallback_priority);
++  g_free (fallback_unsafe_rehandshake_priority);
+ }
+ 
+ static void
+ g_tls_connection_gnutls_set_handshake_priority (GTlsConnectionGnutls *gnutls)
+ {
+-  gboolean use_ssl3, unsafe_rehandshake;
++  gboolean fallback, unsafe_rehandshake;
+ 
+   if (G_IS_TLS_CLIENT_CONNECTION (gnutls))
+-    use_ssl3 = g_tls_client_connection_get_use_ssl3 (G_TLS_CLIENT_CONNECTION (gnutls));
++    fallback = g_tls_client_connection_get_use_ssl3 (G_TLS_CLIENT_CONNECTION (gnutls));
+   else
+-    use_ssl3 = FALSE;
++    fallback = FALSE;
+   unsafe_rehandshake = (gnutls->priv->rehandshake_mode == G_TLS_REHANDSHAKE_UNSAFELY);
+   gnutls_priority_set (gnutls->priv->session,
+-		       priorities[use_ssl3][unsafe_rehandshake]);
++		       priorities[fallback][unsafe_rehandshake]);
+ }
+ 
+ static gboolean
+diff --git a/tls/tests/connection.c b/tls/tests/connection.c
+index 0df8bb1..0e7b706 100644
+--- a/tls/tests/connection.c
++++ b/tls/tests/connection.c
+@@ -1377,11 +1377,90 @@ test_async_implicit_handshake (TestConnection *test, gconstpointer   data)
+   test->client_connection = NULL;
+ }
+ 
++static void
++quit_on_handshake_complete (GObject      *object,
++			    GAsyncResult *result,
++			    gpointer      user_data)
++{
++  TestConnection *test = user_data;
++  GError *error = NULL;
++
++  g_tls_connection_handshake_finish (G_TLS_CONNECTION (object), result, &error);
++  g_assert_no_error (error);
++
++  g_main_loop_quit (test->loop);
++  return;
++}
++
++#define PRIORITY_SSL_FALLBACK "NORMAL:+VERS-SSL3.0"
++#define PRIORITY_TLS_FALLBACK "NORMAL:+VERS-TLS-ALL:-VERS-SSL3.0"
++
++static void
++test_fallback (gconstpointer data)
++{
++  const char *priority_string = (const char *) data;
++  char *test_name;
++
++  test_name = g_strdup_printf ("/tls/connection/fallback/subprocess/%s", priority_string);
++  g_test_trap_subprocess (test_name, 0, 0);
++  g_test_trap_assert_passed ();
++  g_free (test_name);
++}
++
++static void
++test_fallback_subprocess (TestConnection *test,
++			  gconstpointer   data)
++{
++  GIOStream *connection;
++  GTlsConnection *tlsconn;
++  GError *error = NULL;
++
++  connection = start_echo_server_and_connect_to_it (test);
++  test->client_connection = g_tls_client_connection_new (connection, NULL, &error);
++  g_assert_no_error (error);
++  tlsconn = G_TLS_CONNECTION (test->client_connection);
++  g_object_unref (connection);
++
++  g_tls_client_connection_set_validation_flags (G_TLS_CLIENT_CONNECTION (test->client_connection),
++                                                0);
++  g_tls_client_connection_set_use_ssl3 (G_TLS_CLIENT_CONNECTION (test->client_connection),
++					TRUE);
++  g_tls_connection_handshake_async (tlsconn, G_PRIORITY_DEFAULT, NULL,
++				    quit_on_handshake_complete, test);
++  g_main_loop_run (test->loop);
++
++  /* In 2.42 we don't have the API to test that the correct version was negotiated,
++   * so we merely test that the connection succeeded at all.
++   */
++
++  g_io_stream_close (test->client_connection, NULL, &error);
++  g_assert_no_error (error);
++}
++
+ int
+ main (int   argc,
+       char *argv[])
+ {
+   int ret;
++  int i;
++
++  /* Check if this is a subprocess, and set G_TLS_GNUTLS_PRIORITY
++   * appropriately if so.
++   */
++  for (i = 1; i < argc - 1; i++)
++    {
++      if (!strcmp (argv[i], "-p"))
++	{
++	  const char *priority = argv[i + 1];
++
++	  priority = strrchr (priority, '/');
++	  if (priority++ &&
++	      (g_str_has_prefix (priority, "NORMAL:") ||
++	       g_str_has_prefix (priority, "NONE:")))
++	    g_setenv ("G_TLS_GNUTLS_PRIORITY", priority, TRUE);
++	  break;
++	}
++    }
+ 
+   g_test_init (&argc, &argv, NULL);
+   g_test_bug_base ("http://bugzilla.gnome.org/");
+@@ -1431,6 +1510,15 @@ main (int   argc,
+   g_test_add ("/tls/connection/async-implicit-handshake", TestConnection, NULL,
+               setup_connection, test_async_implicit_handshake, teardown_connection);
+ 
++  g_test_add_data_func ("/tls/connection/fallback/SSL", PRIORITY_SSL_FALLBACK, test_fallback);
++  g_test_add ("/tls/connection/fallback/subprocess/" PRIORITY_SSL_FALLBACK,
++	      TestConnection, NULL,
++              setup_connection, test_fallback_subprocess, teardown_connection);
++  g_test_add_data_func ("/tls/connection/fallback/TLS", PRIORITY_TLS_FALLBACK, test_fallback);
++  g_test_add ("/tls/connection/fallback/subprocess/" PRIORITY_TLS_FALLBACK,
++	      TestConnection, NULL,
++              setup_connection, test_fallback_subprocess, teardown_connection);
++
+   ret = g_test_run();
+ 
+   /* for valgrinding */
+-- 
+2.1.0
+
diff --git a/0002-rh1177964-priority-string.patch b/0002-rh1177964-priority-string.patch
new file mode 100644
index 0000000..b06f27a
--- /dev/null
+++ b/0002-rh1177964-priority-string.patch
@@ -0,0 +1,78 @@
+From f474ec2a887f2ef1dba536683f5a7c8b6dc7e283 Mon Sep 17 00:00:00 2001
+From: Dan Winship <danw at gnome.org>
+Date: Thu, 13 Nov 2014 22:30:13 -0500
+Subject: [PATCH 2/2] gnutls: update default priority string and fallback rules
+
+Change the default "priority" string from "NORMAL:%COMPAT" to
+"NORMAL:%COMPAT:%LATEST_RECORD_VERSION". (Correctly-implemented
+servers won't care either way, but apparently some servers have been
+incorrectly updated for POODLE-safeness by rejecting all handshakes
+with SSL 3.0 in the version field [which had long been recommended for
+compatibility reasons], even if the handshake offered to negotiate TLS
+versions too.)
+
+Change the fallback/"ssl3" priority code so that it never includes
+%LATEST_RECORD_VERSION, but does include %COMPAT even if the default
+priority doesn't (eg, because it was overridden with
+G_TLS_GNUTLS_PRIORITY).
+
+https://bugzilla.gnome.org/show_bug.cgi?id=740087
+---
+ tls/gnutls/gtlsconnection-gnutls.c | 23 +++++++++++++++++++----
+ 1 file changed, 19 insertions(+), 4 deletions(-)
+
+diff --git a/tls/gnutls/gtlsconnection-gnutls.c b/tls/gnutls/gtlsconnection-gnutls.c
+index 444ca36..7436451 100644
+--- a/tls/gnutls/gtlsconnection-gnutls.c
++++ b/tls/gnutls/gtlsconnection-gnutls.c
+@@ -197,6 +197,8 @@ g_tls_connection_gnutls_init (GTlsConnectionGnutls *gnutls)
+ /* First field is "fallback", second is "allow unsafe rehandshaking" */
+ static gnutls_priority_t priorities[2][2];
+ 
++#define DEFAULT_BASE_PRIORITY "NORMAL:%COMPAT:%LATEST_RECORD_VERSION"
++
+ static void
+ g_tls_connection_gnutls_init_priorities (void)
+ {
+@@ -207,12 +209,12 @@ g_tls_connection_gnutls_init_priorities (void)
+ 
+   base_priority = g_getenv ("G_TLS_GNUTLS_PRIORITY");
+   if (!base_priority)
+-    base_priority = "NORMAL:%COMPAT";
++    base_priority = DEFAULT_BASE_PRIORITY;
+   ret = gnutls_priority_init (&priorities[FALSE][FALSE], base_priority, NULL);
+   if (ret == GNUTLS_E_INVALID_REQUEST)
+     {
+       g_warning ("G_TLS_GNUTLS_PRIORITY is invalid; ignoring!");
+-      base_priority = "NORMAL:%COMPAT";
++      base_priority = DEFAULT_BASE_PRIORITY;
+       gnutls_priority_init (&priorities[FALSE][FALSE], base_priority, NULL);
+     }
+ 
+@@ -236,8 +238,21 @@ g_tls_connection_gnutls_init_priorities (void)
+     }
+   else
+     {
+-      fallback_priority = g_strdup_printf ("%s:!VERS-TLS-ALL:+VERS-%s",
+-					   base_priority,
++      gchar *cleaned_base, *p, *rest;
++
++      /* fallback_priority should be based on base_priority, except
++       * that we don't want %LATEST_RECORD_VERSION in it.
++       */
++      cleaned_base = g_strdup (base_priority);
++      p = strstr (cleaned_base, ":%LATEST_RECORD_VERSION");
++      if (p)
++	{
++	  rest = p + strlen (":%LATEST_RECORD_VERSION");
++	  memmove (p, rest, strlen (rest) + 1);
++	}
++
++      fallback_priority = g_strdup_printf ("%s:%%COMPAT:!VERS-TLS-ALL:+VERS-%s",
++					   cleaned_base,
+ 					   gnutls_protocol_get_name (fallback_proto));
+     }
+   fallback_unsafe_rehandshake_priority = g_strdup_printf ("%s:%%UNSAFE_RENEGOTIATION",
+-- 
+2.1.0
+
diff --git a/glib-networking.spec b/glib-networking.spec
index ca038d8..46d678e 100644
--- a/glib-networking.spec
+++ b/glib-networking.spec
@@ -2,7 +2,7 @@
 
 Name:           glib-networking
 Version:        2.42.0
-Release:        1%{?dist}
+Release:        2%{?dist}
 Summary:        Networking support for GLib
 
 Group:          Development/Libraries
@@ -10,6 +10,9 @@ License:        LGPLv2+
 URL:            http://www.gnome.org
 Source:         http://download.gnome.org/sources/glib-networking/2.42/%{name}-%{version}.tar.xz
 
+Patch1: 0001-rh1177964-fallback-semantics.patch
+Patch2: 0002-rh1177964-priority-string.patch
+
 BuildRequires:  glib2-devel >= %{glib2_version}
 BuildRequires:  libproxy-devel
 BuildRequires:  gnutls-devel
@@ -38,6 +41,8 @@ the functionality of the installed glib-networking package.
 
 %prep
 %setup -q
+%patch1 -p1 -b .0001-rh1177964-fallback-semantics.patch
+%patch2 -p1 -b .0002-rh1177964-priority-string.patch
 
 
 %build
@@ -72,6 +77,9 @@ gio-querymodules-%{__isa_bits} %{_libdir}/gio/modules
 %{_datadir}/installed-tests
 
 %changelog
+* Fri Mar  6 2015 Dan Winship <danw at redhat.com> - 2.42.0-2
+- Improve priority string and fallback rules for the post-POODLE world (#1177964)
+
 * Mon Sep 22 2014 Kalev Lember <kalevlember at gmail.com> - 2.42.0-1
 - Update to 2.42.0
 


More information about the scm-commits mailing list