aboutsummaryrefslogtreecommitdiffstats
path: root/libempathy/empathy-auth-factory.c
diff options
context:
space:
mode:
Diffstat (limited to 'libempathy/empathy-auth-factory.c')
-rw-r--r--libempathy/empathy-auth-factory.c139
1 files changed, 127 insertions, 12 deletions
diff --git a/libempathy/empathy-auth-factory.c b/libempathy/empathy-auth-factory.c
index fa2b7dcd1..578b6d6cd 100644
--- a/libempathy/empathy-auth-factory.c
+++ b/libempathy/empathy-auth-factory.c
@@ -26,6 +26,7 @@
#define DEBUG_FLAG EMPATHY_DEBUG_TLS
#include "empathy-debug.h"
+#include "empathy-server-sasl-handler.h"
#include "empathy-server-tls-handler.h"
#include "empathy-utils.h"
@@ -36,11 +37,17 @@ G_DEFINE_TYPE (EmpathyAuthFactory, empathy_auth_factory, G_TYPE_OBJECT);
typedef struct {
TpBaseClient *handler;
+ /* Keep a ref here so the auth client doesn't have to mess with
+ * refs. It will be cleared when the channel (and so the handler)
+ * gets invalidated. */
+ EmpathyServerSASLHandler *sasl_handler;
+
gboolean dispose_run;
} EmpathyAuthFactoryPriv;
enum {
NEW_SERVER_TLS_HANDLER,
+ NEW_SERVER_SASL_HANDLER,
LAST_SIGNAL,
};
@@ -111,6 +118,52 @@ server_tls_handler_ready_cb (GObject *source,
}
static void
+sasl_handler_invalidated_cb (EmpathyServerSASLHandler *handler,
+ gpointer user_data)
+{
+ EmpathyAuthFactory *self = user_data;
+ EmpathyAuthFactoryPriv *priv = GET_PRIV (self);
+
+ DEBUG ("SASL handler is invalidated, unref it");
+
+ tp_clear_object (&priv->sasl_handler);
+}
+
+static void
+server_sasl_handler_ready_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ EmpathyAuthFactoryPriv *priv;
+ GError *error = NULL;
+ HandlerContextData *data = user_data;
+
+ priv = GET_PRIV (data->self);
+ priv->sasl_handler = empathy_server_sasl_handler_new_finish (res, &error);
+
+ if (error != NULL)
+ {
+ DEBUG ("Failed to create a server SASL handler; error %s",
+ error->message);
+ tp_handle_channels_context_fail (data->context, error);
+
+ g_error_free (error);
+ }
+ else
+ {
+ tp_handle_channels_context_accept (data->context);
+
+ g_signal_connect (priv->sasl_handler, "invalidated",
+ G_CALLBACK (sasl_handler_invalidated_cb), data->self);
+
+ g_signal_emit (data->self, signals[NEW_SERVER_SASL_HANDLER], 0,
+ priv->sasl_handler);
+ }
+
+ handler_context_data_free (data);
+}
+
+static void
handle_channels_cb (TpSimpleHandler *handler,
TpAccount *account,
TpConnection *connection,
@@ -124,18 +177,22 @@ handle_channels_cb (TpSimpleHandler *handler,
const GError *dbus_error;
GError *error = NULL;
EmpathyAuthFactory *self = user_data;
+ EmpathyAuthFactoryPriv *priv = GET_PRIV (self);
HandlerContextData *data;
+ GHashTable *props;
+ const gchar * const *available_mechanisms;
- DEBUG ("Handle TLS carrier channels.");
+ DEBUG ("Handle TLS or SASL carrier channels.");
- /* there can't be more than one ServerTLSConnection channels
- * at the same time, for the same connection/account.
+ /* there can't be more than one ServerTLSConnection or
+ * ServerAuthentication channels at the same time, for the same
+ * connection/account.
*/
if (g_list_length (channels) != 1)
{
g_set_error_literal (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
- "Can't handle more than one ServerTLSConnection channel "
- "for the same connection.");
+ "Can't handle more than one ServerTLSConnection or ServerAuthentication "
+ "channel for the same connection.");
goto error;
}
@@ -143,11 +200,38 @@ handle_channels_cb (TpSimpleHandler *handler,
channel = channels->data;
if (tp_channel_get_channel_type_id (channel) !=
- EMP_IFACE_QUARK_CHANNEL_TYPE_SERVER_TLS_CONNECTION)
+ EMP_IFACE_QUARK_CHANNEL_TYPE_SERVER_TLS_CONNECTION
+ && tp_channel_get_channel_type_id (channel) !=
+ TP_IFACE_QUARK_CHANNEL_TYPE_SERVER_AUTHENTICATION)
{
g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
- "Can only handle ServerTLSConnection channels, this was a %s "
- "channel", tp_channel_get_channel_type (channel));
+ "Can only handle ServerTLSConnection or ServerAuthentication channels, "
+ "this was a %s channel", tp_channel_get_channel_type (channel));
+
+ goto error;
+ }
+
+ if (tp_channel_get_channel_type_id (channel) ==
+ TP_IFACE_QUARK_CHANNEL_TYPE_SERVER_AUTHENTICATION
+ && priv->sasl_handler != NULL)
+ {
+ g_set_error_literal (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
+ "Can't handle more than one ServerAuthentication channel at one time");
+
+ goto error;
+ }
+
+ props = tp_channel_borrow_immutable_properties (channel);
+ available_mechanisms = tp_asv_get_boxed (props,
+ TP_PROP_CHANNEL_INTERFACE_SASL_AUTHENTICATION_AVAILABLE_MECHANISMS,
+ G_TYPE_STRV);
+
+ if (tp_channel_get_channel_type_id (channel) ==
+ TP_IFACE_QUARK_CHANNEL_TYPE_SERVER_AUTHENTICATION
+ && !tp_strv_contains (available_mechanisms, "X-TELEPATHY-PASSWORD"))
+ {
+ g_set_error_literal (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
+ "Only the X-TELEPATHY-PASSWORD SASL mechanism is supported");
goto error;
}
@@ -160,12 +244,22 @@ handle_channels_cb (TpSimpleHandler *handler,
goto error;
}
- /* create a handler */
data = handler_context_data_new (self, context);
tp_handle_channels_context_delay (context);
- empathy_server_tls_handler_new_async (channel, server_tls_handler_ready_cb,
- data);
+ /* create a handler */
+ if (tp_channel_get_channel_type_id (channel) ==
+ EMP_IFACE_QUARK_CHANNEL_TYPE_SERVER_TLS_CONNECTION)
+ {
+ empathy_server_tls_handler_new_async (channel, server_tls_handler_ready_cb,
+ data);
+ }
+ else if (tp_channel_get_channel_type_id (channel) ==
+ TP_IFACE_QUARK_CHANNEL_TYPE_SERVER_AUTHENTICATION)
+ {
+ empathy_server_sasl_handler_new_async (account, channel,
+ server_sasl_handler_ready_cb, data);
+ }
return;
error:
@@ -218,12 +312,23 @@ empathy_auth_factory_init (EmpathyAuthFactory *self)
FALSE, handle_channels_cb, self, NULL);
tp_base_client_take_handler_filter (priv->handler, tp_asv_new (
+ /* ChannelType */
TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
EMP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION,
+ /* AuthenticationMethod */
TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT,
TP_HANDLE_TYPE_NONE, NULL));
- g_object_unref (bus);
+ tp_base_client_take_handler_filter (priv->handler, tp_asv_new (
+ /* ChannelType */
+ TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
+ TP_IFACE_CHANNEL_TYPE_SERVER_AUTHENTICATION,
+ /* AuthenticationMethod */
+ TP_PROP_CHANNEL_TYPE_SERVER_AUTHENTICATION_AUTHENTICATION_METHOD,
+ G_TYPE_STRING, TP_IFACE_CHANNEL_INTERFACE_SASL_AUTHENTICATION,
+ NULL));
+
+ g_object_unref (bus);
}
static void
@@ -237,6 +342,7 @@ empathy_auth_factory_dispose (GObject *object)
priv->dispose_run = TRUE;
tp_clear_object (&priv->handler);
+ tp_clear_object (&priv->sasl_handler);
G_OBJECT_CLASS (empathy_auth_factory_parent_class)->dispose (object);
}
@@ -259,6 +365,15 @@ empathy_auth_factory_class_init (EmpathyAuthFactoryClass *klass)
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE,
1, EMPATHY_TYPE_SERVER_TLS_HANDLER);
+
+ signals[NEW_SERVER_SASL_HANDLER] =
+ g_signal_new ("new-server-sasl-handler",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST, 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE,
+ 1, EMPATHY_TYPE_SERVER_SASL_HANDLER);
}
EmpathyAuthFactory *