Commit 03bc29b9 authored by Michael Catanzaro's avatar Michael Catanzaro Committed by Ignacio Casal Quinteiro

Fail unsafe rehandshake attempts initiated by API request (take two)

This reimplements 21f765e2, 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.
parent a39e1bc6
Pipeline #92746 passed with stage
in 6 minutes and 23 seconds
......@@ -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)
{
......
......@@ -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
......
......@@ -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
......
......@@ -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;
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment