]> git.0d.be Git - empathy.git/commitdiff
Merge branch 'reference-identities'
authorStef Walter <stefw@collabora.co.uk>
Tue, 22 Mar 2011 14:22:43 +0000 (15:22 +0100)
committerStef Walter <stefw@collabora.co.uk>
Tue, 22 Mar 2011 14:22:43 +0000 (15:22 +0100)
Conflicts:
libempathy/empathy-server-tls-handler.c

libempathy/empathy-server-tls-handler.c
libempathy/empathy-tls-verifier.c
libempathy/empathy-tls-verifier.h
src/empathy-auth-client.c

index 6cf3290c5ebbeee5017464a33353a86919cdc722..31afa276c58fa627c1d74d4c95a125572e398e29 100644 (file)
@@ -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,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 +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;
@@ -236,10 +273,16 @@ 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
index 2f98d9364815c1505d69c2e6b4adab69af0bfc08..47a54333c901c034a19264d94a9513994bb01e42 100644 (file)
@@ -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;
+  gint i;
+  gboolean matched;
   EmpathyTLSVerifierPriv *priv = GET_PRIV (self);
 
   DEBUG ("Performing verification");
@@ -295,8 +299,21 @@ 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. */
+  if (priv->reference_identities != NULL)
+    {
+      for (i = 0, matched = FALSE; priv->reference_identities[i] != NULL; ++i)
+        {
+          if (gnutls_x509_crt_check_hostname (list[0],
+                  priv->reference_identities[i]) == 1)
+            {
+              matched = TRUE;
+              break;
+            }
+        }
+    }
+
+  if (!matched)
     {
       gchar *certified_hostname;
 
@@ -362,6 +379,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 +404,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 +437,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 +472,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);
 }
 
index e333bc81e2bcab5b89048f2616b72daf39842171..436149336d0a26a8b0edc3f7069b1bd16e42f409 100644 (file)
@@ -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,
index df2003495f90e47671af83ecdad665e7e38c4810..68c4543a881e2d673ef363429bc985d956514862 100644 (file)
@@ -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