diff options
-rw-r--r-- | libemail-engine/Makefile.am | 2 | ||||
-rw-r--r-- | libemail-engine/camel-sasl-xoauth2.c | 131 | ||||
-rw-r--r-- | libemail-engine/camel-sasl-xoauth2.h (renamed from modules/online-accounts/camel-sasl-xoauth2.h) | 4 | ||||
-rw-r--r-- | libemail-engine/e-mail-session.c | 6 | ||||
-rw-r--r-- | modules/online-accounts/Makefile.am | 2 | ||||
-rw-r--r-- | modules/online-accounts/camel-sasl-xoauth2.c | 266 | ||||
-rw-r--r-- | modules/online-accounts/evolution-online-accounts.c | 2 |
7 files changed, 140 insertions, 273 deletions
diff --git a/libemail-engine/Makefile.am b/libemail-engine/Makefile.am index 215d48e934..60a8437c6e 100644 --- a/libemail-engine/Makefile.am +++ b/libemail-engine/Makefile.am @@ -25,6 +25,7 @@ libemail_engine_la_CPPFLAGS = \ libmailengineincludedir = $(privincludedir)/libemail-engine libmailengineinclude_HEADERS = \ camel-null-store.h \ + camel-sasl-xoauth2.h \ e-mail-authenticator.h \ e-mail-enums.h \ e-mail-enumtypes.h \ @@ -48,6 +49,7 @@ libmailengineinclude_HEADERS = \ libemail_engine_la_SOURCES = \ $(libmailengineinclude_HEADERS) \ camel-null-store.c \ + camel-sasl-xoauth2.c \ e-mail-authenticator.c \ e-mail-enumtypes.c \ e-mail-folder-utils.c \ diff --git a/libemail-engine/camel-sasl-xoauth2.c b/libemail-engine/camel-sasl-xoauth2.c new file mode 100644 index 0000000000..3cf43e7393 --- /dev/null +++ b/libemail-engine/camel-sasl-xoauth2.c @@ -0,0 +1,131 @@ +/* + * 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/> + * + */ + +#include <config.h> +#include <glib/gi18n-lib.h> + +#include "camel-sasl-xoauth2.h" + +#include <libemail-engine/e-mail-session.h> + +static CamelServiceAuthType sasl_xoauth2_auth_type = { + N_("OAuth2"), + N_("This option will use an OAuth 2.0 " + "access token to connect to the server"), + "XOAUTH2", + FALSE +}; + +G_DEFINE_TYPE (CamelSaslXOAuth2, camel_sasl_xoauth2, CAMEL_TYPE_SASL) + +static void +sasl_xoauth2_append_request (GByteArray *byte_array, + const gchar *user, + const gchar *access_token) +{ + GString *request; + + g_return_if_fail (user != NULL); + g_return_if_fail (access_token != NULL); + + /* 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, user); + 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 GByteArray * +sasl_xoauth2_challenge_sync (CamelSasl *sasl, + GByteArray *token, + GCancellable *cancellable, + GError **error) +{ + GByteArray *byte_array = NULL; + CamelService *service; + CamelSession *session; + CamelSettings *settings; + ESourceRegistry *registry; + ESource *source; + const gchar *uid; + gchar *access_token = NULL; + gboolean success; + + service = camel_sasl_get_service (sasl); + session = camel_service_get_session (service); + settings = camel_service_ref_settings (service); + + uid = camel_service_get_uid (service); + registry = e_mail_session_get_registry (E_MAIL_SESSION (session)); + source = e_source_registry_ref_source (registry, uid); + g_return_val_if_fail (source != NULL, NULL); + + success = e_source_get_oauth2_access_token_sync ( + source, cancellable, &access_token, NULL, error); + + if (success) { + CamelNetworkSettings *network_settings; + gchar *user; + + network_settings = CAMEL_NETWORK_SETTINGS (settings); + user = camel_network_settings_dup_user (network_settings); + + byte_array = g_byte_array_new (); + sasl_xoauth2_append_request (byte_array, user, access_token); + + g_free (user); + } + + g_free (access_token); + + g_object_unref (source); + g_object_unref (settings); + + /* IMAP and SMTP services will Base64-encode the request. */ + + return byte_array; +} + +static void +camel_sasl_xoauth2_class_init (CamelSaslXOAuth2Class *class) +{ + CamelSaslClass *sasl_class; + + sasl_class = CAMEL_SASL_CLASS (class); + sasl_class->auth_type = &sasl_xoauth2_auth_type; + sasl_class->challenge_sync = sasl_xoauth2_challenge_sync; +} + +static void +camel_sasl_xoauth2_init (CamelSaslXOAuth2 *sasl) +{ +} + diff --git a/modules/online-accounts/camel-sasl-xoauth2.h b/libemail-engine/camel-sasl-xoauth2.h index 3528d83f9b..940964b498 100644 --- a/modules/online-accounts/camel-sasl-xoauth2.h +++ b/libemail-engine/camel-sasl-xoauth2.h @@ -55,9 +55,7 @@ struct _CamelSaslXOAuth2Class { CamelSaslClass parent_class; }; -GType camel_sasl_xoauth2_get_type (void); -void camel_sasl_xoauth2_type_register - (GTypeModule *type_module); +GType camel_sasl_xoauth2_get_type (void) G_GNUC_CONST; G_END_DECLS diff --git a/libemail-engine/e-mail-session.c b/libemail-engine/e-mail-session.c index 30a83d4230..b195238145 100644 --- a/libemail-engine/e-mail-session.c +++ b/libemail-engine/e-mail-session.c @@ -51,6 +51,9 @@ /* This is our hack, not part of libcamel. */ #include "camel-null-store.h" +/* This too, though it's less of a hack. */ +#include "camel-sasl-xoauth2.h" + #include "e-mail-authenticator.h" #include "e-mail-junk-filter.h" #include "e-mail-session.h" @@ -1963,6 +1966,9 @@ e_mail_session_class_init (EMailSessionClass *class) /* Make sure ESourceCamel picks up the "none" provider. */ e_source_camel_generate_subtype ("none", CAMEL_TYPE_SETTINGS); + + /* Make sure CamelSasl picks up the XOAUTH2 mechanism. */ + g_type_ensure (CAMEL_TYPE_SASL_XOAUTH2); } static void diff --git a/modules/online-accounts/Makefile.am b/modules/online-accounts/Makefile.am index 2ee4bc6940..dbf222ecdb 100644 --- a/modules/online-accounts/Makefile.am +++ b/modules/online-accounts/Makefile.am @@ -16,8 +16,6 @@ module_online_accounts_la_SOURCES = \ evolution-online-accounts.c \ camel-sasl-xoauth.c \ camel-sasl-xoauth.h \ - camel-sasl-xoauth2.c \ - camel-sasl-xoauth2.h \ $(NULL) module_online_accounts_la_LIBADD = \ diff --git a/modules/online-accounts/camel-sasl-xoauth2.c b/modules/online-accounts/camel-sasl-xoauth2.c deleted file mode 100644 index eca048affa..0000000000 --- a/modules/online-accounts/camel-sasl-xoauth2.c +++ /dev/null @@ -1,266 +0,0 @@ -/* - * 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/evolution-online-accounts.c b/modules/online-accounts/evolution-online-accounts.c index 1093e6d818..9f80c93c7a 100644 --- a/modules/online-accounts/evolution-online-accounts.c +++ b/modules/online-accounts/evolution-online-accounts.c @@ -17,7 +17,6 @@ */ #include "camel-sasl-xoauth.h" -#include "camel-sasl-xoauth2.h" /* Module Entry Points */ void e_module_load (GTypeModule *type_module); @@ -27,7 +26,6 @@ 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 |