* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include "config.h"
#include "empathy-server-tls-handler.h"
-#define DEBUG_FLAG EMPATHY_DEBUG_TLS
-#include "empathy-debug.h"
-#include "empathy-tls-certificate.h"
+#include <telepathy-glib/telepathy-glib-dbus.h>
+
#include "empathy-utils.h"
-#include "extensions/extensions.h"
+#define DEBUG_FLAG EMPATHY_DEBUG_TLS
+#include "empathy-debug.h"
static void async_initable_iface_init (GAsyncInitableIface *iface);
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;
#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);
-}
-
-static void
-server_tls_channel_got_all_cb (TpProxy *proxy,
- GHashTable *properties,
- const GError *error,
- gpointer user_data,
- GObject *weak_object)
-{
- EmpathyServerTLSHandler *self = EMPATHY_SERVER_TLS_HANDLER (weak_object);
- EmpathyServerTLSHandlerPriv *priv = GET_PRIV (self);
-
- if (error != NULL)
- {
- g_simple_async_result_set_from_error (priv->async_init_res, error);
- g_simple_async_result_complete_in_idle (priv->async_init_res);
- }
- else
- {
- const gchar *cert_object_path;
- const gchar *hostname;
-
- cert_object_path = tp_asv_get_object_path (properties,
- "ServerCertificate");
-
- DEBUG ("Creating an EmpathyTLSCertificate for path %s, bus name %s",
- cert_object_path, tp_proxy_get_bus_name (proxy));
-
- empathy_tls_certificate_new_async (
- tp_proxy_get_bus_name (proxy),
- cert_object_path,
- tls_certificate_constructed_cb, self);
-
- hostname = tp_asv_get_string (properties, "Hostname");
- priv->hostname = g_strdup (hostname);
-
- DEBUG ("Received hostname: %s", hostname);
- }
+ tp_clear_object (&priv->async_init_res);
}
static gboolean
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;
GAsyncReadyCallback callback,
gpointer user_data)
{
+ GVariant *properties;
+ const gchar *cert_object_path;
+ 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, NULL);
+ 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);
+
+ DEBUG ("Received hostname: %s", priv->hostname);
- /* call GetAll() on the channel properties */
- tp_cli_dbus_properties_call_get_all (priv->channel,
- -1, EMP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION,
- server_tls_channel_got_all_cb, NULL, NULL, G_OBJECT (self));
+ g_variant_lookup (properties,
+ TP_PROP_CHANNEL_TYPE_SERVER_TLS_CONNECTION_REFERENCE_IDENTITIES,
+ "^as", &priv->reference_identities);
+
+ /*
+ * 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,
+ TP_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 TpTLSCertificate for path %s, bus name %s",
+ cert_object_path, bus_name);
+
+ 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
EmpathyServerTLSHandlerPriv *priv = GET_PRIV (object);
DEBUG ("%p", object);
-
- if (priv->channel != NULL)
- g_object_unref (priv->channel);
+
+ 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);
}
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;
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
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;
}