]> git.0d.be Git - empathy.git/blobdiff - libempathy/empathy-server-tls-handler.c
Merge branch 'gnome-3-8'
[empathy.git] / libempathy / empathy-server-tls-handler.c
index a207dffcf71022666ac8bf9f0906092895927c1a..34c3147a38c32fccdbd46569f7ed0df264ce829e 100644 (file)
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+#include "config.h"
 #include "empathy-server-tls-handler.h"
 
-#include <telepathy-glib/util.h>
+#include "empathy-utils.h"
+#include "extensions.h"
 
 #define DEBUG_FLAG EMPATHY_DEBUG_TLS
 #include "empathy-debug.h"
-#include "empathy-tls-certificate.h"
-#include "empathy-utils.h"
-
-#include "extensions/extensions.h"
 
 static void async_initable_iface_init (GAsyncInitableIface *iface);
 
@@ -35,14 +33,16 @@ enum {
   PROP_CHANNEL = 1,
   PROP_TLS_CERTIFICATE,
   PROP_HOSTNAME,
+  PROP_REFERENCE_IDENTITIES,
   LAST_PROPERTY,
 };
 
 typedef struct {
   TpChannel *channel;
 
-  EmpathyTLSCertificate *certificate;
+  TpTLSCertificate *certificate;
   gchar *hostname;
+  gchar **reference_identities;
 
   GSimpleAsyncResult *async_init_res;
 } EmpathyServerTLSHandlerPriv;
@@ -54,29 +54,23 @@ G_DEFINE_TYPE_WITH_CODE (EmpathyServerTLSHandler, empathy_server_tls_handler,
 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyServerTLSHandler);
 
 static void
-tls_certificate_constructed_cb (GObject *source,
+tls_certificate_prepared_cb (GObject *source,
     GAsyncResult *result,
     gpointer user_data)
 {
-  EmpathyTLSCertificate *certificate;
+  TpTLSCertificate *certificate = TP_TLS_CERTIFICATE (source);
   EmpathyServerTLSHandler *self = user_data;
   GError *error = NULL;
   EmpathyServerTLSHandlerPriv *priv = GET_PRIV (self);
 
-  certificate = empathy_tls_certificate_new_finish (result, &error);
-
-  if (error != NULL)
+  if (!tp_proxy_prepare_finish (certificate, result, &error))
     {
       g_simple_async_result_set_from_error (priv->async_init_res, error);
       g_error_free (error);
     }
-  else
-    {
-      priv->certificate = certificate;
-    }
 
   g_simple_async_result_complete_in_idle (priv->async_init_res);
-  g_object_unref (priv->async_init_res);
+  tp_clear_object (&priv->async_init_res);
 }
 
 static gboolean
@@ -85,10 +79,9 @@ tls_handler_init_finish (GAsyncInitable *initable,
     GError **error)
 {
   gboolean retval = TRUE;
-  EmpathyServerTLSHandler *self = EMPATHY_SERVER_TLS_HANDLER (initable);
-  EmpathyServerTLSHandlerPriv *priv = GET_PRIV (self);
 
-  if (g_simple_async_result_propagate_error (priv->async_init_res, error))
+  if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res),
+          error))
     retval = FALSE;
 
   return retval;
