aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXavier Claessens <xavier.claessens@collabora.co.uk>2012-07-16 20:15:45 +0800
committerXavier Claessens <xavier.claessens@collabora.co.uk>2012-07-23 20:34:17 +0800
commitfa8970d7304e81821dd0b1ed6a6704add1904af9 (patch)
treecac1ba13af9018444de1436e26e457fcd6728b48
parentf32e5ba5af1dfa3a0ceb4fde6e96b31a74b195c5 (diff)
downloadgsoc2013-empathy-fa8970d7304e81821dd0b1ed6a6704add1904af9.tar
gsoc2013-empathy-fa8970d7304e81821dd0b1ed6a6704add1904af9.tar.gz
gsoc2013-empathy-fa8970d7304e81821dd0b1ed6a6704add1904af9.tar.bz2
gsoc2013-empathy-fa8970d7304e81821dd0b1ed6a6704add1904af9.tar.lz
gsoc2013-empathy-fa8970d7304e81821dd0b1ed6a6704add1904af9.tar.xz
gsoc2013-empathy-fa8970d7304e81821dd0b1ed6a6704add1904af9.tar.zst
gsoc2013-empathy-fa8970d7304e81821dd0b1ed6a6704add1904af9.zip
Add Ubuntu Online Accounts auth handler
-rw-r--r--configure.ac2
-rw-r--r--libempathy/Makefile.am15
-rw-r--r--libempathy/empathy-auth-factory.c56
-rw-r--r--libempathy/empathy-uoa-auth-handler.c299
-rw-r--r--libempathy/empathy-uoa-auth-handler.h72
5 files changed, 444 insertions, 0 deletions
diff --git a/configure.ac b/configure.ac
index 290280d1c..ed9b560ec 100644
--- a/configure.ac
+++ b/configure.ac
@@ -76,6 +76,7 @@ NETWORK_MANAGER_REQUIRED=0.7.0
CHAMPLAIN_REQUIRED=0.12.1
CHEESE_GTK_REQUIRED=3.4.0
LIBACCOUNTS_REQUIRED=1.1
+LIBSIGNON_REQUIRED=1.1
MC_PLUGINS_REQUIRED=5.13.0
# Use --enable-maintainer-mode to disable deprecated symbols,
@@ -514,6 +515,7 @@ if test "x$enable_ubuntu_online_accounts" != "xno"; then
account-plugin
mission-control-plugins >= $MC_PLUGINS_REQUIRED
libaccounts-glib >= $LIBACCOUNTS_REQUIRED
+ libsignon-glib >= $LIBSIGNON_REQUIRED
], have_uoa="yes", have_uoa="no")
# MC plugins dir
diff --git a/libempathy/Makefile.am b/libempathy/Makefile.am
index 67e64a9f6..2274b99ed 100644
--- a/libempathy/Makefile.am
+++ b/libempathy/Makefile.am
@@ -16,6 +16,7 @@ AM_CPPFLAGS = \
$(CONNMAN_CFLAGS) \
$(UDEV_CFLAGS) \
$(GOA_CFLAGS) \
+ $(UOA_CFLAGS) \
$(WARN_CFLAGS) \
$(DISABLE_DEPRECATED)
@@ -99,6 +100,12 @@ goa_sources = \
empathy-goa-auth-handler.h \
$(NULL)
+# these are sources that depend on Ubuntu Online Accounts
+uoa_sources = \
+ empathy-uoa-auth-handler.c \
+ empathy-uoa-auth-handler.h \
+ $(NULL)
+
pkglib_LTLIBRARIES = libempathy.la
# libempathy's API is not stable and will never be, so use -release to make the
@@ -122,6 +129,7 @@ libempathy_la_LIBADD = \
$(CONNMAN_LIBS) \
$(UDEV_LIBS) \
$(GOA_LIBS) \
+ $(UOA_LIBS) \
$(LIBM)
dtddir = $(datadir)/empathy
@@ -149,6 +157,12 @@ else
EXTRA_DIST += $(goa_sources)
endif
+if HAVE_UOA
+libempathy_la_SOURCES += $(uoa_sources)
+else
+EXTRA_DIST += $(uoa_sources)
+endif
+
# do not distribute generated files
nodist_libempathy_la_SOURCES =\
$(BUILT_SOURCES)
@@ -156,6 +170,7 @@ nodist_libempathy_la_SOURCES =\
check_c_sources = \
$(libempathy_handwritten_source) \
$(goa_sources) \
+ $(uoa_sources) \
$(NULL)
include $(top_srcdir)/tools/check-coding-style.mk
diff --git a/libempathy/empathy-auth-factory.c b/libempathy/empathy-auth-factory.c
index 922528577..a4bc15a62 100644
--- a/libempathy/empathy-auth-factory.c
+++ b/libempathy/empathy-auth-factory.c
@@ -36,6 +36,10 @@
#include "empathy-goa-auth-handler.h"
#endif /* HAVE_GOA */
+#ifdef HAVE_UOA
+#include "empathy-uoa-auth-handler.h"
+#endif /* HAVE_UOA */
+
#include "extensions/extensions.h"
G_DEFINE_TYPE (EmpathyAuthFactory, empathy_auth_factory, TP_TYPE_BASE_CLIENT);
@@ -54,6 +58,10 @@ struct _EmpathyAuthFactoryPriv {
EmpathyGoaAuthHandler *goa_handler;
#endif /* HAVE_GOA */
+#ifdef HAVE_UOA
+ EmpathyUoaAuthHandler *uoa_handler;
+#endif /* HAVE_UOA */
+
/* If an account failed to connect and user enters a new password to try, we
* store it in this hash table and will try to use it next time the account
* attemps to connect.
@@ -474,6 +482,32 @@ goa_claim_cb (GObject *source,
}
#endif /* HAVE_GOA */
+#ifdef HAVE_UOA
+static void
+uoa_claim_cb (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ ObserveChannelsData *data = user_data;
+ EmpathyAuthFactory *self = data->self;
+ GError *error = NULL;
+
+ if (!tp_channel_dispatch_operation_claim_with_finish (data->dispatch_operation,
+ result, &error))
+ {
+ DEBUG ("Failed to claim: %s", error->message);
+ g_clear_error (&error);
+ }
+ else
+ {
+ empathy_uoa_auth_handler_start (self->priv->uoa_handler,
+ data->channel, data->account);
+ }
+
+ observe_channels_data_free (data);
+}
+#endif /* HAVE_UOA */
+
static void
observe_channels (TpBaseClient *client,
TpAccount *account,
@@ -522,6 +556,20 @@ observe_channels (TpBaseClient *client,
}
#endif /* HAVE_GOA */
+#ifdef HAVE_UOA
+ /* UOA auth? */
+ if (empathy_uoa_auth_handler_supports (self->priv->uoa_handler, channel, account))
+ {
+ DEBUG ("Supported UOA account (%s), claim SASL channel",
+ tp_proxy_get_object_path (account));
+
+ tp_channel_dispatch_operation_claim_with_async (dispatch_operation,
+ client, uoa_claim_cb, data);
+ tp_observe_channels_context_accept (context);
+ return;
+ }
+#endif /* HAVE_UOA */
+
/* Password auth? */
if (empathy_sasl_channel_supports_mechanism (data->channel,
"X-TELEPATHY-PASSWORD"))
@@ -589,6 +637,10 @@ empathy_auth_factory_init (EmpathyAuthFactory *self)
self->priv->goa_handler = empathy_goa_auth_handler_new ();
#endif /* HAVE_GOA */
+#ifdef HAVE_UOA
+ self->priv->uoa_handler = empathy_uoa_auth_handler_new ();
+#endif /* HAVE_UOA */
+
self->priv->retry_passwords = g_hash_table_new_full (NULL, NULL,
g_object_unref, g_free);
}
@@ -657,6 +709,10 @@ empathy_auth_factory_dispose (GObject *object)
g_object_unref (priv->goa_handler);
#endif /* HAVE_GOA */
+#ifdef HAVE_UOA
+ g_object_unref (priv->uoa_handler);
+#endif /* HAVE_UOA */
+
g_hash_table_unref (priv->retry_passwords);
G_OBJECT_CLASS (empathy_auth_factory_parent_class)->dispose (object);
diff --git a/libempathy/empathy-uoa-auth-handler.c b/libempathy/empathy-uoa-auth-handler.c
new file mode 100644
index 000000000..1bfd6e16d
--- /dev/null
+++ b/libempathy/empathy-uoa-auth-handler.c
@@ -0,0 +1,299 @@
+/*
+ * empathy-auth-uoa.c - Source for Uoa SASL authentication
+ * Copyright (C) 2012 Collabora Ltd.
+ * @author Xavier Claessens <xavier.claessens@collabora.co.uk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+
+#include <libaccounts-glib/ag-account.h>
+#include <libaccounts-glib/ag-account-service.h>
+#include <libaccounts-glib/ag-auth-data.h>
+#include <libaccounts-glib/ag-manager.h>
+#include <libaccounts-glib/ag-service.h>
+
+#include <libsignon-glib/signon-identity.h>
+#include <libsignon-glib/signon-auth-session.h>
+
+#define DEBUG_FLAG EMPATHY_DEBUG_SASL
+#include "empathy-debug.h"
+#include "empathy-utils.h"
+#include "empathy-uoa-auth-handler.h"
+#include "empathy-sasl-mechanisms.h"
+
+#define SERVICE_TYPE "IM"
+
+struct _EmpathyUoaAuthHandlerPriv
+{
+ AgManager *manager;
+};
+
+G_DEFINE_TYPE (EmpathyUoaAuthHandler, empathy_uoa_auth_handler, G_TYPE_OBJECT);
+
+static void
+empathy_uoa_auth_handler_init (EmpathyUoaAuthHandler *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+ EMPATHY_TYPE_UOA_AUTH_HANDLER, EmpathyUoaAuthHandlerPriv);
+
+ self->priv->manager = ag_manager_new_for_service_type (SERVICE_TYPE);
+}
+
+static void
+empathy_uoa_auth_handler_dispose (GObject *object)
+{
+ EmpathyUoaAuthHandler *self = (EmpathyUoaAuthHandler *) object;
+
+ tp_clear_object (&self->priv->manager);
+
+ G_OBJECT_CLASS (empathy_uoa_auth_handler_parent_class)->dispose (object);
+}
+
+static void
+empathy_uoa_auth_handler_class_init (EmpathyUoaAuthHandlerClass *klass)
+{
+ GObjectClass *oclass = G_OBJECT_CLASS (klass);
+
+ oclass->dispose = empathy_uoa_auth_handler_dispose;
+
+ g_type_class_add_private (klass, sizeof (EmpathyUoaAuthHandlerPriv));
+}
+
+EmpathyUoaAuthHandler *
+empathy_uoa_auth_handler_new (void)
+{
+ return g_object_new (EMPATHY_TYPE_UOA_AUTH_HANDLER, NULL);
+}
+
+static void
+auth_cb (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ TpChannel *channel = (TpChannel *) source;
+ GError *error = NULL;
+
+ if (!empathy_sasl_auth_finish (channel, result, &error))
+ {
+ DEBUG ("SASL Mechanism error: %s", error->message);
+ g_clear_error (&error);
+ }
+
+ tp_channel_close_async (channel, NULL, NULL);
+}
+
+typedef struct
+{
+ TpChannel *channel;
+ AgAuthData *auth_data;
+ SignonAuthSession *session;
+ SignonIdentity *identity;
+
+ gchar *username;
+} QueryInfoData;
+
+static QueryInfoData *
+query_info_data_new (TpChannel *channel,
+ AgAuthData *auth_data,
+ SignonAuthSession *session,
+ SignonIdentity *identity)
+{
+ QueryInfoData *data;
+
+ data = g_slice_new0 (QueryInfoData);
+ data->channel = g_object_ref (channel);
+ data->auth_data = ag_auth_data_ref (auth_data);
+ data->session = g_object_ref (session);
+ data->identity = g_object_ref (identity);
+
+ return data;
+}
+
+static void
+query_info_data_free (QueryInfoData *data)
+{
+ g_object_unref (data->channel);
+ ag_auth_data_unref (data->auth_data);
+ g_object_unref (data->session);
+ g_object_unref (data->identity);
+ g_free (data->username);
+ g_slice_free (QueryInfoData, data);
+}
+
+static void
+session_process_cb (SignonAuthSession *session,
+ GHashTable *session_data,
+ const GError *error,
+ gpointer user_data)
+{
+ QueryInfoData *data = user_data;
+ const gchar *access_token;
+ const gchar *client_id;
+
+ if (error != NULL)
+ {
+ DEBUG ("Error processing the session: %s", error->message);
+ tp_channel_close_async (data->channel, NULL, NULL);
+ query_info_data_free (data);
+ return;
+ }
+
+ access_token = tp_asv_get_string (session_data, "AccessToken");
+ client_id = tp_asv_get_string (ag_auth_data_get_parameters (data->auth_data),
+ "ClientId");
+
+ switch (empathy_sasl_channel_select_mechanism (data->channel))
+ {
+ case EMPATHY_SASL_MECHANISM_FACEBOOK:
+ empathy_sasl_auth_facebook_async (data->channel,
+ client_id, access_token,
+ auth_cb, NULL);
+ break;
+
+ case EMPATHY_SASL_MECHANISM_WLM:
+ empathy_sasl_auth_wlm_async (data->channel,
+ access_token,
+ auth_cb, NULL);
+ break;
+
+ case EMPATHY_SASL_MECHANISM_GOOGLE:
+ empathy_sasl_auth_google_async (data->channel,
+ data->username, access_token,
+ auth_cb, NULL);
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ query_info_data_free (data);
+}
+
+static void
+identity_query_info_cb (SignonIdentity *identity,
+ const SignonIdentityInfo *info,
+ const GError *error,
+ gpointer user_data)
+{
+ QueryInfoData *data = user_data;
+
+ if (error != NULL)
+ {
+ DEBUG ("Error querying info from identity: %s", error->message);
+ tp_channel_close_async (data->channel, NULL, NULL);
+ query_info_data_free (data);
+ return;
+ }
+
+ data->username = g_strdup (signon_identity_info_get_username (info));
+
+ signon_auth_session_process (data->session,
+ ag_auth_data_get_parameters (data->auth_data),
+ ag_auth_data_get_mechanism (data->auth_data),
+ session_process_cb,
+ data);
+}
+
+void
+empathy_uoa_auth_handler_start (EmpathyUoaAuthHandler *self,
+ TpChannel *channel,
+ TpAccount *tp_account)
+{
+ const GValue *id_value;
+ AgAccountId id;
+ AgAccount *account;
+ GList *l = NULL;
+ AgAccountService *service;
+ AgAuthData *auth_data;
+ guint cred_id;
+ SignonIdentity *identity;
+ SignonAuthSession *session;
+ GError *error = NULL;
+
+ g_return_if_fail (TP_IS_CHANNEL (channel));
+ g_return_if_fail (TP_IS_ACCOUNT (tp_account));
+ g_return_if_fail (empathy_uoa_auth_handler_supports (self, channel,
+ tp_account));
+
+ DEBUG ("Start UOA auth for account: %s",
+ tp_proxy_get_object_path (tp_account));
+
+ id_value = tp_account_get_storage_identifier (tp_account);
+ id = g_value_get_uint (id_value);
+
+ account = ag_manager_get_account (self->priv->manager, id);
+ if (account != NULL)
+ l = ag_account_list_services_by_type (account, SERVICE_TYPE);
+ if (l == NULL)
+ {
+ DEBUG ("Couldn't find IM service for AgAccountId %u", id);
+ g_object_unref (account);
+ tp_channel_close_async (channel, NULL, NULL);
+ return;
+ }
+
+ /* Assume there is only one IM service */
+ service = ag_account_service_new (account, l->data);
+ ag_service_list_free (l);
+ g_object_unref (account);
+
+ auth_data = ag_account_service_get_auth_data (service);
+ cred_id = ag_auth_data_get_credentials_id (auth_data);
+ identity = signon_identity_new_from_db (cred_id);
+ session = signon_identity_create_session (identity,
+ ag_auth_data_get_method (auth_data),
+ &error);
+ if (session == NULL)
+ {
+ DEBUG ("Error creating a SignonAuthSession: %s", error->message);
+ tp_channel_close_async (channel, NULL, NULL);
+ goto cleanup;
+ }
+
+ /* Query UOA for more info */
+ signon_identity_query_info (identity,
+ identity_query_info_cb,
+ query_info_data_new (channel, auth_data, session, identity));
+
+cleanup:
+ ag_auth_data_unref (auth_data);
+ g_object_unref (service);
+ g_object_unref (identity);
+ g_object_unref (session);
+}
+
+gboolean
+empathy_uoa_auth_handler_supports (EmpathyUoaAuthHandler *self,
+ TpChannel *channel,
+ TpAccount *account)
+{
+ const gchar *provider;
+ EmpathySaslMechanism mech;
+
+ g_return_val_if_fail (TP_IS_CHANNEL (channel), FALSE);
+ g_return_val_if_fail (TP_IS_ACCOUNT (account), FALSE);
+
+ provider = tp_account_get_storage_provider (account);
+
+ if (tp_strdiff (provider, EMPATHY_UOA_PROVIDER))
+ return FALSE;
+
+ mech = empathy_sasl_channel_select_mechanism (channel);
+ return mech == EMPATHY_SASL_MECHANISM_FACEBOOK ||
+ mech == EMPATHY_SASL_MECHANISM_WLM ||
+ mech == EMPATHY_SASL_MECHANISM_GOOGLE;
+}
diff --git a/libempathy/empathy-uoa-auth-handler.h b/libempathy/empathy-uoa-auth-handler.h
new file mode 100644
index 000000000..2c61a7606
--- /dev/null
+++ b/libempathy/empathy-uoa-auth-handler.h
@@ -0,0 +1,72 @@
+/*
+ * empathy-auth-uoa.h - Header for Uoa SASL authentication
+ * Copyright (C) 2012 Collabora Ltd.
+ * @author Xavier Claessens <xavier.claessens@collabora.co.uk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __EMPATHY_UOA_AUTH_HANDLER_H__
+#define __EMPATHY_UOA_AUTH_HANDLER_H__
+
+#include <telepathy-glib/telepathy-glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct _EmpathyUoaAuthHandler EmpathyUoaAuthHandler;
+typedef struct _EmpathyUoaAuthHandlerClass EmpathyUoaAuthHandlerClass;
+typedef struct _EmpathyUoaAuthHandlerPriv EmpathyUoaAuthHandlerPriv;
+
+struct _EmpathyUoaAuthHandlerClass {
+ GObjectClass parent_class;
+};
+
+struct _EmpathyUoaAuthHandler {
+ GObject parent;
+ EmpathyUoaAuthHandlerPriv *priv;
+};
+
+GType empathy_uoa_auth_handler_get_type (void);
+
+/* TYPE MACROS */
+#define EMPATHY_TYPE_UOA_AUTH_HANDLER \
+ (empathy_uoa_auth_handler_get_type ())
+#define EMPATHY_UOA_AUTH_HANDLER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), EMPATHY_TYPE_UOA_AUTH_HANDLER, \
+ EmpathyUoaAuthHandler))
+#define EMPATHY_UOA_AUTH_HANDLER_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), EMPATHY_TYPE_UOA_AUTH_HANDLER, \
+ EmpathyUoaAuthHandlerClass))
+#define EMPATHY_IS_UOA_AUTH_HANDLER(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), EMPATHY_TYPE_UOA_AUTH_HANDLER))
+#define EMPATHY_IS_UOA_AUTH_HANDLER_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), EMPATHY_TYPE_UOA_AUTH_HANDLER))
+#define EMPATHY_UOA_AUTH_HANDLER_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), EMPATHY_TYPE_UOA_AUTH_HANDLER, \
+ EmpathyUoaAuthHandlerClass))
+
+EmpathyUoaAuthHandler *empathy_uoa_auth_handler_new (void);
+
+void empathy_uoa_auth_handler_start (EmpathyUoaAuthHandler *self,
+ TpChannel *channel,
+ TpAccount *account);
+
+gboolean empathy_uoa_auth_handler_supports (EmpathyUoaAuthHandler *self,
+ TpChannel *channel,
+ TpAccount *account);
+
+G_END_DECLS
+
+#endif /* #ifndef __EMPATHY_UOA_AUTH_HANDLER_H__*/