[glib-networking] gnutls: move some code from finish_handshake to handshake
- From: Dan Winship <danw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib-networking] gnutls: move some code from finish_handshake to handshake
- Date: Sun, 9 Dec 2012 15:35:26 +0000 (UTC)
commit c8a597e2ed8e181fd65ef3b777fe010d7409093b
Author: Dan Winship <danw gnome org>
Date: Wed Dec 5 15:05:21 2012 -0500
gnutls: move some code from finish_handshake to handshake
verify_peer_certificate() doesn't emit signals, and might block, so it
should happen in the handshake thread. And then with that moved there
there's no reason to not do the other (non-interactive)
certificate-related checks there as well.
tls/gnutls/gtlsconnection-gnutls.c | 160 +++++++++++++++++++-----------------
1 files changed, 85 insertions(+), 75 deletions(-)
---
diff --git a/tls/gnutls/gtlsconnection-gnutls.c b/tls/gnutls/gtlsconnection-gnutls.c
index ef53bb2..a0a221f 100644
--- a/tls/gnutls/gtlsconnection-gnutls.c
+++ b/tls/gnutls/gtlsconnection-gnutls.c
@@ -100,6 +100,9 @@ struct _GTlsConnectionGnutlsPrivate
GTlsCertificate *certificate, *peer_certificate;
GTlsCertificateFlags peer_certificate_errors;
+ GTlsCertificate *peer_certificate_tmp;
+ GTlsCertificateFlags peer_certificate_errors_tmp;
+
gboolean require_close_notify;
GTlsRehandshakeMode rehandshake_mode;
gboolean is_system_certdb;
@@ -291,6 +294,7 @@ g_tls_connection_gnutls_finalize (GObject *object)
g_clear_object (&gnutls->priv->database);
g_clear_object (&gnutls->priv->certificate);
g_clear_object (&gnutls->priv->peer_certificate);
+ g_clear_object (&gnutls->priv->peer_certificate_tmp);
#ifdef HAVE_PKCS11
p11_kit_pin_unregister_callback (gnutls->priv->interaction_id,
@@ -1035,67 +1039,6 @@ g_tls_connection_gnutls_push_func (gnutls_transport_ptr_t transport_data,
return ret;
}
-static void
-handshake_thread (GTask *task,
- gpointer object,
- gpointer task_data,
- GCancellable *cancellable)
-{
- GTlsConnectionGnutls *gnutls = object;
- gboolean is_client;
- GError *error = NULL;
- int ret;
-
- gnutls->priv->started_handshake = FALSE;
-
- if (!claim_op (gnutls, G_TLS_CONNECTION_GNUTLS_OP_HANDSHAKE,
- TRUE, cancellable, &error))
- {
- g_task_return_error (task, error);
- return;
- }
-
- g_clear_error (&gnutls->priv->handshake_error);
-
- is_client = G_IS_TLS_CLIENT_CONNECTION (gnutls);
-
- if (!is_client && gnutls->priv->ever_handshaked &&
- !gnutls->priv->implicit_handshake)
- {
- BEGIN_GNUTLS_IO (gnutls, G_IO_IN | G_IO_OUT, TRUE, cancellable);
- ret = gnutls_rehandshake (gnutls->priv->session);
- END_GNUTLS_IO (gnutls, G_IO_IN | G_IO_OUT, ret,
- _("Error performing TLS handshake: %s"), &error);
-
- if (error)
- {
- g_task_return_error (task, error);
- return;
- }
- }
-
- gnutls->priv->started_handshake = TRUE;
-
- g_clear_object (&gnutls->priv->peer_certificate);
- gnutls->priv->peer_certificate_errors = 0;
-
- g_tls_connection_gnutls_set_handshake_priority (gnutls);
-
- BEGIN_GNUTLS_IO (gnutls, G_IO_IN | G_IO_OUT, TRUE, cancellable);
- ret = gnutls_handshake (gnutls->priv->session);
- END_GNUTLS_IO (gnutls, G_IO_IN | G_IO_OUT, ret,
- _("Error performing TLS handshake: %s"), &error);
-
- if (error)
- {
- g_task_return_error (task, error);
- }
- else
- {
- gnutls->priv->ever_handshaked = TRUE;
- g_task_return_boolean (task, TRUE);
- }
-}
static GTlsCertificate *
get_peer_certificate_from_session (GTlsConnectionGnutls *gnutls)
@@ -1169,6 +1112,82 @@ verify_peer_certificate (GTlsConnectionGnutls *gnutls,
return errors;
}
+static void
+handshake_thread (GTask *task,
+ gpointer object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ GTlsConnectionGnutls *gnutls = object;
+ gboolean is_client;
+ GError *error = NULL;
+ int ret;
+
+ gnutls->priv->started_handshake = FALSE;
+
+ if (!claim_op (gnutls, G_TLS_CONNECTION_GNUTLS_OP_HANDSHAKE,
+ TRUE, cancellable, &error))
+ {
+ g_task_return_error (task, error);
+ return;
+ }
+
+ g_clear_error (&gnutls->priv->handshake_error);
+
+ is_client = G_IS_TLS_CLIENT_CONNECTION (gnutls);
+
+ if (!is_client && gnutls->priv->ever_handshaked &&
+ !gnutls->priv->implicit_handshake)
+ {
+ BEGIN_GNUTLS_IO (gnutls, G_IO_IN | G_IO_OUT, TRUE, cancellable);
+ ret = gnutls_rehandshake (gnutls->priv->session);
+ END_GNUTLS_IO (gnutls, G_IO_IN | G_IO_OUT, ret,
+ _("Error performing TLS handshake: %s"), &error);
+
+ if (error)
+ {
+ g_task_return_error (task, error);
+ return;
+ }
+ }
+
+ gnutls->priv->started_handshake = TRUE;
+
+ g_clear_object (&gnutls->priv->peer_certificate);
+ gnutls->priv->peer_certificate_errors = 0;
+
+ g_tls_connection_gnutls_set_handshake_priority (gnutls);
+
+ BEGIN_GNUTLS_IO (gnutls, G_IO_IN | G_IO_OUT, TRUE, cancellable);
+ ret = gnutls_handshake (gnutls->priv->session);
+ END_GNUTLS_IO (gnutls, G_IO_IN | G_IO_OUT, ret,
+ _("Error performing TLS handshake: %s"), &error);
+
+ if (ret == 0 && gnutls_certificate_type_get (gnutls->priv->session) == GNUTLS_CRT_X509)
+ {
+ gnutls->priv->peer_certificate_tmp = get_peer_certificate_from_session (gnutls);
+ if (gnutls->priv->peer_certificate_tmp)
+ gnutls->priv->peer_certificate_errors_tmp = verify_peer_certificate (gnutls, gnutls->priv->peer_certificate_tmp);
+ else if (G_IS_TLS_CLIENT_CONNECTION (gnutls))
+ {
+ g_set_error_literal (&error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
+ _("Server did not return a valid TLS certificate"));
+ }
+ }
+
+ G_TLS_CONNECTION_GNUTLS_GET_CLASS (gnutls)->finish_handshake (gnutls, &error);
+
+ if (error)
+ {
+ g_task_return_error (task, error);
+ }
+ else
+ {
+ gnutls->priv->ever_handshaked = TRUE;
+ g_task_return_boolean (task, TRUE);
+ }
+}
+
static gboolean
accept_peer_certificate (GTlsConnectionGnutls *gnutls,
GTlsCertificate *peer_certificate,
@@ -1216,15 +1235,13 @@ finish_handshake (GTlsConnectionGnutls *gnutls,
g_assert (error != NULL);
- if (g_task_propagate_boolean (task, error) &&
- gnutls_certificate_type_get (gnutls->priv->session) == GNUTLS_CRT_X509)
- peer_certificate = get_peer_certificate_from_session (gnutls);
- else
- peer_certificate = NULL;
+ peer_certificate = gnutls->priv->peer_certificate_tmp;
+ gnutls->priv->peer_certificate_tmp = NULL;
+ peer_certificate_errors = gnutls->priv->peer_certificate_errors_tmp;
+ gnutls->priv->peer_certificate_errors_tmp = 0;
- if (peer_certificate)
+ if (g_task_propagate_boolean (task, error) && peer_certificate)
{
- peer_certificate_errors = verify_peer_certificate (gnutls, peer_certificate);
if (!accept_peer_certificate (gnutls, peer_certificate,
peer_certificate_errors))
{
@@ -1237,13 +1254,6 @@ finish_handshake (GTlsConnectionGnutls *gnutls,
g_object_notify (G_OBJECT (gnutls), "peer-certificate");
g_object_notify (G_OBJECT (gnutls), "peer-certificate-errors");
}
- else if (error && !*error && G_IS_TLS_CLIENT_CONNECTION (gnutls))
- {
- g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
- _("Server did not return a valid TLS certificate"));
- }
-
- G_TLS_CONNECTION_GNUTLS_GET_CLASS (gnutls)->finish_handshake (gnutls, error);
if (*error && gnutls->priv->started_handshake)
gnutls->priv->handshake_error = g_error_copy (*error);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]