@@ -101,34 +94,83 @@ tls_handler_init_async (GAsyncInitable *initable,
     GAsyncReadyCallback callback,
     gpointer user_data)
 {
-  GHashTable *properties;
+  GVariant *properties;
   const gchar *cert_object_path;
-  const gchar *hostname;
   const gchar *bus_name;
+  GError *error = NULL;
+  GQuark features[] = { TP_TLS_CERTIFICATE_FEATURE_CORE, 0 };
+  /*
+   * 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);
 
   g_assert (priv->channel != NULL);
 
   priv->async_init_res = g_simple_async_result_new (G_OBJECT (self),
-      callback, user_data, empathy_tls_certificate_new_async);
-  properties = tp_channel_borrow_immutable_properties (priv->channel);
+      callback, user_data, empathy_server_tls_handler_new_async);
+  properties = tp_channel_dup_immutable_properties (priv->channel);
+
+  g_variant_lookup (properties,
+      TP_PROP_CHANNEL_TYPE_SERVER_TLS_CONNECTION_HOSTNAME,
+      "s", &priv->hostname);
 
-  hostname = tp_asv_get_string (properties,
-      EMP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION ".Hostname");
-  priv->hostname = g_strdup (hostname);
+  DEBUG ("Received hostname: %s", priv->hostname);
 
-  DEBUG ("Received hostname: %s", hostname);
+  g_variant_lookup (properties,
+      TP_PROP_CHANNEL_TYPE_SERVER_TLS_CONNECTION_REFERENCE_IDENTITIES,
+      "^as", &priv->reference_identities);
 
-  cert_object_path = tp_asv_get_object_path (properties,
-      EMP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION ".ServerCertificate");
+  /*
+   * If the channel doesn't implement the ReferenceIdentities parameter
+   * then fallback to the hostname.
+   */
+  if (priv->reference_identities == NULL)
+    {
+      default_identities[0] = (gchar *) priv->hostname;
+      default_identities[1] = NULL;
+      priv->reference_identities = g_strdupv (default_identities);
+    }
+  else
+    {
+#ifdef ENABLE_DEBUG
+      gchar *output = g_strjoinv (", ", (gchar **) priv->reference_identities);
+      DEBUG ("Received reference identities: %s", output);
+      g_free (output);
+#endif /* ENABLE_DEBUG */
+  }
+
+  g_variant_lookup (properties,
+      EMP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION ".ServerCertificate",
+      "&o", &cert_object_path);
   bus_name = tp_proxy_get_bus_name (TP_PROXY (priv->channel));
 
-  DEBUG ("Creating an EmpathyTLSCertificate for path %s, bus name %s",
+  DEBUG ("Creating an TpTLSCertificate for path %s, bus name %s",
       cert_object_path, bus_name);
 
-  empathy_tls_certificate_new_async (bus_name, cert_object_path,
-      tls_certificate_constructed_cb, self);
+  priv->certificate = tp_tls_certificate_new (TP_PROXY (priv->channel),
+      cert_object_path, &error);
+
+  g_variant_unref (properties);
+
+  if (error != NULL)
+    {
+      DEBUG ("Unable to create the TpTLSCertificate: error %s",
+          error->message);
+
+      g_simple_async_result_set_from_error (priv->async_init_res, error);
+      g_simple_async_result_complete_in_idle (priv->async_init_res);
+
+      g_error_free (error);
+      tp_clear_object (&priv->async_init_res);
+
+      return;
+    }
+
+  tp_proxy_prepare_async (priv->certificate, features,
+      tls_certificate_prepared_cb, self);
 }
 
 static void
@@ -147,6 +189,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);
 }
@@ -170,6 +214,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;
@@ -213,17 +260,23 @@ empathy_server_tls_handler_class_init (EmpathyServerTLSHandlerClass *klass)
       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
   g_object_class_install_property (oclass, PROP_CHANNEL, pspec);
 
-  pspec = g_param_spec_object ("certificate", "The EmpathyTLSCertificate",
-      "The EmpathyTLSCertificate carried by the channel.",
-      EMPATHY_TYPE_TLS_CERTIFICATE,
+  pspec = g_param_spec_object ("certificate", "The TpTLSCertificate",
+      "The TpTLSCertificate carried by the channel.",
+      TP_TYPE_TLS_CERTIFICATE,
       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
   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
@@ -264,12 +317,12 @@ empathy_server_tls_handler_new_finish (GAsyncResult *result,
     return NULL;
 }
 
-EmpathyTLSCertificate *
+TpTLSCertificate *
 empathy_server_tls_handler_get_certificate (EmpathyServerTLSHandler *self)
 {
   EmpathyServerTLSHandlerPriv *priv = GET_PRIV (self);
 
   g_assert (priv->certificate != NULL);
-  
+
   return priv->certificate;
 }