From 6558e252f986d2214df755a0f7a3bb06220e49dc Mon Sep 17 00:00:00 2001 From: Stefan Becker Date: Mon, 22 Apr 2013 14:39:30 +0300 Subject: [PATCH] telepathy: introduce TLS info data structure It contains all the information required for the user interaction. --- src/telepathy/telepathy-private.h | 8 +++-- src/telepathy/telepathy-tls.c | 52 ++++++++++++++++++++++---------- src/telepathy/telepathy-transport.c | 59 ++++++++++++++++++++----------------- 3 files changed, 75 insertions(+), 44 deletions(-) diff --git a/src/telepathy/telepathy-private.h b/src/telepathy/telepathy-private.h index 3c11a619..a8529c60 100644 --- a/src/telepathy/telepathy-private.h +++ b/src/telepathy/telepathy-private.h @@ -23,12 +23,14 @@ /* Forward declarations */ struct _GObject; struct _GObjectClass; +struct _GTlsCertificate; struct _SipeConnection; struct _SipeContactList; struct _SipeTLSManager; struct _TpBaseConnection; struct _TpBaseConnectionManager; struct _TpBaseProtocol; +struct sipe_tls_info; struct sipe_transport_telepathy; /* constants */ @@ -107,9 +109,11 @@ void sipe_telepathy_status_init(struct _GObjectClass *object_class, /* TLS certificate verification */ struct _SipeTLSManager *sipe_telepathy_tls_new(struct _TpBaseConnection *connection); +struct sipe_tls_info *sipe_telepathy_tls_info_new(const gchar *hostname, + struct _GTlsCertificate *certificate); +void sipe_telepathy_tls_info_free(struct sipe_tls_info *tls_info); void sipe_telepathy_tls_verify_async(struct _GObject *connection, - const gchar *hostname, - const gchar **reference_identities, + struct sipe_tls_info *tls_info, GAsyncReadyCallback callback, gpointer user_data); diff --git a/src/telepathy/telepathy-tls.c b/src/telepathy/telepathy-tls.c index b86070e7..6b689616 100644 --- a/src/telepathy/telepathy-tls.c +++ b/src/telepathy/telepathy-tls.c @@ -31,6 +31,13 @@ #include "telepathy-private.h" +/* TLS information required for user interaction */ +struct sipe_tls_info { + gchar *hostname; + gchar *server_cert_path; + GStrv reference_identities; +}; + G_BEGIN_DECLS /* * TLS Manager class - data structures @@ -67,9 +74,7 @@ typedef struct _SipeTLSChannelClass { typedef struct _SipeTLSChannel { TpBaseChannel parent; - gchar *server_cert_path; - gchar *hostname; - GStrv reference_identities; + const struct sipe_tls_info *tls_info; GSimpleAsyncResult *result; } SipeTLSChannel; @@ -259,13 +264,13 @@ static void get_property(GObject *object, switch (property_id) { case CHANNEL_PROP_SERVER_CERTIFICATE: - g_value_set_boxed(value, self->server_cert_path); + g_value_set_boxed(value, self->tls_info->server_cert_path); break; case CHANNEL_PROP_HOSTNAME: - g_value_set_string(value, self->hostname); + g_value_set_string(value, self->tls_info->hostname); break; case CHANNEL_PROP_REFERENCE_IDENTITIES: - g_value_set_boxed(value, self->reference_identities); + g_value_set_boxed(value, self->tls_info->reference_identities); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); @@ -312,10 +317,6 @@ static void sipe_tls_channel_finalize(GObject *object) g_simple_async_result_complete(self->result); g_clear_object(&self->result); - g_free(self->server_cert_path); - g_free(self->hostname); - g_strfreev(self->reference_identities); - G_OBJECT_CLASS(sipe_tls_channel_parent_class)->finalize(object); } @@ -400,10 +401,33 @@ static void sipe_tls_channel_init(SIPE_UNUSED_PARAMETER SipeTLSChannel *self) SIPE_DEBUG_INFO_NOFORMAT("SipeTLSChannel::init"); } +struct sipe_tls_info *sipe_telepathy_tls_info_new(const gchar *hostname, + SIPE_UNUSED_PARAMETER struct _GTlsCertificate *certificate) +{ + struct sipe_tls_info *tls_info = g_new0(struct sipe_tls_info, 1); + + tls_info->hostname = g_strdup(hostname); + + /* + * @TODO + * tls_info->reference_identities = g_boxed_copy(G_TYPE_STRV, reference_identities);?? + * tls_info->tls_info->server_cert_path + */ + + return(tls_info); +} + +void sipe_telepathy_tls_info_free(struct sipe_tls_info *tls_info) +{ + g_free(tls_info->hostname); + g_free(tls_info->server_cert_path); + g_strfreev(tls_info->reference_identities); + g_free(tls_info); +} + /* create new tls channel object */ void sipe_telepathy_tls_verify_async(GObject *connection, - const gchar *hostname, - const gchar **reference_identities, + struct sipe_tls_info *tls_info, GAsyncReadyCallback callback, gpointer user_data) { @@ -414,9 +438,7 @@ void sipe_telepathy_tls_verify_async(GObject *connection, "connection", connection, NULL); - self->hostname = g_strdup(hostname); - self->reference_identities = g_boxed_copy(G_TYPE_STRV, reference_identities); - + self->tls_info = tls_info; self->result = g_simple_async_result_new(G_OBJECT(self), callback, user_data, diff --git a/src/telepathy/telepathy-transport.c b/src/telepathy/telepathy-transport.c index 2fa59812..2b30a943 100644 --- a/src/telepathy/telepathy-transport.c +++ b/src/telepathy/telepathy-transport.c @@ -44,6 +44,8 @@ struct sipe_transport_telepathy { transport_connected_cb *connected; transport_input_cb *input; transport_error_cb *error; + gchar *hostname; + struct sipe_tls_info *tls_info; struct sipe_backend_private *private; GCancellable *cancel; GSocketConnection *socket; @@ -52,7 +54,6 @@ struct sipe_transport_telepathy { GSList *buffers; gboolean is_writing; gboolean do_flush; - gboolean wait_for_user; }; #define TELEPATHY_TRANSPORT ((struct sipe_transport_telepathy *) conn) @@ -125,6 +126,17 @@ static void read_completed(GObject *stream, transport); } +static void certificate_result(SIPE_UNUSED_PARAMETER GObject *unused, + SIPE_UNUSED_PARAMETER GAsyncResult *res, + gpointer data) +{ + struct sipe_transport_telepathy *transport = data; + + SIPE_DEBUG_INFO("certificate_result: %p", transport); + + /* @TODO: take action based on result */ +} + static void socket_connected(GObject *client, GAsyncResult *result, gpointer data) @@ -137,9 +149,12 @@ static void socket_connected(GObject *client, &error); if (transport->socket == NULL) { - if (transport->wait_for_user) { + if (transport->tls_info) { SIPE_DEBUG_INFO_NOFORMAT("socket_connected: need to wait for user interaction"); - /* @TODO: trigger user interaction */ + sipe_telepathy_tls_verify_async(G_OBJECT(transport->private->connection), + transport->tls_info, + certificate_result, + transport); } else { const gchar *msg = error ? error->message : "UNKNOWN"; SIPE_DEBUG_ERROR("socket_connected: failed: %s", msg); @@ -183,40 +198,25 @@ static void socket_connected(GObject *client, } } -static void certificate_result(SIPE_UNUSED_PARAMETER GObject *unused, - SIPE_UNUSED_PARAMETER GAsyncResult *res, - gpointer data) -{ - struct sipe_transport_telepathy *transport = data; - - SIPE_DEBUG_INFO("certificate_result: %p", transport); - - /* @TODO: take action based on result */ -} - -static gboolean accept_certificate_signal(GTlsConnection *tls, - SIPE_UNUSED_PARAMETER GTlsCertificate *peer_cert, +static gboolean accept_certificate_signal(SIPE_UNUSED_PARAMETER GTlsConnection *tls, + GTlsCertificate *peer_cert, SIPE_UNUSED_PARAMETER GTlsCertificateFlags errors, gpointer user_data) { struct sipe_transport_telepathy *transport = user_data; - SIPE_DEBUG_INFO("accept_certificate_signal: %p", tls); + SIPE_DEBUG_INFO("accept_certificate_signal: %p", transport); /* second connection attempt after feedback from user? */ - if (transport->wait_for_user) { + if (transport->tls_info) { /* user accepted certificate */ - transport->wait_for_user = FALSE; + sipe_telepathy_tls_info_free(transport->tls_info); + transport->tls_info = NULL; return(TRUE); } else { /* retry after user accepted certificate */ - transport->wait_for_user = TRUE; - /* @TODO: set up correct parameters */ - sipe_telepathy_tls_verify_async(G_OBJECT(transport->private->connection), - "", - NULL, - certificate_result, - transport); + transport->tls_info = sipe_telepathy_tls_info_new(transport->hostname, + peer_cert); return(FALSE); } } @@ -249,11 +249,12 @@ struct sipe_transport_connection *sipe_backend_transport_connect(struct sipe_cor transport->connected = setup->connected; transport->input = setup->input; transport->error = setup->error; + transport->hostname = g_strdup(setup->server_name); + transport->tls_info = NULL; transport->private = sipe_public->backend_private; transport->buffers = NULL; transport->is_writing = FALSE; transport->do_flush = FALSE; - transport->wait_for_user = FALSE; if ((setup->type == SIPE_TRANSPORT_TLS) || (setup->type == SIPE_TRANSPORT_TCP)) { @@ -295,6 +296,10 @@ static gboolean free_transport(gpointer data) SIPE_DEBUG_INFO("free_transport %p", transport); + if (transport->tls_info) + sipe_telepathy_tls_info_free(transport->tls_info); + g_free(transport->hostname); + /* free unflushed buffers */ for (entry = transport->buffers; entry; entry = entry->next) g_free(entry->data); -- 2.11.4.GIT