aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Barnes <mbarnes@redhat.com>2012-10-11 10:06:59 +0800
committerMatthew Barnes <mbarnes@redhat.com>2012-10-12 00:11:57 +0800
commit1ed5b89c02656c9172957980c85e412a27b2e6a2 (patch)
treeb21f43ddf9e30481c65d18351b31e317d2a98db1
parent1166789bd6993dfa02c06b0863047617e97fca34 (diff)
downloadgsoc2013-evolution-1ed5b89c02656c9172957980c85e412a27b2e6a2.tar
gsoc2013-evolution-1ed5b89c02656c9172957980c85e412a27b2e6a2.tar.gz
gsoc2013-evolution-1ed5b89c02656c9172957980c85e412a27b2e6a2.tar.bz2
gsoc2013-evolution-1ed5b89c02656c9172957980c85e412a27b2e6a2.tar.lz
gsoc2013-evolution-1ed5b89c02656c9172957980c85e412a27b2e6a2.tar.xz
gsoc2013-evolution-1ed5b89c02656c9172957980c85e412a27b2e6a2.tar.zst
gsoc2013-evolution-1ed5b89c02656c9172957980c85e412a27b2e6a2.zip
Prototype CamelSaslXOAuth2.
Untested, but conforms to the specification as well as I understand it.
-rw-r--r--modules/online-accounts/Makefile.am13
-rw-r--r--modules/online-accounts/camel-sasl-xoauth2.c266
-rw-r--r--modules/online-accounts/camel-sasl-xoauth2.h65
-rw-r--r--modules/online-accounts/evolution-online-accounts.c2
4 files changed, 343 insertions, 3 deletions
diff --git a/modules/online-accounts/Makefile.am b/modules/online-accounts/Makefile.am
index 9b30ced4f0..d12fd08d03 100644
--- a/modules/online-accounts/Makefile.am
+++ b/modules/online-accounts/Makefile.am
@@ -1,3 +1,5 @@
+NULL =
+
module_LTLIBRARIES = module-online-accounts.la
module_online_accounts_la_CPPFLAGS = \
@@ -6,12 +8,16 @@ module_online_accounts_la_CPPFLAGS = \
-DG_LOG_DOMAIN=\"evolution-online-accounts\" \
$(EVOLUTION_DATA_SERVER_CFLAGS) \
$(GNOME_PLATFORM_CFLAGS) \
- $(GOA_CFLAGS)
+ $(GOA_CFLAGS) \
+ $(NULL)
module_online_accounts_la_SOURCES = \
evolution-online-accounts.c \
camel-sasl-xoauth.c \
- camel-sasl-xoauth.h
+ camel-sasl-xoauth.h \
+ camel-sasl-xoauth2.c \
+ camel-sasl-xoauth2.h \
+ $(NULL)
module_online_accounts_la_LIBADD = \
$(top_builddir)/e-util/libeutil.la \
@@ -20,7 +26,8 @@ module_online_accounts_la_LIBADD = \
$(top_builddir)/libemail-utils/libemail-utils.la \
$(EVOLUTION_DATA_SERVER_LIBS) \
$(GNOME_PLATFORM_LIBS) \
- $(GOA_LIBS)
+ $(GOA_LIBS) \
+ $(NULL)
module_online_accounts_la_LDFLAGS = \
-module -avoid-version $(NO_UNDEFINED)
diff --git a/modules/online-accounts/camel-sasl-xoauth2.c b/modules/online-accounts/camel-sasl-xoauth2.c
new file mode 100644
index 0000000000..eca048affa
--- /dev/null
+++ b/modules/online-accounts/camel-sasl-xoauth2.c
@@ -0,0 +1,266 @@
+/*
+ * camel-sasl-xoauth2.c
+ *
+ * This program 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 of the License, or (at your option) version 3.
+ *
+ * This program 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 the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+/* XXX Yeah, yeah... */
+#define GOA_API_IS_SUBJECT_TO_CHANGE
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+
+#include <goa/goa.h>
+
+#include <libemail-engine/e-mail-session.h>
+
+#include "camel-sasl-xoauth2.h"
+
+#define CAMEL_SASL_XOAUTH2_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), CAMEL_TYPE_SASL_XOAUTH2, CamelSaslXOAuth2Private))
+
+struct _CamelSaslXOAuth2Private {
+ gint placeholder;
+};
+
+G_DEFINE_DYNAMIC_TYPE (CamelSaslXOAuth2, camel_sasl_xoauth2, CAMEL_TYPE_SASL)
+
+static void
+sasl_xoauth2_append_request (GByteArray *byte_array,
+ const gchar *identity,
+ const gchar *access_token)
+{
+ GString *request;
+
+ /* Compared to OAuth 1.0, this step is trivial. */
+
+ /* The request is easier to assemble with a GString. */
+ request = g_string_sized_new (512);
+
+ g_string_append (request, "user=");
+ g_string_append (request, identity);
+ g_string_append_c (request, 1);
+ g_string_append (request, "auth=Bearer ");
+ g_string_append (request, access_token);
+ g_string_append_c (request, 1);
+ g_string_append_c (request, 1);
+
+ /* Copy the GString content to the GByteArray. */
+ g_byte_array_append (
+ byte_array, (guint8 *) request->str, request->len);
+
+ g_string_free (request, TRUE);
+}
+
+static gchar *
+sasl_xoauth2_find_account_id (ESourceRegistry *registry,
+ const gchar *uid)
+{
+ ESource *source;
+ ESource *ancestor;
+ const gchar *extension_name;
+ gchar *account_id = NULL;
+
+ extension_name = E_SOURCE_EXTENSION_GOA;
+
+ source = e_source_registry_ref_source (registry, uid);
+ g_return_val_if_fail (source != NULL, NULL);
+
+ ancestor = e_source_registry_find_extension (
+ registry, source, extension_name);
+
+ if (ancestor != NULL) {
+ ESourceGoa *extension;
+
+ extension = e_source_get_extension (ancestor, extension_name);
+ account_id = e_source_goa_dup_account_id (extension);
+
+ g_object_unref (ancestor);
+ }
+
+ g_object_unref (source);
+
+ return account_id;
+}
+
+static GoaObject *
+sasl_xoauth2_get_account_by_id (GoaClient *client,
+ const gchar *account_id)
+{
+ GoaObject *match = NULL;
+ GList *list, *iter;
+
+ list = goa_client_get_accounts (client);
+
+ for (iter = list; iter != NULL; iter = g_list_next (iter)) {
+ GoaObject *goa_object;
+ GoaAccount *goa_account;
+ const gchar *candidate_id;
+
+ goa_object = GOA_OBJECT (iter->data);
+ goa_account = goa_object_get_account (goa_object);
+ candidate_id = goa_account_get_id (goa_account);
+
+ if (g_strcmp0 (account_id, candidate_id) == 0)
+ match = g_object_ref (goa_object);
+
+ g_object_unref (goa_account);
+
+ if (match != NULL)
+ break;
+ }
+
+ g_list_free_full (list, (GDestroyNotify) g_object_unref);
+
+ return match;
+}
+
+static GByteArray *
+sasl_xoauth2_challenge_sync (CamelSasl *sasl,
+ GByteArray *token,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GoaClient *goa_client;
+ GoaObject *goa_object;
+ GoaAccount *goa_account;
+ GByteArray *byte_array = NULL;
+ CamelService *service;
+ CamelSession *session;
+ ESourceRegistry *registry;
+ const gchar *uid;
+ gchar *account_id;
+ gboolean success;
+
+ service = camel_sasl_get_service (sasl);
+ session = camel_service_get_session (service);
+ registry = e_mail_session_get_registry (E_MAIL_SESSION (session));
+
+ goa_client = goa_client_new_sync (cancellable, error);
+ if (goa_client == NULL)
+ return NULL;
+
+ uid = camel_service_get_uid (service);
+ account_id = sasl_xoauth2_find_account_id (registry, uid);
+ goa_object = sasl_xoauth2_get_account_by_id (goa_client, account_id);
+
+ g_free (account_id);
+
+ if (goa_object == NULL) {
+ g_set_error_literal (
+ error, CAMEL_SERVICE_ERROR,
+ CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
+ _("Cannot find a corresponding account in "
+ "the org.gnome.OnlineAccounts service from "
+ "which to obtain an authentication token."));
+ g_object_unref (goa_client);
+ return NULL;
+ }
+
+ goa_account = goa_object_get_account (goa_object);
+
+ success = goa_account_call_ensure_credentials_sync (
+ goa_account, NULL, cancellable, error);
+
+ if (success) {
+ GoaOAuth2Based *goa_oauth2_based;
+ gchar *access_token = NULL;
+
+ goa_oauth2_based = goa_object_get_oauth2_based (goa_object);
+
+ success = goa_oauth2_based_call_get_access_token_sync (
+ goa_oauth2_based,
+ &access_token, NULL,
+ cancellable, error);
+
+ if (success) {
+ gchar *identity;
+
+ identity = goa_account_dup_identity (goa_account);
+
+ byte_array = g_byte_array_new ();
+ sasl_xoauth2_append_request (
+ byte_array, identity, access_token);
+
+ g_free (identity);
+ }
+
+ g_free (access_token);
+
+ g_object_unref (goa_oauth2_based);
+ }
+
+ g_object_unref (goa_account);
+ g_object_unref (goa_object);
+ g_object_unref (goa_client);
+
+ /* IMAP and SMTP services will Base64-encode the request. */
+
+ return byte_array;
+}
+
+static gpointer
+camel_sasl_xoauth2_auth_type_init (gpointer unused)
+{
+ CamelServiceAuthType *auth_type;
+
+ /* This is a one-time allocation, never freed. */
+ auth_type = g_malloc0 (sizeof (CamelServiceAuthType));
+ auth_type->name = _("OAuth2");
+ auth_type->description =
+ _("This option will connect to the server by "
+ "way of the GNOME Online Accounts service");
+ auth_type->authproto = "XOAUTH2";
+ auth_type->need_password = FALSE;
+
+ return auth_type;
+}
+
+static void
+camel_sasl_xoauth2_class_init (CamelSaslXOAuth2Class *class)
+{
+ static GOnce auth_type_once = G_ONCE_INIT;
+ CamelSaslClass *sasl_class;
+
+ g_once (&auth_type_once, camel_sasl_xoauth2_auth_type_init, NULL);
+
+ g_type_class_add_private (class, sizeof (CamelSaslXOAuth2Private));
+
+ sasl_class = CAMEL_SASL_CLASS (class);
+ sasl_class->auth_type = auth_type_once.retval;
+ sasl_class->challenge_sync = sasl_xoauth2_challenge_sync;
+}
+
+static void
+camel_sasl_xoauth2_class_finalize (CamelSaslXOAuth2Class *class)
+{
+}
+
+static void
+camel_sasl_xoauth2_init (CamelSaslXOAuth2 *sasl)
+{
+ sasl->priv = CAMEL_SASL_XOAUTH2_GET_PRIVATE (sasl);
+}
+
+void
+camel_sasl_xoauth2_type_register (GTypeModule *type_module)
+{
+ /* XXX G_DEFINE_DYNAMIC_TYPE declares a static type registration
+ * function, so we have to wrap it with a public function in
+ * order to register types from a separate compilation unit. */
+ camel_sasl_xoauth2_register_type (type_module);
+}
+
diff --git a/modules/online-accounts/camel-sasl-xoauth2.h b/modules/online-accounts/camel-sasl-xoauth2.h
new file mode 100644
index 0000000000..3528d83f9b
--- /dev/null
+++ b/modules/online-accounts/camel-sasl-xoauth2.h
@@ -0,0 +1,65 @@
+/*
+ * camel-sasl-xoauth2.h
+ *
+ * This program 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 of the License, or (at your option) version 3.
+ *
+ * This program 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 the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef CAMEL_SASL_XOAUTH2_H
+#define CAMEL_SASL_XOAUTH2_H
+
+#include <camel/camel.h>
+
+/* Standard GObject macros */
+#define CAMEL_TYPE_SASL_XOAUTH2 \
+ (camel_sasl_xoauth2_get_type ())
+#define CAMEL_SASL_XOAUTH2(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), CAMEL_TYPE_SASL_XOAUTH2, CamelSaslXOAuth2))
+#define CAMEL_SASL_XOAUTH2_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), CAMEL_TYPE_SASL_XOAUTH2, CamelSaslXOAuth2Class))
+#define CAMEL_IS_SASL_XOAUTH2(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), CAMEL_TYPE_SASL_XOAUTH2))
+#define CAMEL_IS_SASL_XOAUTH2_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), CAMEL_TYPE_SASL_XOAUTH2))
+#define CAMEL_SASL_XOAUTH2_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), CAMEL_TYPE_SASL_XOAUTH2, CamelSaslXOAuth2Class))
+
+G_BEGIN_DECLS
+
+typedef struct _CamelSaslXOAuth2 CamelSaslXOAuth2;
+typedef struct _CamelSaslXOAuth2Class CamelSaslXOAuth2Class;
+typedef struct _CamelSaslXOAuth2Private CamelSaslXOAuth2Private;
+
+struct _CamelSaslXOAuth2 {
+ CamelSasl parent;
+ CamelSaslXOAuth2Private *priv;
+};
+
+struct _CamelSaslXOAuth2Class {
+ CamelSaslClass parent_class;
+};
+
+GType camel_sasl_xoauth2_get_type (void);
+void camel_sasl_xoauth2_type_register
+ (GTypeModule *type_module);
+
+G_END_DECLS
+
+#endif /* CAMEL_SASL_XOAUTH2_H */
+
diff --git a/modules/online-accounts/evolution-online-accounts.c b/modules/online-accounts/evolution-online-accounts.c
index 9f80c93c7a..1093e6d818 100644
--- a/modules/online-accounts/evolution-online-accounts.c
+++ b/modules/online-accounts/evolution-online-accounts.c
@@ -17,6 +17,7 @@
*/
#include "camel-sasl-xoauth.h"
+#include "camel-sasl-xoauth2.h"
/* Module Entry Points */
void e_module_load (GTypeModule *type_module);
@@ -26,6 +27,7 @@ G_MODULE_EXPORT void
e_module_load (GTypeModule *type_module)
{
camel_sasl_xoauth_type_register (type_module);
+ camel_sasl_xoauth2_type_register (type_module);
}
G_MODULE_EXPORT void