[empathy/gnome-2-34] Use ServerTLSConnection.ReferenceIdentities to check cert identity.



commit 8b18f92aedef75ae557e879ddc4a60ce833d50d3
Author: Stef Walter <stefw collabora co uk>
Date:   Fri Mar 18 18:42:55 2011 +0100

    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

 libempathy/empathy-server-tls-handler.c |   47 +++++++++++++++++++++++++++++-
 libempathy/empathy-tls-verifier.c       |   42 +++++++++++++++++++++++++--
 libempathy/empathy-tls-verifier.h       |    3 +-
 src/empathy-auth-client.c               |    6 +++-
 4 files changed, 90 insertions(+), 8 deletions(-)
---
diff --git a/libempathy/empathy-server-tls-handler.c b/libempathy/empathy-server-tls-handler.c
index 6180fef..61c3af1 100644
--- a/libempathy/empathy-server-tls-handler.c
+++ b/libempathy/empathy-server-tls-handler.c
@@ -20,6 +20,7 @@
 
 #include "empathy-server-tls-handler.h"
 
+#include <telepathy-glib/interfaces.h>
 #include <telepathy-glib/util.h>
 
 #define DEBUG_FLAG EMPATHY_DEBUG_TLS
@@ -35,6 +36,7 @@ enum {
   PROP_CHANNEL = 1,
   PROP_TLS_CERTIFICATE,
   PROP_HOSTNAME,
+  PROP_REFERENCE_IDENTITIES,
   LAST_PROPERTY,
 };
 
@@ -43,6 +45,7 @@ typedef struct {
 
   EmpathyTLSCertificate *certificate;
   gchar *hostname;
+  gchar **reference_identities;
 
   GSimpleAsyncResult *async_init_res;
 } EmpathyServerTLSHandlerPriv;
@@ -99,9 +102,15 @@ 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;
+  /*
+   * Used when channel doesn't implement ReferenceIdentities. A GStrv
+   * with [0] the hostname, and [1] a NULL terminator.
+   */
+  gchar *default_identities[2];
   EmpathyServerTLSHandler *self = EMPATHY_SERVER_TLS_HANDLER (initable);
   EmpathyServerTLSHandlerPriv *priv = GET_PRIV (self);
 
@@ -112,11 +121,35 @@ tls_handler_init_async (GAsyncInitable *initable,
   properties = tp_channel_borrow_immutable_properties (priv->channel);
 
   hostname = tp_asv_get_string (properties,
-      EMP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION ".Hostname");
+      TP_PROP_CHANNEL_TYPE_SERVER_TLS_CONNECTION_HOSTNAME);
   priv->hostname = g_strdup (hostname);
 
   DEBUG ("Received hostname: %s", hostname);
 
+  identities = tp_asv_get_strv (properties,
+      TP_PROP_CHANNEL_TYPE_SERVER_TLS_CONNECTION_REFERENCE_IDENTITIES);
+
+  /*
+   * If the channel doesn't implement the ReferenceIdentities parameter
+   * then fallback to the hostname.
+   */
+  if (identities == NULL)
+    {
+      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 +195,8 @@ 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);
 }
@@ -185,6 +220,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;
@@ -235,10 +273,15 @@ 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 2241505..7b9c94c 100644
--- a/libempathy/empathy-tls-verifier.c
+++ b/libempathy/empathy-tls-verifier.c
@@ -39,6 +39,7 @@ G_DEFINE_TYPE (EmpathyTLSVerifier, empathy_tls_verifier,
 enum {
   PROP_TLS_CERTIFICATE = 1,
   PROP_HOSTNAME,
+  PROP_REFERENCE_IDENTITIES,
 
   LAST_PROPERTY,
 };
@@ -58,6 +59,7 @@ typedef struct {
 
   EmpathyTLSCertificate *certificate;
   gchar *hostname;
+  gchar **reference_identities;
 
   GSimpleAsyncResult *verify_result;
   GHashTable *details;
@@ -229,13 +231,28 @@ real_start_verification (EmpathyTLSVerifier *self)
   gint num_certs;
   EmpTLSCertificateRejectReason reason =
     EMP_TLS_CERTIFICATE_REJECT_REASON_UNKNOWN;
+  gint i;
+  gboolean matched;
   EmpathyTLSVerifierPriv *priv = GET_PRIV (self);
 
   DEBUG ("Starting verification");
 
-  /* check if the certificate matches the hostname first. */
+  /* check if the certificate matches one of the reference identities. */
   first_cert = g_ptr_array_index (priv->cert_chain, 0);
-  if (gnutls_x509_crt_check_hostname (first_cert, priv->hostname) == 0)
+  if (priv->reference_identities != NULL)
+    {
+      for (i = 0, matched = FALSE; priv->reference_identities[i] != NULL; ++i)
+        {
+          if (gnutls_x509_crt_check_hostname (first_cert,
+                  priv->reference_identities[i]) == 1)
+            {
+              matched = TRUE;
+              break;
+            }
+        }
+    }
+
+  if (!matched)
     {
       gchar *certified_hostname;
 
@@ -539,6 +556,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;
@@ -561,6 +581,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;
@@ -593,6 +616,7 @@ empathy_tls_verifier_finalize (GObject *object)
   tp_clear_pointer (&priv->cert_chain, g_ptr_array_unref);
   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);
 }
@@ -639,22 +663,32 @@ 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 e73a71a..f61201f 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 907c349..2a1e425 100644
--- a/src/empathy-auth-client.c
+++ b/src/empathy-auth-client.c
@@ -191,6 +191,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");
@@ -198,15 +199,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



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]