aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStef Walter <stefw@collabora.co.uk>2011-03-18 18:59:02 +0800
committerStef Walter <stefw@collabora.co.uk>2011-03-18 18:59:02 +0800
commit3b10103f06517cd7bfbb1576daadaf4855b800a2 (patch)
tree7b9d0c12a74a876dad6e87d2a22dacfc405c7437
parent00f27e9c52f494cad1b36e0e106a129e884ac428 (diff)
downloadgsoc2013-empathy-3b10103f06517cd7bfbb1576daadaf4855b800a2.tar
gsoc2013-empathy-3b10103f06517cd7bfbb1576daadaf4855b800a2.tar.gz
gsoc2013-empathy-3b10103f06517cd7bfbb1576daadaf4855b800a2.tar.bz2
gsoc2013-empathy-3b10103f06517cd7bfbb1576daadaf4855b800a2.tar.lz
gsoc2013-empathy-3b10103f06517cd7bfbb1576daadaf4855b800a2.tar.xz
gsoc2013-empathy-3b10103f06517cd7bfbb1576daadaf4855b800a2.tar.zst
gsoc2013-empathy-3b10103f06517cd7bfbb1576daadaf4855b800a2.zip
Use ServerTLSConnection.ReferenceIdentities to check cert identity.
The certificate identity can be checked against more than just one piece of information. Load and use all the reference identities to check the identity of the certificate. https://bugzilla.gnome.org/show_bug.cgi?id=645119
-rw-r--r--libempathy/empathy-server-tls-handler.c41
-rw-r--r--libempathy/empathy-tls-verifier.c38
-rw-r--r--libempathy/empathy-tls-verifier.h3
-rw-r--r--src/empathy-auth-client.c6
4 files changed, 81 insertions, 7 deletions
diff --git a/libempathy/empathy-server-tls-handler.c b/libempathy/empathy-server-tls-handler.c
index 6cf3290c5..540bb35fa 100644
--- a/libempathy/empathy-server-tls-handler.c
+++ b/libempathy/empathy-server-tls-handler.c
@@ -35,6 +35,7 @@ enum {
PROP_CHANNEL = 1,
PROP_TLS_CERTIFICATE,
PROP_HOSTNAME,
+ PROP_REFERENCE_IDENTITIES,
LAST_PROPERTY,
};
@@ -43,6 +44,7 @@ typedef struct {
EmpathyTLSCertificate *certificate;
gchar *hostname;
+ gchar **reference_identities;
GSimpleAsyncResult *async_init_res;
} EmpathyServerTLSHandlerPriv;
@@ -99,9 +101,11 @@ tls_handler_init_async (GAsyncInitable *initable,
GHashTable *properties;
const gchar *cert_object_path;
const gchar *hostname;
+ const gchar * const *identities;
const gchar *bus_name;
TpDBusDaemon *dbus;
GError *error = NULL;
+ gchar *default_identities[2];
EmpathyServerTLSHandler *self = EMPATHY_SERVER_TLS_HANDLER (initable);
EmpathyServerTLSHandlerPriv *priv = GET_PRIV (self);
@@ -117,6 +121,30 @@ tls_handler_init_async (GAsyncInitable *initable,
DEBUG ("Received hostname: %s", hostname);
+ identities = tp_asv_get_strv (properties,
+ EMP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION ".ReferenceIdentities");
+
+ /*
+ * If the channel doesn't implement the ReferenceIdentities parameter
+ * then fallback to the hostname.
+ */
+ if (!identities)
+ {
+ default_identities[0] = (gchar*)hostname;
+ default_identities[1] = NULL;
+ identities = (const gchar**)default_identities;
+ }
+ else
+ {
+#ifdef ENABLE_DEBUG
+ gchar *output = g_strjoinv (", ", (gchar**)identities);
+ DEBUG ("Received reference identities: %s", output);
+ g_free (output);
+#endif /* ENABLE_DEBUG */
+ }
+
+ priv->reference_identities = g_strdupv ((gchar**)identities);
+
cert_object_path = tp_asv_get_object_path (properties,
EMP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION ".ServerCertificate");
bus_name = tp_proxy_get_bus_name (TP_PROXY (priv->channel));
@@ -162,6 +190,7 @@ empathy_server_tls_handler_finalize (GObject *object)
tp_clear_object (&priv->channel);
tp_clear_object (&priv->certificate);
+ g_strfreev (priv->reference_identities);
g_free (priv->hostname);
G_OBJECT_CLASS (empathy_server_tls_handler_parent_class)->finalize (object);
@@ -186,6 +215,9 @@ empathy_server_tls_handler_get_property (GObject *object,
case PROP_HOSTNAME:
g_value_set_string (value, priv->hostname);
break;
+ case PROP_REFERENCE_IDENTITIES:
+ g_value_set_boxed (value, priv->reference_identities);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -236,10 +268,17 @@ empathy_server_tls_handler_class_init (EmpathyServerTLSHandlerClass *klass)
g_object_class_install_property (oclass, PROP_TLS_CERTIFICATE, pspec);
pspec = g_param_spec_string ("hostname", "The hostname",
- "The hostname which should be certified by the server certificate.",
+ "The hostname the user is expecting to connect to.",
NULL,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (oclass, PROP_HOSTNAME, pspec);
+
+ pspec = g_param_spec_boxed ("reference-identities", "Reference Identities",
+ "The server certificate should certify one of these identities",
+ G_TYPE_STRV,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (oclass, PROP_REFERENCE_IDENTITIES, pspec);
+
}
static void
diff --git a/libempathy/empathy-tls-verifier.c b/libempathy/empathy-tls-verifier.c
index 2f98d9364..e0fa130bf 100644
--- a/libempathy/empathy-tls-verifier.c
+++ b/libempathy/empathy-tls-verifier.c
@@ -42,6 +42,7 @@ G_DEFINE_TYPE (EmpathyTLSVerifier, empathy_tls_verifier,
enum {
PROP_TLS_CERTIFICATE = 1,
PROP_HOSTNAME,
+ PROP_REFERENCE_IDENTITIES,
LAST_PROPERTY,
};
@@ -49,6 +50,7 @@ enum {
typedef struct {
EmpathyTLSCertificate *certificate;
gchar *hostname;
+ gchar **reference_identities;
GSimpleAsyncResult *verify_result;
GHashTable *details;
@@ -255,6 +257,8 @@ perform_verification (EmpathyTLSVerifier *self,
guint n_list, n_anchors;
guint verify_output;
gint res;
+ gchar **i;
+ gboolean matched;
EmpathyTLSVerifierPriv *priv = GET_PRIV (self);
DEBUG ("Performing verification");
@@ -295,8 +299,18 @@ perform_verification (EmpathyTLSVerifier *self,
goto out;
}
- /* now check if the certificate matches the hostname. */
- if (gnutls_x509_crt_check_hostname (list[0], priv->hostname) == 0)
+ /* now check if the certificate matches one of the reference identities. */
+ for (i = priv->reference_identities, matched = FALSE; i && *i; ++i)
+ {
+ const gchar *identity = *i;
+ if (gnutls_x509_crt_check_hostname (list[0], identity) == 1)
+ {
+ matched = TRUE;
+ break;
+ }
+ }
+
+ if (!matched)
{
gchar *certified_hostname;
@@ -362,6 +376,9 @@ empathy_tls_verifier_get_property (GObject *object,
case PROP_HOSTNAME:
g_value_set_string (value, priv->hostname);
break;
+ case PROP_REFERENCE_IDENTITIES:
+ g_value_set_boxed (value, priv->reference_identities);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -384,6 +401,9 @@ empathy_tls_verifier_set_property (GObject *object,
case PROP_HOSTNAME:
priv->hostname = g_value_dup_string (value);
break;
+ case PROP_REFERENCE_IDENTITIES:
+ priv->reference_identities = g_value_dup_boxed (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -414,6 +434,7 @@ empathy_tls_verifier_finalize (GObject *object)
tp_clear_boxed (G_TYPE_HASH_TABLE, &priv->details);
g_free (priv->hostname);
+ g_strfreev (priv->reference_identities);
G_OBJECT_CLASS (empathy_tls_verifier_parent_class)->finalize (object);
}
@@ -448,22 +469,31 @@ empathy_tls_verifier_class_init (EmpathyTLSVerifierClass *klass)
g_object_class_install_property (oclass, PROP_TLS_CERTIFICATE, pspec);
pspec = g_param_spec_string ("hostname", "The hostname",
- "The hostname which should be certified by the certificate.",
+ "The hostname which is certified by the certificate.",
NULL,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (oclass, PROP_HOSTNAME, pspec);
+
+ pspec = g_param_spec_boxed ("reference-identities",
+ "The reference identities",
+ "The certificate should certify one of these identities.",
+ G_TYPE_STRV,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (oclass, PROP_REFERENCE_IDENTITIES, pspec);
}
EmpathyTLSVerifier *
empathy_tls_verifier_new (EmpathyTLSCertificate *certificate,
- const gchar *hostname)
+ const gchar *hostname, const gchar **reference_identities)
{
g_assert (EMPATHY_IS_TLS_CERTIFICATE (certificate));
g_assert (hostname != NULL);
+ g_assert (reference_identities != NULL);
return g_object_new (EMPATHY_TYPE_TLS_VERIFIER,
"certificate", certificate,
"hostname", hostname,
+ "reference-identities", reference_identities,
NULL);
}
diff --git a/libempathy/empathy-tls-verifier.h b/libempathy/empathy-tls-verifier.h
index e333bc81e..436149336 100644
--- a/libempathy/empathy-tls-verifier.h
+++ b/libempathy/empathy-tls-verifier.h
@@ -62,7 +62,8 @@ GType empathy_tls_verifier_get_type (void);
EmpathyTLSVerifier * empathy_tls_verifier_new (
EmpathyTLSCertificate *certificate,
- const gchar *hostname);
+ const gchar *hostname,
+ const gchar **reference_identities);
void empathy_tls_verifier_verify_async (EmpathyTLSVerifier *self,
GAsyncReadyCallback callback,
diff --git a/src/empathy-auth-client.c b/src/empathy-auth-client.c
index df2003495..56c977072 100644
--- a/src/empathy-auth-client.c
+++ b/src/empathy-auth-client.c
@@ -197,6 +197,7 @@ auth_factory_new_tls_handler_cb (EmpathyAuthFactory *factory,
{
EmpathyTLSCertificate *certificate = NULL;
gchar *hostname = NULL;
+ gchar **reference_identities = NULL;
EmpathyTLSVerifier *verifier;
DEBUG ("New TLS server handler received from the factory");
@@ -204,15 +205,18 @@ auth_factory_new_tls_handler_cb (EmpathyAuthFactory *factory,
g_object_get (handler,
"certificate", &certificate,
"hostname", &hostname,
+ "reference-identities", &reference_identities,
NULL);
- verifier = empathy_tls_verifier_new (certificate, hostname);
+ verifier = empathy_tls_verifier_new (certificate, hostname,
+ (const gchar**)reference_identities);
empathy_tls_verifier_verify_async (verifier,
verifier_verify_cb, NULL);
g_object_unref (verifier);
g_object_unref (certificate);
g_free (hostname);
+ g_strfreev (reference_identities);
}
static void