summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWill Thompson <will.thompson@collabora.co.uk>2011-03-31 18:12:53 +0100
committerWill Thompson <will.thompson@collabora.co.uk>2011-03-31 18:12:55 +0100
commit37cfceaeb41b511c3e87124913eccaf0ca5a034a (patch)
treedf30804e3bd6a2b537f38f178ebc905bce6af079
parentf3452284e8b2c07eb9621091e96a49064f4c25ed (diff)
parent50e2995cfb21d61c2c7d570ef14c60cf1baf4b96 (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.ac2
-rw-r--r--src/connection.c40
-rw-r--r--src/protocol.c2
-rw-r--r--src/server-tls-channel.c42
-rw-r--r--src/server-tls-manager.c3
-rw-r--r--tests/twisted/constants.py2
-rw-r--r--tests/twisted/tls/server-tls-channel.py18
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)