[glib-networking/mcatanzaro/insecure-renegotiation-check: 2/2] Fail unsafe rehandshake attempts initiated by API request (take two)



commit 03bc29b91f66efdedc31dd8dd1f8dd20a0a7c480
Author: Michael Catanzaro <mcatanzaro igalia com>
Date:   Mon Jul 1 19:59:49 2019 -0500

    Fail unsafe rehandshake attempts initiated by API request (take two)
    
    This reimplements 21f765e24c9a9f7da6860ce6b4affc74a46648ee, which got
    lost when I ported the GnuTLS code to the base class. I've had a pending
    TODO to restore this check for a while now.
    
    It's not possible to test because we don't test against an old peer that
    lacks secure renegotiation support.

 tls/base/gtlsconnection-base.c       |   8 +++
 tls/base/gtlsconnection-base.h       | 135 ++++++++++++++++++-----------------
 tls/gnutls/gtlsconnection-gnutls.c   |  11 +++
 tls/openssl/gtlsconnection-openssl.c |  13 ++++
 tls/tests/connection.c               |   1 +
 5 files changed, 104 insertions(+), 64 deletions(-)
---
diff --git a/tls/base/gtlsconnection-base.c b/tls/base/gtlsconnection-base.c
index b1225f5..5230152 100644
--- a/tls/base/gtlsconnection-base.c
+++ b/tls/base/gtlsconnection-base.c
@@ -1332,6 +1332,14 @@ handshake_thread (GTask        *task,
     {
       GTlsConnectionBaseStatus status;
 
+      if (priv->rehandshake_mode != G_TLS_REHANDSHAKE_UNSAFELY &&
+          tls_class->safe_renegotiation_status (tls) != G_TLS_SAFE_RENEGOTIATION_SUPPORTED_BY_PEER)
+        {
+          g_task_return_new_error (task, G_TLS_ERROR, G_TLS_ERROR_MISC,
+                                   _("Peer does not support safe renegotiation"));
+          return;
+        }
+
       /* Adjust the timeout for the next operation in the sequence. */
       if (timeout > 0)
         {
diff --git a/tls/base/gtlsconnection-base.h b/tls/base/gtlsconnection-base.h
index 3cbb14c..98632ad 100644
--- a/tls/base/gtlsconnection-base.h
+++ b/tls/base/gtlsconnection-base.h
@@ -47,76 +47,83 @@ typedef enum {
   G_TLS_DIRECTION_WRITE = 1 << 1,
 } GTlsDirection;
 
+typedef enum {
+  G_TLS_SAFE_RENEGOTIATION_SUPPORTED_BY_PEER,
+  G_TLS_SAFE_RENEGOTIATION_UNSUPPORTED
+} GTlsSafeRenegotiationStatus;
+
 #define G_TLS_DIRECTION_BOTH (G_TLS_DIRECTION_READ | G_TLS_DIRECTION_WRITE)
 
 struct _GTlsConnectionBaseClass
 {
   GTlsConnectionClass parent_class;
 
-  GTlsConnectionBaseStatus (*request_rehandshake)        (GTlsConnectionBase   *tls,
-                                                          gint64                timeout,
-                                                          GCancellable         *cancellable,
-                                                          GError              **error);
-
-  void                     (*prepare_handshake)          (GTlsConnectionBase   *tls,
-                                                          gchar               **advertised_protocols);
-  GTlsConnectionBaseStatus (*handshake_thread_handshake) (GTlsConnectionBase   *tls,
-                                                          gint64                timeout,
-                                                          GCancellable         *cancellable,
-                                                          GError              **error);
-  GTlsCertificate         *(*retrieve_peer_certificate)  (GTlsConnectionBase   *tls);
-  GTlsCertificateFlags     (*verify_peer_certificate)    (GTlsConnectionBase   *tls,
-                                                          GTlsCertificate      *certificate,
-                                                          GTlsCertificateFlags  flags);
-  void                     (*complete_handshake)         (GTlsConnectionBase   *tls,
-                                                          gchar               **negotiated_protocol,
-                                                          GError              **error);
-
-  gboolean                 (*is_session_resumed)         (GTlsConnectionBase   *tls);
-
-  void                     (*push_io)                    (GTlsConnectionBase   *tls,
-                                                          GIOCondition          direction,
-                                                          gint64                timeout,
-                                                          GCancellable         *cancellable);
-  GTlsConnectionBaseStatus (*pop_io)                     (GTlsConnectionBase   *tls,
-                                                          GIOCondition          direction,
-                                                          gboolean              success,
-                                                          GError              **error);
-
-  GTlsConnectionBaseStatus (*read_fn)                    (GTlsConnectionBase   *tls,
-                                                          void                 *buffer,
-                                                          gsize                 count,
-                                                          gint64                timeout,
-                                                          gssize               *nread,
-                                                          GCancellable         *cancellable,
-                                                          GError              **error);
-  GTlsConnectionBaseStatus (*read_message_fn)            (GTlsConnectionBase   *tls,
-                                                          GInputVector         *vectors,
-                                                          guint                 num_vectors,
-                                                          gint64                timeout,
-                                                          gssize               *nread,
-                                                          GCancellable         *cancellable,
-                                                          GError              **error);
-
-  GTlsConnectionBaseStatus (*write_fn)                   (GTlsConnectionBase   *tls,
-                                                          const void           *buffer,
-                                                          gsize                 count,
-                                                          gint64                timeout,
-                                                          gssize               *nwrote,
-                                                          GCancellable         *cancellable,
-                                                          GError              **error);
-  GTlsConnectionBaseStatus (*write_message_fn)           (GTlsConnectionBase   *tls,
-                                                          GOutputVector        *vectors,
-                                                          guint                 num_vectors,
-                                                          gint64                timeout,
-                                                          gssize               *nwrote,
-                                                          GCancellable         *cancellable,
-                                                          GError              **error);
-
-  GTlsConnectionBaseStatus (*close_fn)                   (GTlsConnectionBase   *tls,
-                                                          gint64                timeout,
-                                                          GCancellable         *cancellable,
-                                                          GError              **error);
+  GTlsConnectionBaseStatus    (*request_rehandshake)        (GTlsConnectionBase   *tls,
+                                                             gint64                timeout,
+                                                             GCancellable         *cancellable,
+                                                             GError              **error);
+
+  void                        (*prepare_handshake)          (GTlsConnectionBase   *tls,
+                                                             gchar               **advertised_protocols);
+  GTlsConnectionBaseStatus    (*handshake_thread_handshake) (GTlsConnectionBase   *tls,
+                                                             gint64                timeout,
+                                                             GCancellable         *cancellable,
+                                                             GError              **error);
+  GTlsCertificate            *(*retrieve_peer_certificate)  (GTlsConnectionBase   *tls);
+  GTlsCertificateFlags        (*verify_peer_certificate)    (GTlsConnectionBase   *tls,
+                                                             GTlsCertificate      *certificate,
+                                                             GTlsCertificateFlags  flags);
+  void                        (*complete_handshake)         (GTlsConnectionBase   *tls,
+                                                             gchar               **negotiated_protocol,
+                                                             GError              **error);
+
+  gboolean                    (*is_session_resumed)         (GTlsConnectionBase   *tls);
+
+  void                        (*push_io)                    (GTlsConnectionBase   *tls,
+                                                             GIOCondition          direction,
+                                                             gint64                timeout,
+                                                             GCancellable         *cancellable);
+  GTlsConnectionBaseStatus    (*pop_io)                     (GTlsConnectionBase   *tls,
+                                                             GIOCondition          direction,
+                                                             gboolean              success,
+                                                             GError              **error);
+
+  GTlsConnectionBaseStatus    (*read_fn)                    (GTlsConnectionBase   *tls,
+                                                             void                 *buffer,
+                                                             gsize                 count,
+                                                             gint64                timeout,
+                                                             gssize               *nread,
+                                                             GCancellable         *cancellable,
+                                                             GError              **error);
+  GTlsConnectionBaseStatus    (*read_message_fn)            (GTlsConnectionBase   *tls,
+                                                             GInputVector         *vectors,
+                                                             guint                 num_vectors,
+                                                             gint64                timeout,
+                                                             gssize               *nread,
+                                                             GCancellable         *cancellable,
+                                                             GError              **error);
+
+  GTlsConnectionBaseStatus    (*write_fn)                   (GTlsConnectionBase   *tls,
+                                                             const void           *buffer,
+                                                             gsize                 count,
+                                                             gint64                timeout,
+                                                             gssize               *nwrote,
+                                                             GCancellable         *cancellable,
+                                                             GError              **error);
+  GTlsConnectionBaseStatus    (*write_message_fn)           (GTlsConnectionBase   *tls,
+                                                             GOutputVector        *vectors,
+                                                             guint                 num_vectors,
+                                                             gint64                timeout,
+                                                             gssize               *nwrote,
+                                                             GCancellable         *cancellable,
+                                                             GError              **error);
+
+  GTlsConnectionBaseStatus    (*close_fn)                   (GTlsConnectionBase   *tls,
+                                                             gint64                timeout,
+                                                             GCancellable         *cancellable,
+                                                             GError              **error);
+
+  GTlsSafeRenegotiationStatus (*safe_renegotiation_status)  (GTlsConnectionBase    *tls);
 };
 
 gboolean                  g_tls_connection_base_handshake_thread_verify_certificate
diff --git a/tls/gnutls/gtlsconnection-gnutls.c b/tls/gnutls/gtlsconnection-gnutls.c
index 1ac803a..0990006 100644
--- a/tls/gnutls/gtlsconnection-gnutls.c
+++ b/tls/gnutls/gtlsconnection-gnutls.c
@@ -1096,6 +1096,16 @@ g_tls_connection_gnutls_close (GTlsConnectionBase  *tls,
   return status;
 }
 
+static GTlsSafeRenegotiationStatus
+g_tls_connection_gnutls_safe_renegotiation_status (GTlsConnectionBase *tls)
+{
+  GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (tls);
+  GTlsConnectionGnutlsPrivate *priv = g_tls_connection_gnutls_get_instance_private (gnutls);
+
+  return gnutls_safe_renegotiation_status (priv->session) ? G_TLS_SAFE_RENEGOTIATION_SUPPORTED_BY_PEER
+                                                          : G_TLS_SAFE_RENEGOTIATION_UNSUPPORTED;
+}
+
 static void
 g_tls_connection_gnutls_class_init (GTlsConnectionGnutlsClass *klass)
 {
@@ -1115,6 +1125,7 @@ g_tls_connection_gnutls_class_init (GTlsConnectionGnutlsClass *klass)
   base_class->write_fn                   = g_tls_connection_gnutls_write;
   base_class->write_message_fn           = g_tls_connection_gnutls_write_message;
   base_class->close_fn                   = g_tls_connection_gnutls_close;
+  base_class->safe_renegotiation_status  = g_tls_connection_gnutls_safe_renegotiation_status;
 }
 
 static void
diff --git a/tls/openssl/gtlsconnection-openssl.c b/tls/openssl/gtlsconnection-openssl.c
index d3c39b1..3745766 100644
--- a/tls/openssl/gtlsconnection-openssl.c
+++ b/tls/openssl/gtlsconnection-openssl.c
@@ -497,6 +497,18 @@ g_tls_connection_openssl_close (GTlsConnectionBase  *tls,
   return status;
 }
 
+static GTlsSafeRenegotiationStatus
+g_tls_connection_openssl_safe_renegotiation_status (GTlsConnectionBase *tls)
+{
+  GTlsConnectionOpenssl *openssl = G_TLS_CONNECTION_OPENSSL (tls);
+  SSL *ssl;
+
+  ssl = g_tls_connection_openssl_get_ssl (openssl);
+
+  return SSL_get_secure_renegotiation_support (ssl) ? G_TLS_SAFE_RENEGOTIATION_SUPPORTED_BY_PEER
+                                                    : G_TLS_SAFE_RENEGOTIATION_UNSUPPORTED;
+}
+
 static void
 g_tls_connection_openssl_class_init (GTlsConnectionOpensslClass *klass)
 {
@@ -513,6 +525,7 @@ g_tls_connection_openssl_class_init (GTlsConnectionOpensslClass *klass)
   base_class->read_fn                    = g_tls_connection_openssl_read;
   base_class->write_fn                   = g_tls_connection_openssl_write;
   base_class->close_fn                   = g_tls_connection_openssl_close;
+  base_class->safe_renegotiation_status  = g_tls_connection_openssl_safe_renegotiation_status;
 }
 
 static int data_index = -1;
diff --git a/tls/tests/connection.c b/tls/tests/connection.c
index e5cd537..31aaa1c 100644
--- a/tls/tests/connection.c
+++ b/tls/tests/connection.c
@@ -1053,6 +1053,7 @@ test_client_auth_rehandshake (TestConnection *test,
                               gconstpointer   data)
 {
 #ifdef BACKEND_IS_OPENSSL
+  /* FIXME: this doesn't make sense, we should support safe renegotation */
   g_test_skip ("the server avoids rehandshake to avoid the security problem CVE-2009-3555");
   return;
 #endif


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]