[glib-networking/mcatanzaro/base-rebase] Progress
- From: Michael Catanzaro <mcatanzaro src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib-networking/mcatanzaro/base-rebase] Progress
- Date: Mon, 29 Apr 2019 03:49:10 +0000 (UTC)
commit 63ad9580c0e4d08ea791e71c555f6c06701d8caf
Author: Michael Catanzaro <mcatanzaro igalia com>
Date: Sun Apr 28 22:47:24 2019 -0500
Progress
tls/base/gtlsconnection-base.c | 174 +++++++++++++++++--
tls/base/gtlsconnection-base.h | 270 ++++++++++++++---------------
tls/gnutls/gtlsconnection-gnutls.c | 166 +-----------------
tls/gnutls/meson.build | 2 -
tls/openssl/gtlsclientconnection-openssl.c | 64 ++++++-
tls/openssl/gtlsconnection-openssl.c | 161 ++---------------
tls/openssl/gtlsserverconnection-openssl.c | 9 +-
7 files changed, 372 insertions(+), 474 deletions(-)
---
diff --git a/tls/base/gtlsconnection-base.c b/tls/base/gtlsconnection-base.c
index 8602265..91fef0a 100644
--- a/tls/base/gtlsconnection-base.c
+++ b/tls/base/gtlsconnection-base.c
@@ -1123,12 +1123,81 @@ g_tls_connection_base_condition_wait (GDatagramBased *datagram_based,
return !g_cancellable_set_error_if_cancelled (cancellable, error);
}
-void
-g_tls_connection_base_set_peer_certificate (GTlsConnectionBase *tls,
- GTlsCertificate *peer_certificate,
- GTlsCertificateFlags peer_certificate_errors)
+static GTlsCertificateFlags
+verify_peer_certificate (GTlsConnectionBase *tls,
+ GTlsCertificate *peer_certificate)
{
- GTlsConnectionBasePrivate *priv = g_tls_connection_base_get_instance_private (tls);
+ GSocketConnectable *peer_identity;
+ GTlsDatabase *database;
+ GTlsCertificateFlags errors;
+ gboolean is_client;
+
+ is_client = G_IS_TLS_CLIENT_CONNECTION (tls);
+
+ if (!is_client)
+ peer_identity = NULL;
+ else if (!g_tls_connection_base_is_dtls (tls))
+ peer_identity = g_tls_client_connection_get_server_identity (G_TLS_CLIENT_CONNECTION (tls));
+ else
+ peer_identity = g_dtls_client_connection_get_server_identity (G_DTLS_CLIENT_CONNECTION (tls));
+
+ errors = 0;
+
+ database = g_tls_connection_get_database (G_TLS_CONNECTION (tls));
+ if (database == NULL)
+ {
+ errors |= G_TLS_CERTIFICATE_UNKNOWN_CA;
+ errors |= g_tls_certificate_verify (peer_certificate, peer_identity, NULL);
+ }
+ else
+ {
+ GError *error = NULL;
+
+ errors |= g_tls_database_verify_chain (database, peer_certificate,
+ is_client ?
+ G_TLS_DATABASE_PURPOSE_AUTHENTICATE_SERVER :
+ G_TLS_DATABASE_PURPOSE_AUTHENTICATE_CLIENT,
+ peer_identity,
+ g_tls_connection_get_interaction (G_TLS_CONNECTION (tls)),
+ G_TLS_DATABASE_VERIFY_NONE,
+ NULL, &error);
+ if (error)
+ {
+ g_warning ("failure verifying certificate chain: %s",
+ error->message);
+ g_assert (errors != 0);
+ g_clear_error (&error);
+ }
+ }
+
+ if (tls_class->verify_peer_certificate)
+ errors |= tls_class->verify_peer_certificate (tls, peer_certificate, errors);
+
+ return errors;
+}
+
+static void
+update_peer_certificate_and_compute_errors (GTlsConnectionBase *tls)
+{
+ GTlsConnectionBasePrivate *priv = g_tls_connection_base_get_instance_private (gnutls);
+ GTlsCertificate *peer_certificate = NULL;
+ GTlsCertificateFlags peer_certificate_errors = 0;
+
+ /* This function must be called from the handshake context thread
+ * (probably the main thread, NOT the handshake thread) because
+ * it emits notifies that are application-visible.
+ *
+ * verify_certificate_mutex should be locked.
+ */
+ g_assert (priv->handshake_context);
+ g_assert (g_main_context_is_owner (priv->handshake_context));
+
+ if (gnutls_certificate_type_get (priv->session) == GNUTLS_CRT_X509)
+ {
+ peer_certificate = get_peer_certificate_from_session (tls);
+ if (peer_certificate)
+ peer_certificate_errors = verify_peer_certificate (tls, peer_certificate);
+ }
g_set_object (&priv->peer_certificate, peer_certificate);
@@ -1138,6 +1207,89 @@ g_tls_connection_base_set_peer_certificate (GTlsConnectionBase *tls,
g_object_notify (G_OBJECT (tls), "peer-certificate-errors");
}
+static gboolean
+accept_or_reject_peer_certificate (gpointer user_data)
+{
+ GTlsConnectionBase *tls = user_data;
+ GTlsConnectionBasePrivate *priv = g_tls_connection_base_get_instance_private (tls);
+ gboolean accepted = FALSE;
+
+ g_assert (g_main_context_is_owner (priv->handshake_context));
+
+ g_mutex_lock (&priv->verify_certificate_mutex);
+
+ update_peer_certificate_and_compute_errors (tls);
+
+ if (G_IS_TLS_CLIENT_CONNECTION (tls) && priv->peer_certificate != NULL)
+ {
+ GTlsCertificateFlags validation_flags;
+
+ if (!g_tls_connection_base_is_dtls (tls))
+ validation_flags =
+ g_tls_client_connection_get_validation_flags (G_TLS_CLIENT_CONNECTION (tls));
+ else
+ validation_flags =
+ g_dtls_client_connection_get_validation_flags (G_DTLS_CLIENT_CONNECTION (tls));
+
+ if ((priv->peer_certificate_errors & validation_flags) == 0)
+ accepted = TRUE;
+ }
+
+ if (!accepted)
+ {
+ g_main_context_pop_thread_default (priv->handshake_context);
+ accepted = g_tls_connection_emit_accept_certificate (G_TLS_CONNECTION (tls),
+ priv->peer_certificate,
+ priv->peer_certificate_errors);
+ g_main_context_push_thread_default (priv->handshake_context);
+ }
+
+ priv->peer_certificate_accepted = accepted;
+
+ /* This has to be the very last statement before signaling the
+ * condition variable because otherwise the code could spuriously
+ * wakeup and continue before we are done here.
+ */
+ priv->peer_certificate_examined = TRUE;
+
+ g_cond_signal (&priv->verify_certificate_condition);
+ g_mutex_unlock (&priv->verify_certificate_mutex);
+
+ g_object_notify (G_OBJECT (tls), "peer-certificate");
+ g_object_notify (G_OBJECT (tls), "peer-certificate-errors");
+
+ return G_SOURCE_REMOVE;
+}
+
+gboolean
+g_tls_connection_base_handshake_thread_verify_certificate (GTlsConnectionBase *tls)
+{
+ GTlsConnectionBasePrivate *priv = g_tls_connection_base_get_instance_private (tls);
+
+ g_mutex_lock (&priv->verify_certificate_mutex);
+ priv->peer_certificate_examined = FALSE;
+ priv->peer_certificate_accepted = FALSE;
+ g_mutex_unlock (&priv->verify_certificate_mutex);
+
+ /* Invoke the callback on the handshake context's thread. This is
+ * necessary because we need to ensure the accept-certificate signal
+ * is emitted on the original thread.
+ */
+ g_assert (priv->handshake_context);
+ g_main_context_invoke (priv->handshake_context, accept_or_reject_peer_certificate, gnutls);
+
+ /* We'll block the handshake thread until the original thread has
+ * decided whether to accept the certificate.
+ */
+ g_mutex_lock (&priv->verify_certificate_mutex);
+ while (!priv->peer_certificate_examined)
+ g_cond_wait (&priv->verify_certificate_condition, &priv->verify_certificate_mutex);
+ accepted = priv->peer_certificate_accepted;
+ g_mutex_unlock (&priv->verify_certificate_mutex);
+
+ return accepted;
+}
+
static void
handshake_thread (GTask *task,
gpointer object,
@@ -2327,14 +2479,14 @@ g_tls_connection_base_datagram_based_iface_init (GDatagramBasedInterface *iface)
}
void
-GTLS_DEBUG (gpointer gnutls,
+GTLS_DEBUG (gpointer connection,
const char *message,
...)
{
char *result = NULL;
int ret;
- g_assert (G_IS_TLS_CONNECTION (gnutls));
+ g_assert (G_IS_TLS_CONNECTION (connection));
va_list args;
va_start (args, message);
@@ -2342,10 +2494,10 @@ GTLS_DEBUG (gpointer gnutls,
ret = g_vasprintf (&result, message, args);
g_assert (ret > 0);
- if (G_IS_TLS_CLIENT_CONNECTION (gnutls))
- g_printf ("CLIENT %p: ", gnutls);
- else if (G_IS_TLS_SERVER_CONNECTION (gnutls))
- g_printf ("SERVER %p: ", gnutls);
+ if (G_IS_TLS_CLIENT_CONNECTION (connection))
+ g_printf ("CLIENT %p: ", connection;
+ else if (G_IS_TLS_SERVER_CONNECTION (connection))
+ g_printf ("SERVER %p: ", connection);
else
g_assert_not_reached ();
diff --git a/tls/base/gtlsconnection-base.h b/tls/base/gtlsconnection-base.h
index 66e2048..e7febf6 100644
--- a/tls/base/gtlsconnection-base.h
+++ b/tls/base/gtlsconnection-base.h
@@ -43,9 +43,9 @@ typedef enum {
} GTlsConnectionBaseStatus;
typedef enum {
- G_TLS_DIRECTION_NONE = 0,
- G_TLS_DIRECTION_READ = 1 << 0,
- G_TLS_DIRECTION_WRITE = 1 << 1,
+ G_TLS_DIRECTION_NONE = 0,
+ G_TLS_DIRECTION_READ = 1 << 0,
+ G_TLS_DIRECTION_WRITE = 1 << 1,
} GTlsDirection;
#define G_TLS_DIRECTION_BOTH (G_TLS_DIRECTION_READ | G_TLS_DIRECTION_WRITE)
@@ -54,141 +54,139 @@ 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);
- void (*complete_handshake) (GTlsConnectionBase *tls,
- gchar **negotiated_protocol,
- GError **error);
-
- 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);
+ GTlsCertificateFlags (*verify_peer_certificate) (GTlsConnenctionBase *tls,
+ GTlsCertificate *certificate,
+ GTlsCertificateFlags flags);
+ void (*complete_handshake) (GTlsConnectionBase *tls,
+ gchar **negotiated_protocol,
+ GError **error);
+
+ 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);
};
-void g_tls_connection_base_set_peer_certificate (GTlsConnectionBase *tls,
- GTlsCertificate *peer_certificate,
- GTlsCertificateFlags peer_certificate_errors);
-
-void g_tls_connection_base_push_io (GTlsConnectionBase *tls,
- GIOCondition direction,
- gint64 timeout,
- GCancellable *cancellable);
-GTlsConnectionBaseStatus
- g_tls_connection_base_pop_io (GTlsConnectionBase *tls,
- GIOCondition direction,
- gboolean success,
- GError **error);
-
-gssize g_tls_connection_base_read (GTlsConnectionBase *tls,
- void *buffer,
- gsize size,
- gint64 timeout,
- GCancellable *cancellable,
- GError **error);
-gssize g_tls_connection_base_write (GTlsConnectionBase *tls,
- const void *buffer,
- gsize size,
- gint64 timeout,
- GCancellable *cancellable,
- GError **error);
-
-gboolean g_tls_connection_base_check (GTlsConnectionBase *tls,
- GIOCondition condition);
-gboolean g_tls_connection_base_base_check (GTlsConnectionBase *tls,
- GIOCondition condition);
-GSource *g_tls_connection_base_create_source (GTlsConnectionBase *tls,
- GIOCondition condition,
- GCancellable *cancellable);
-
-gboolean g_tls_connection_base_close_internal (GIOStream *stream,
- GTlsDirection direction,
- gint64 timeout,
- GCancellable *cancellable,
- GError **error);
-
-gboolean g_tls_connection_base_is_dtls (GTlsConnectionBase *tls);
-
-GDatagramBased *g_tls_connection_base_get_base_socket (GTlsConnectionBase *tls);
-
-GIOStream *g_tls_connection_base_get_base_iostream (GTlsConnectionBase *tls);
-GPollableInputStream *g_tls_connection_base_get_base_istream (GTlsConnectionBase *tls);
-GPollableOutputStream *g_tls_connection_base_get_base_ostream (GTlsConnectionBase *tls);
-
-void g_tls_connection_base_set_missing_requested_client_certificate
- (GTlsConnectionBase *tls);
-
-GError **g_tls_connection_base_get_certificate_error (GTlsConnectionBase *tls);
-GError **g_tls_connection_base_get_read_error (GTlsConnectionBase *tls);
-GError **g_tls_connection_base_get_write_error (GTlsConnectionBase *tls);
-
-gint64 g_tls_connection_base_get_read_timeout (GTlsConnectionBase *tls);
-gint64 g_tls_connection_base_get_write_timeout (GTlsConnectionBase *tls);
-
-gboolean g_tls_connection_base_is_handshaking (GTlsConnectionBase *tls);
-
-gboolean g_tls_connection_base_ever_handshaked (GTlsConnectionBase *tls);
-
-gboolean g_tls_connection_base_request_certificate (GTlsConnectionBase *tls,
- GError **error);
-
-void g_tls_connection_base_buffer_application_data (GTlsConnectionBase *tls,
- guint8 *data,
- gsize length);
-
-void g_tls_connection_base_set_advertised_protocols
-
-void GTLS_DEBUG (gpointer gnutls,
- const char *message,
- ...);
+gboolean g_tls_connection_base_handshake_thread_verify_certificate
+ (GTlsConnectionBase *tls);
+
+void g_tls_connection_base_push_io (GTlsConnectionBase *tls,
+ GIOCondition direction,
+ gint64 timeout,
+ GCancellable *cancellable);
+GTlsConnectionBaseStatus g_tls_connection_base_pop_io (GTlsConnectionBase *tls,
+ GIOCondition direction,
+ gboolean success,
+ GError **error);
+
+gssize g_tls_connection_base_read (GTlsConnectionBase *tls,
+ void *buffer,
+ gsize size,
+ gint64 timeout,
+ GCancellable *cancellable,
+ GError **error);
+gssize g_tls_connection_base_write (GTlsConnectionBase *tls,
+ const void *buffer,
+ gsize size,
+ gint64 timeout,
+ GCancellable *cancellable,
+ GError **error);
+
+gboolean g_tls_connection_base_check (GTlsConnectionBase *tls,
+ GIOCondition condition);
+gboolean g_tls_connection_base_base_check (GTlsConnectionBase *tls,
+ GIOCondition condition);
+GSource *g_tls_connection_base_create_source (GTlsConnectionBase *tls,
+ GIOCondition condition,
+ GCancellable *cancellable);
+
+gboolean g_tls_connection_base_close_internal (GIOStream *stream,
+ GTlsDirection direction,
+ gint64 timeout,
+ GCancellable *cancellable,
+ GError **error);
+
+gboolean g_tls_connection_base_is_dtls (GTlsConnectionBase *tls);
+
+GDatagramBased *g_tls_connection_base_get_base_socket (GTlsConnectionBase *tls);
+
+GIOStream *g_tls_connection_base_get_base_iostream (GTlsConnectionBase *tls);
+GPollableInputStream *g_tls_connection_base_get_base_istream (GTlsConnectionBase *tls);
+GPollableOutputStream *g_tls_connection_base_get_base_ostream (GTlsConnectionBase *tls);
+
+void g_tls_connection_base_set_missing_requested_client_certificate
+ (GTlsConnectionBase *tls);
+
+GError **g_tls_connection_base_get_certificate_error (GTlsConnectionBase *tls);
+GError **g_tls_connection_base_get_read_error (GTlsConnectionBase *tls);
+GError **g_tls_connection_base_get_write_error (GTlsConnectionBase *tls);
+
+gint64 g_tls_connection_base_get_read_timeout (GTlsConnectionBase *tls);
+gint64 g_tls_connection_base_get_write_timeout (GTlsConnectionBase *tls);
+
+gboolean g_tls_connection_base_is_handshaking (GTlsConnectionBase *tls);
+
+gboolean g_tls_connection_base_ever_handshaked (GTlsConnectionBase *tls);
+
+gboolean g_tls_connection_base_request_certificate (GTlsConnectionBase *tls,
+ GError **error);
+
+void g_tls_connection_base_buffer_application_data (GTlsConnectionBase *tls,
+ guint8 *data,
+ gsize length);
+
+void GTLS_DEBUG (gpointer connection,
+ const char *message,
+ ...);
G_END_DECLS
diff --git a/tls/gnutls/gtlsconnection-gnutls.c b/tls/gnutls/gtlsconnection-gnutls.c
index 537d465..937cc30 100644
--- a/tls/gnutls/gtlsconnection-gnutls.c
+++ b/tls/gnutls/gtlsconnection-gnutls.c
@@ -801,173 +801,15 @@ get_peer_certificate_from_session (GTlsConnectionGnutls *gnutls)
return G_TLS_CERTIFICATE (chain);
}
-//MOVE
-#if 0
-static GTlsCertificateFlags
-verify_peer_certificate (GTlsConnectionGnutls *gnutls,
- GTlsCertificate *peer_certificate)
-{
- GTlsConnection *conn = G_TLS_CONNECTION (gnutls);
- GSocketConnectable *peer_identity;
- GTlsDatabase *database;
- GTlsCertificateFlags errors;
- gboolean is_client;
-
- is_client = G_IS_TLS_CLIENT_CONNECTION (gnutls);
-
- if (!is_client)
- peer_identity = NULL;
- else if (!g_tls_connection_gnutls_is_dtls (gnutls))
- peer_identity = g_tls_client_connection_get_server_identity (G_TLS_CLIENT_CONNECTION (gnutls));
- else
- peer_identity = g_dtls_client_connection_get_server_identity (G_DTLS_CLIENT_CONNECTION (gnutls));
-
- errors = 0;
-
- database = g_tls_connection_get_database (conn);
- if (database == NULL)
- {
- errors |= G_TLS_CERTIFICATE_UNKNOWN_CA;
- errors |= g_tls_certificate_verify (peer_certificate, peer_identity, NULL);
- }
- else
- {
- GError *error = NULL;
-
- errors |= g_tls_database_verify_chain (database, peer_certificate,
- is_client ?
- G_TLS_DATABASE_PURPOSE_AUTHENTICATE_SERVER :
- G_TLS_DATABASE_PURPOSE_AUTHENTICATE_CLIENT,
- peer_identity,
- g_tls_connection_get_interaction (conn),
- G_TLS_DATABASE_VERIFY_NONE,
- NULL, &error);
- if (error)
- {
- g_warning ("failure verifying certificate chain: %s",
- error->message);
- g_assert (errors != 0);
- g_clear_error (&error);
- }
- }
-
- return errors;
-}
-
-static void
-update_peer_certificate_and_compute_errors (GTlsConnectionGnutls *gnutls)
-{
- GTlsConnectionGnutlsPrivate *priv = g_tls_connection_gnutls_get_instance_private (gnutls);
- GTlsCertificate *peer_certificate = NULL;
- GTlsCertificateFlags peer_certificate_errors = 0;
-
- /* This function must be called from the handshake context thread
- * (probably the main thread, NOT the handshake thread) because
- * g_tls_connection_base_set_peer_certificate() emits notifies
- * that are application-visible.
- *
- * verify_certificate_mutex should be locked.
- */
- g_assert (priv->handshake_context);
- g_assert (g_main_context_is_owner (priv->handshake_context));
-
- if (gnutls_certificate_type_get (priv->session) == GNUTLS_CRT_X509)
- {
- peer_certificate = get_peer_certificate_from_session (gnutls);
- if (peer_certificate)
- peer_certificate_errors = verify_peer_certificate (gnutls, peer_certificate);
- }
-
- g_tls_connection_base_set_peer_certificate (G_TLS_CONNECTION_BASE (gnutls),
- peer_certificate, peer_certificate_errors);
-}
-
-static gboolean
-accept_or_reject_peer_certificate (gpointer user_data)
-{
- GTlsConnectionGnutls *gnutls = user_data;
- GTlsConnectionGnutlsPrivate *priv = g_tls_connection_gnutls_get_instance_private (gnutls);
- gboolean accepted = FALSE;
-
- g_assert (g_main_context_is_owner (priv->handshake_context));
-
- g_mutex_lock (&priv->verify_certificate_mutex);
-
- update_peer_certificate_and_compute_errors (gnutls);
-
- if (G_IS_TLS_CLIENT_CONNECTION (gnutls) && priv->peer_certificate != NULL)
- {
- GTlsCertificateFlags validation_flags;
-
- if (!g_tls_connection_gnutls_is_dtls (gnutls))
- validation_flags =
- g_tls_client_connection_get_validation_flags (G_TLS_CLIENT_CONNECTION (gnutls));
- else
- validation_flags =
- g_dtls_client_connection_get_validation_flags (G_DTLS_CLIENT_CONNECTION (gnutls));
-
- if ((priv->peer_certificate_errors & validation_flags) == 0)
- accepted = TRUE;
- }
-
- if (!accepted)
- {
- g_main_context_pop_thread_default (priv->handshake_context);
- accepted = g_tls_connection_emit_accept_certificate (G_TLS_CONNECTION (gnutls),
- priv->peer_certificate,
- priv->peer_certificate_errors);
- g_main_context_push_thread_default (priv->handshake_context);
- }
-
- priv->peer_certificate_accepted = accepted;
-
- /* This has to be the very last statement before signaling the
- * condition variable because otherwise the code could spuriously
- * wakeup and continue before we are done here.
- */
- priv->peer_certificate_examined = TRUE;
-
- g_cond_signal (&priv->verify_certificate_condition);
- g_mutex_unlock (&priv->verify_certificate_mutex);
-
- g_object_notify (G_OBJECT (gnutls), "peer-certificate");
- g_object_notify (G_OBJECT (gnutls), "peer-certificate-errors");
-
- return G_SOURCE_REMOVE;
-}
-
static int
verify_certificate_cb (gnutls_session_t session)
{
- GTlsConnectionGnutls *gnutls = gnutls_session_get_ptr (session);
- GTlsConnectionGnutlsPrivate *priv = g_tls_connection_gnutls_get_instance_private (gnutls);
- gboolean accepted;
-
- g_mutex_lock (&priv->verify_certificate_mutex);
- priv->peer_certificate_examined = FALSE;
- priv->peer_certificate_accepted = FALSE;
- g_mutex_unlock (&priv->verify_certificate_mutex);
-
- /* Invoke the callback on the handshake context's thread. This is
- * necessary because we need to ensure the accept-certificate signal
- * is emitted on the original thread.
- */
- g_assert (priv->handshake_context);
- g_main_context_invoke (priv->handshake_context, accept_or_reject_peer_certificate, gnutls);
+ GTlsConnectionBase *tls = gnutls_session_get_ptr (session);
- /* We'll block the handshake thread until the original thread has
- * decided whether to accept the certificate.
- */
- g_mutex_lock (&priv->verify_certificate_mutex);
- while (!priv->peer_certificate_examined)
- g_cond_wait (&priv->verify_certificate_condition, &priv->verify_certificate_mutex);
- accepted = priv->peer_certificate_accepted;
- g_mutex_unlock (&priv->verify_certificate_mutex);
-
- /* Return 0 for the handshake to continue, non-zero to terminate. */
- return !accepted;
+ /* Return 0 for the handshake to continue, non-zero to terminate.
+ * Complete opposite of what OpenSSL does. */
+ return !g_tls_connection_base_handshake_thread_verify_certificate (tls);
}
-#endif
static void
g_tls_connection_gnutls_prepare_handshake (GTlsConnectionBase *tls,
diff --git a/tls/gnutls/meson.build b/tls/gnutls/meson.build
index 4ff127e..af2b937 100644
--- a/tls/gnutls/meson.build
+++ b/tls/gnutls/meson.build
@@ -6,8 +6,6 @@ sources = files(
'gtlsconnection-gnutls.c',
'gtlsdatabase-gnutls.c',
'gtlsfiledatabase-gnutls.c',
- 'gtlsinputstream-gnutls.c',
- 'gtlsoutputstream-gnutls.c',
'gtlsserverconnection-gnutls.c'
)
diff --git a/tls/openssl/gtlsclientconnection-openssl.c b/tls/openssl/gtlsclientconnection-openssl.c
index 7d7be05..762b812 100644
--- a/tls/openssl/gtlsclientconnection-openssl.c
+++ b/tls/openssl/gtlsclientconnection-openssl.c
@@ -234,6 +234,56 @@ g_tls_client_connection_openssl_constructed (GObject *object)
G_OBJECT_CLASS (g_tls_client_connection_openssl_parent_class)->constructed (object);
}
+static GTlsCertificateFlags
+verify_ocsp_response (GTlsClientConnectionOpenssl *openssl,
+ GTlsCertificate *peer_certificate)
+{
+#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_OCSP)
+ SSL *ssl = NULL;
+ OCSP_RESPONSE *resp = NULL;
+ GTlsDatabase *database;
+ long len = 0;
+ unsigned char *p = NULL;
+
+ ssl = g_tls_connection_openssl_get_ssl (G_TLS_CONNECTION_OPENSSL (openssl));
+ len = SSL_get_tlsext_status_ocsp_resp (ssl, &p);
+ /* Soft fail in case of no response is the best we can do
+ * FIXME: this makes it security theater, why bother with OCSP at all? */
+ if (p == NULL)
+ return 0;
+
+ resp = d2i_OCSP_RESPONSE (NULL, (const unsigned char **)&p, len);
+ if (resp == NULL)
+ return G_TLS_CERTIFICATE_GENERIC_ERROR;
+
+ database = g_tls_connection_get_database (G_TLS_CONNECTION (openssl));
+
+ /* If there's no database, then G_TLS_CERTIFICATE_UNKNOWN_CA must be flagged,
+ * and this function is only called if there are no flags.
+ */
+ g_assert (database);
+
+ return g_tls_file_database_openssl_verify_ocsp_response (database,
+ peer_certificate,
+ resp);
+#else
+ return 0;
+#endif
+}
+
+static GTlsCertificateFlags
+g_tls_client_connection_openssl_verify_peer_certificate (GTlsConnectionBase *tls,
+ GTlsCertificate *certificate,
+ GTlsCertificateFlags flags)
+{
+ GTlsClientConnectionOpenssl *openssl = G_TLS_CLIENT_CONNECTION_OPENSSL (tls);
+
+ if (flags == 0)
+ flags = verify_ocsp_response (openssl, certificate);
+
+ return flags;
+}
+
static SSL *
g_tls_client_connection_openssl_get_ssl (GTlsConnectionOpenssl *connection)
{
@@ -245,14 +295,16 @@ g_tls_client_connection_openssl_class_init (GTlsClientConnectionOpensslClass *kl
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GTlsConnectionBaseClass *base_class = G_TLS_CONNECTION_BASE_CLASS (klass);
- GTlsConnectionOpensslClass *connection_class = G_TLS_CONNECTION_OPENSSL_CLASS (klass);
+ GTlsConnectionOpensslClass *openssl_class = G_TLS_CONNECTION_OPENSSL_CLASS (klass);
+
+ gobject_class->finalize = g_tls_client_connection_openssl_finalize;
+ gobject_class->get_property = g_tls_client_connection_openssl_get_property;
+ gobject_class->set_property = g_tls_client_connection_openssl_set_property;
+ gobject_class->constructed = g_tls_client_connection_openssl_constructed;
- gobject_class->finalize = g_tls_client_connection_openssl_finalize;
- gobject_class->get_property = g_tls_client_connection_openssl_get_property;
- gobject_class->set_property = g_tls_client_connection_openssl_set_property;
- gobject_class->constructed = g_tls_client_connection_openssl_constructed;
+ base_class->verify_peer_certificate = g_tls_client_connection_openssl_verify_peer_certificate;
- connection_class->get_ssl = g_tls_client_connection_openssl_get_ssl;
+ openssl_class->get_ssl = g_tls_client_connection_openssl_get_ssl;
g_object_class_override_property (gobject_class, PROP_VALIDATION_FLAGS, "validation-flags");
g_object_class_override_property (gobject_class, PROP_SERVER_IDENTITY, "server-identity");
diff --git a/tls/openssl/gtlsconnection-openssl.c b/tls/openssl/gtlsconnection-openssl.c
index cbd193b..95ecb20 100644
--- a/tls/openssl/gtlsconnection-openssl.c
+++ b/tls/openssl/gtlsconnection-openssl.c
@@ -290,120 +290,18 @@ get_peer_certificate (GTlsConnectionOpenssl *openssl)
return G_TLS_CERTIFICATE (chain);
}
-static GTlsCertificateFlags
-verify_ocsp_response (GTlsConnectionOpenssl *openssl,
- GTlsDatabase *database,
- GTlsCertificate *peer_certificate)
+static int
+handshake_thread_verify_certificate_cb (int preverify_ok,
+ X509_STORE_CTX *x509_ctx)
{
-#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
- !defined(OPENSSL_NO_OCSP)
- SSL *ssl = NULL;
- OCSP_RESPONSE *resp = NULL;
- long len = 0;
- unsigned char *p = NULL;
-
- ssl = g_tls_connection_openssl_get_ssl (openssl);
- len = SSL_get_tlsext_status_ocsp_resp (ssl, &p);
- /* Soft fail in case of no response is the best we can do */
- if (p == NULL)
- return 0;
-
- resp = d2i_OCSP_RESPONSE (NULL, (const unsigned char **)&p, len);
- if (resp == NULL)
- return G_TLS_CERTIFICATE_GENERIC_ERROR;
-
- return g_tls_file_database_openssl_verify_ocsp_response (database,
- peer_certificate,
- resp);
-#else
+ // FIXME: Get the GTlsConnectionOpenssl out of the X509_STORE_CTX using
+ // x509_STORE_CTX_get_ex_data... somehow. We probably have to pass
+ // the GTlsConnectionOpenssl to the GTlsFileDatabaseOpenssl...
+ // somehow.
+ // return !g_tls_connection_base_handshake_thread_verify_certificate (
+ /* Return 1 for the handshake to continue, 0 to terminate.
+ * Complete opposite of what GnuTLS does. */
return 0;
-#endif
-}
-
-/* FIXME: Share with GnuTLS */
-static GTlsCertificateFlags
-verify_peer_certificate (GTlsConnectionOpenssl *openssl,
- GTlsCertificate *peer_certificate)
-{
- GTlsConnection *conn = G_TLS_CONNECTION (openssl);
- GSocketConnectable *peer_identity;
- GTlsDatabase *database;
- GTlsCertificateFlags errors;
- gboolean is_client;
-
- is_client = G_IS_TLS_CLIENT_CONNECTION (openssl);
- if (is_client)
- peer_identity = g_tls_client_connection_get_server_identity (G_TLS_CLIENT_CONNECTION (openssl));
- else
- peer_identity = NULL;
-
- errors = 0;
-
- database = g_tls_connection_get_database (conn);
- if (database == NULL)
- {
- errors |= G_TLS_CERTIFICATE_UNKNOWN_CA;
- errors |= g_tls_certificate_verify (peer_certificate, peer_identity, NULL);
- }
- else
- {
- GError *error = NULL;
-
- errors |= g_tls_database_verify_chain (database, peer_certificate,
- is_client ?
- G_TLS_DATABASE_PURPOSE_AUTHENTICATE_SERVER :
- G_TLS_DATABASE_PURPOSE_AUTHENTICATE_CLIENT,
- peer_identity,
- g_tls_connection_get_interaction (conn),
- G_TLS_DATABASE_VERIFY_NONE,
- NULL, &error);
- if (error)
- {
- g_warning ("failure verifying certificate chain: %s",
- error->message);
- g_assert (errors != 0);
- g_clear_error (&error);
- }
- }
-
- if (is_client && (errors == 0))
- errors = verify_ocsp_response (openssl, database, peer_certificate);
-
- return errors;
-}
-
-/* FIXME: Share with GnuTLS */
-static gboolean
-accept_peer_certificate (GTlsConnectionBase *tls,
- GTlsCertificate *peer_certificate,
- GTlsCertificateFlags peer_certificate_errors)
-{
- GTlsConnectionBasePrivate *priv = g_tls_connection_base_get_instance_private (tls);
- gboolean accepted = FALSE;
-
- if (G_IS_TLS_CLIENT_CONNECTION (tls) && priv->peer_certificate)
- {
- GTlsCertificateFlags validation_flags;
-
- if (!g_tls_connection_base_is_dtls (tls))
- validation_flags =
- g_tls_client_connection_get_validation_flags (G_TLS_CLIENT_CONNECTION (tls));
- else
- validation_flags =
- g_dtls_client_connection_get_validation_flags (G_DTLS_CLIENT_CONNECTION (tls));
-
- if ((peer_certificate_errors & validation_flags) == 0)
- accepted = TRUE;
- }
-
- if (!accepted)
- {
- accepted = g_tls_connection_emit_accept_certificate (G_TLS_CONNECTION (tls),
- peer_certificate,
- peer_certificate_errors);
- }
-
- return accepted;
}
static GTlsConnectionBaseStatus
@@ -442,43 +340,6 @@ g_tls_connection_openssl_handshake_thread_handshake (GTlsConnectionBase *tls,
return status;
}
-// FIXME all this needs to move up to base class
-#if 0
-static void
-g_tls_connection_openssl_complete_handshake (GTlsConnectionBase *tls,
- gchar **negotiated_protocol,
- GError **error)
-{
- GTlsConnectionOpenssl *openssl = G_TLS_CONNECTION_OPENSSL (tls);
- GTlsConnectionOpensslPrivate *priv;
- GTlsCertificate *peer_certificate;
- GTlsCertificateFlags peer_certificate_errors = 0;
-
- priv = g_tls_connection_openssl_get_instance_private (openssl);
-
- peer_certificate = priv->peer_certificate_tmp;
- priv->peer_certificate_tmp = NULL;
- peer_certificate_errors = priv->peer_certificate_errors_tmp;
- priv->peer_certificate_errors_tmp = 0;
-
- if (peer_certificate)
- {
- /* FIXME: This is too late. Verification should occur during the handshake. */
- if (!accept_peer_certificate (tls, peer_certificate, peer_certificate_errors))
- {
- g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
- _("Unacceptable TLS certificate"));
- status = G_TLS_CONNECTION_BASE_ERROR;
- }
-
- g_tls_connection_base_set_peer_certificate (G_TLS_CONNECTION_BASE (openssl),
- peer_certificate,
- peer_certificate_errors);
- g_clear_object (&peer_certificate);
- }
-}
-#endif
-
static void
g_tls_connection_openssl_push_io (GTlsConnectionBase *tls,
GIOCondition direction,
@@ -652,6 +513,8 @@ g_tls_connection_openssl_initable_init (GInitable *initable,
ssl = g_tls_connection_openssl_get_ssl (openssl);
g_assert (ssl != NULL);
+ SSL_set_verify (ssl, SSL_VERIFY_PEER, handshake_thread_verify_certificate_cb);
+
priv->bio = g_tls_bio_new (base_io_stream);
SSL_set_bio (ssl, priv->bio, priv->bio);
diff --git a/tls/openssl/gtlsserverconnection-openssl.c b/tls/openssl/gtlsserverconnection-openssl.c
index 73e86f9..86a51ab 100644
--- a/tls/openssl/gtlsserverconnection-openssl.c
+++ b/tls/openssl/gtlsserverconnection-openssl.c
@@ -172,13 +172,6 @@ g_tls_server_connection_openssl_set_property (GObject *object,
}
}
-static int
-verify_callback (int preverify_ok,
- X509_STORE_CTX *ctx)
-{
- return 1;
-}
-
static void
g_tls_server_connection_openssl_prepare_handshake (GTlsConnectionBase *tls,
gchar **advertised_protocols)
@@ -200,7 +193,7 @@ g_tls_server_connection_openssl_prepare_handshake (GTlsConnectionBase *tls,
break;
}
- SSL_set_verify (openssl->ssl, req_mode, verify_callback);
+ SSL_set_verify (openssl->ssl, req_mode, NULL);
/* FIXME: is this ok? */
SSL_set_verify_depth (openssl->ssl, 0);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]