diff options
author | Will Thompson <will.thompson@collabora.co.uk> | 2011-03-31 18:12:53 +0100 |
---|---|---|
committer | Will Thompson <will.thompson@collabora.co.uk> | 2011-03-31 18:12:55 +0100 |
commit | 37cfceaeb41b511c3e87124913eccaf0ca5a034a (patch) | |
tree | df30804e3bd6a2b537f38f178ebc905bce6af079 | |
parent | f3452284e8b2c07eb9621091e96a49064f4c25ed (diff) | |
parent | 50e2995cfb21d61c2c7d570ef14c60cf1baf4b96 (diff) |
Merge remote-tracking branch 'stefw/reference-identities'
Fixes: <https://bugs.freedesktop.org/show_bug.cgi?id=35410>
Reviewed-by: Jonny Lamb <jonny.lamb@collabora.co.uk>
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | src/connection.c | 40 | ||||
-rw-r--r-- | src/protocol.c | 2 | ||||
-rw-r--r-- | src/server-tls-channel.c | 42 | ||||
-rw-r--r-- | src/server-tls-manager.c | 3 | ||||
-rw-r--r-- | tests/twisted/constants.py | 2 | ||||
-rw-r--r-- | tests/twisted/tls/server-tls-channel.py | 18 |
7 files changed, 98 insertions, 11 deletions
diff --git a/configure.ac b/configure.ac index 523f50d64..4198ae01a 100644 --- a/configure.ac +++ b/configure.ac @@ -240,7 +240,7 @@ PKG_CHECK_MODULES(DBUS, [dbus-1 >= 1.1.0, dbus-glib-1 >= 0.82]) AC_SUBST(DBUS_CFLAGS) AC_SUBST(DBUS_LIBS) -PKG_CHECK_MODULES(TP_GLIB, [telepathy-glib >= 0.13.12]) +PKG_CHECK_MODULES(TP_GLIB, [telepathy-glib >= 0.14.1]) AC_SUBST(TP_GLIB_CFLAGS) AC_SUBST(TP_GLIB_LIBS) diff --git a/src/connection.c b/src/connection.c index c8bca65f5..b54462c6b 100644 --- a/src/connection.c +++ b/src/connection.c @@ -143,6 +143,7 @@ G_DEFINE_TYPE_WITH_CODE(GabbleConnection, enum { PROP_CONNECT_SERVER = 1, + PROP_EXPLICIT_SERVER, PROP_PORT, PROP_OLD_SSL, PROP_REQUIRE_ENCRYPTION, @@ -183,6 +184,7 @@ struct _GabbleConnectionPrivate /* connection properties */ gchar *connect_server; + gchar *explicit_server; guint port; gboolean old_ssl; gboolean require_encryption; @@ -512,6 +514,9 @@ gabble_connection_get_property (GObject *object, case PROP_CONNECT_SERVER: g_value_set_string (value, priv->connect_server); break; + case PROP_EXPLICIT_SERVER: + g_value_set_string (value, priv->explicit_server); + break; case PROP_STREAM_SERVER: g_value_set_string (value, priv->stream_server); break; @@ -604,9 +609,11 @@ gabble_connection_set_property (GObject *object, GabbleConnectionPrivate *priv = self->priv; switch (property_id) { - case PROP_CONNECT_SERVER: - g_free (priv->connect_server); - priv->connect_server = g_value_dup_string (value); + case PROP_EXPLICIT_SERVER: + g_free (priv->explicit_server); + priv->explicit_server = g_value_dup_string (value); + if (priv->connect_server == NULL) + priv->connect_server = g_value_dup_string (value); break; case PROP_PORT: priv->port = g_value_get_uint (value); @@ -901,6 +908,20 @@ gabble_connection_class_init (GabbleConnectionClass *gabble_connection_class) "connect-server", "Hostname or IP of Jabber server", "The server used when establishing a connection.", NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + /* + * The explicit-server property can be used for verification of a + * server certificate. It's important that it comes from the user + * and is not the result of any other outside lookup, unlike the + * connect-server property. + */ + + g_object_class_install_property (object_class, PROP_EXPLICIT_SERVER, + g_param_spec_string ( + "explicit-server", "Explicit Hostname or IP of Jabber server", + "Server explicitly specified by the user to connect to.", + NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_PORT, @@ -1193,6 +1214,7 @@ gabble_connection_finalize (GObject *object) DEBUG ("called with %p", object); g_free (priv->connect_server); + g_free (priv->explicit_server); g_free (priv->stream_server); g_free (priv->username); g_free (priv->password); @@ -1704,11 +1726,13 @@ next_fallback_server (GabbleConnection *self, return FALSE; } - g_object_set (self, - "connect-server", g_network_address_get_hostname (addr), - "port", g_network_address_get_port (addr), - "old-ssl", old_ssl, - NULL); + g_free (priv->connect_server); + priv->connect_server = g_strdup (g_network_address_get_hostname (addr)); + priv->port = g_network_address_get_port (addr); + priv->old_ssl = old_ssl; + g_object_notify (G_OBJECT (self), "connect-server"); + g_object_notify (G_OBJECT (self), "port"); + g_object_notify (G_OBJECT (self), "old-ssl"); g_object_unref (addr); diff --git a/src/protocol.c b/src/protocol.c index 9530cbab5..96c86ba99 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -205,7 +205,7 @@ struct ParamMapping { const gchar *tp_param; const gchar *conn_prop; } params2props[] = { - MAP ("server", "connect-server"), + MAP ("server", "explicit-server"), SAME ("resource"), SAME ("priority"), SAME ("port"), diff --git a/src/server-tls-channel.c b/src/server-tls-channel.c index 5787ed80b..09d700d08 100644 --- a/src/server-tls-channel.c +++ b/src/server-tls-channel.c @@ -49,6 +49,7 @@ enum { /* server TLS channel iface */ PROP_SERVER_CERTIFICATE = 1, PROP_HOSTNAME, + PROP_REFERENCE_IDENTITIES, /* not exported */ PROP_TLS_SESSION, @@ -62,6 +63,7 @@ struct _GabbleServerTLSChannelPrivate { GabbleTLSCertificate *server_cert; gchar *server_cert_path; gchar *hostname; + GPtrArray *reference_identities; gboolean dispose_has_run; }; @@ -82,6 +84,9 @@ gabble_server_tls_channel_get_property (GObject *object, case PROP_HOSTNAME: g_value_set_string (value, self->priv->hostname); break; + case PROP_REFERENCE_IDENTITIES: + g_value_set_boxed (value, self->priv->reference_identities->pdata); + break; case PROP_TLS_SESSION: g_value_set_object (value, self->priv->tls_session); break; @@ -122,6 +127,7 @@ gabble_server_tls_channel_finalize (GObject *object) g_free (self->priv->server_cert_path); g_free (self->priv->hostname); + g_ptr_array_free (self->priv->reference_identities, TRUE); G_OBJECT_CLASS (gabble_server_tls_channel_parent_class)->finalize (object); } @@ -176,6 +182,8 @@ gabble_server_tls_channel_constructed (GObject *object) const gchar *path; gchar *cert_object_path; GPtrArray *certificates; + gchar *connect_server; + gchar *explicit_server; if (chain_up != NULL) chain_up (object); @@ -196,6 +204,31 @@ gabble_server_tls_channel_constructed (GObject *object) NULL); self->priv->server_cert_path = cert_object_path; + /* Build up the identities we can check against */ + self->priv->reference_identities = g_ptr_array_new_with_free_func (g_free); + + /* First the domain part of the JID, which we were initialied with */ + g_ptr_array_add (self->priv->reference_identities, + g_strdup (self->priv->hostname)); + + /* Secondly include an explicitly overridden server */ + connect_server = NULL; + explicit_server = NULL; + g_object_get (tp_base_channel_get_connection (TP_BASE_CHANNEL (self)), + "connect-server", &connect_server, + "explicit-server", &explicit_server, + NULL); + if (!tp_strdiff (connect_server, explicit_server)) + { + g_ptr_array_add (self->priv->reference_identities, explicit_server); + explicit_server = NULL; + } + g_free (explicit_server); + g_free (connect_server); + + /* Null terminate, since this is a gchar** */ + g_ptr_array_add (self->priv->reference_identities, NULL); + DEBUG ("Server TLS channel constructed at %s", path); } @@ -211,6 +244,7 @@ gabble_server_tls_channel_fill_immutable_properties ( G_OBJECT (chan), properties, TP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION, "ServerCertificate", TP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION, "Hostname", + TP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION, "ReferenceIdentities", NULL); } @@ -233,6 +267,7 @@ gabble_server_tls_channel_class_init (GabbleServerTLSChannelClass *klass) static TpDBusPropertiesMixinPropImpl server_tls_props[] = { { "ServerCertificate", "server-certificate", NULL }, { "Hostname", "hostname", NULL }, + { "ReferenceIdentities", "reference-identities", NULL }, { NULL } }; @@ -269,6 +304,13 @@ gabble_server_tls_channel_class_init (GabbleServerTLSChannelClass *klass) G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_property (oclass, PROP_HOSTNAME, pspec); + pspec = g_param_spec_boxed ("reference-identities", + "The various identities to check the certificate against", + "The server certificate identity should match one of these identities.", + G_TYPE_STRV, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (oclass, PROP_REFERENCE_IDENTITIES, pspec); + pspec = g_param_spec_object ("tls-session", "The WockyTLSSession", "The WockyTLSSession object containing the TLS information", WOCKY_TYPE_TLS_SESSION, diff --git a/src/server-tls-manager.c b/src/server-tls-manager.c index e9f0a65a4..1ad48921f 100644 --- a/src/server-tls-manager.c +++ b/src/server-tls-manager.c @@ -313,6 +313,7 @@ gabble_server_tls_manager_dispose (GObject *object) self->priv->dispose_has_run = TRUE; + tp_clear_object (&self->priv->tls_session); tp_clear_object (&self->priv->connection); G_OBJECT_CLASS (gabble_server_tls_manager_parent_class)->dispose (object); @@ -328,6 +329,8 @@ gabble_server_tls_manager_finalize (GObject *object) if (self->priv->channel != NULL) tp_base_channel_close (TP_BASE_CHANNEL (self->priv->channel)); + g_free (self->priv->peername); + G_OBJECT_CLASS (gabble_server_tls_manager_parent_class)->finalize (object); } diff --git a/tests/twisted/constants.py b/tests/twisted/constants.py index e979843fb..db26f0358 100644 --- a/tests/twisted/constants.py +++ b/tests/twisted/constants.py @@ -390,6 +390,8 @@ SASL_DEFAULT_USERNAME = CHANNEL_IFACE_SASL_AUTH + ".DefaultUsername" # Channel_Type_ServerTLSConnection TLS_CERT_PATH = CHANNEL_TYPE_SERVER_TLS_CONNECTION + ".ServerCertificate" TLS_HOSTNAME = CHANNEL_TYPE_SERVER_TLS_CONNECTION + ".Hostname" +TLS_REFERENCE_IDENTITIES = \ + CHANNEL_TYPE_SERVER_TLS_CONNECTION + ".ReferenceIdentities" # Connection.Interface.Location diff --git a/tests/twisted/tls/server-tls-channel.py b/tests/twisted/tls/server-tls-channel.py index 0a9723cc5..cf1af5e78 100644 --- a/tests/twisted/tls/server-tls-channel.py +++ b/tests/twisted/tls/server-tls-channel.py @@ -24,7 +24,8 @@ from twisted.internet import ssl import ns from gabbletest import exec_test, XmppAuthenticator -from servicetest import ProxyWrapper, EventPattern, assertEquals, assertLength +from servicetest import ProxyWrapper, EventPattern +from servicetest import assertEquals, assertLength, assertSameSets import constants as cs JID = "test@example.org" @@ -218,6 +219,17 @@ def test_connect_success(q, bus, conn, stream): args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]) ) +def test_channel_reference_identity(q, bus, conn, stream): + chan, hostname, certificate_path = connect_and_get_tls_objects(q, bus, conn) + + chan_props = dbus.Interface(chan, cs.PROPERTIES_IFACE) + reference_identities = chan_props.Get(cs.CHANNEL_TYPE_SERVER_TLS_CONNECTION, + "ReferenceIdentities") + hostname = chan_props.Get(cs.CHANNEL_TYPE_SERVER_TLS_CONNECTION, "Hostname") + + assertSameSets(reference_identities, [ "example.org", "localhost"]) + assertEquals(hostname, "example.org") + if __name__ == '__main__': exec_test(test_connect_success, { 'account' : JID }, authenticator=TlsAuthenticator(username='test', password='pass'), do_connect=False) @@ -235,3 +247,7 @@ if __name__ == '__main__': authenticator=TlsAuthenticator(username='test', password='pass'), do_connect=False) exec_test(test_disconnect_inbetween, { 'account' : JID }, authenticator=TlsAuthenticator(username='test', password='pass'), do_connect=False) + + # Certificate verification reference identity checks + exec_test(test_channel_reference_identity, { 'account' : JID }, + authenticator=TlsAuthenticator(username='test', password='pass'), do_connect=False) |