[evolution-kolab/ek-wip-porting: 11/14] CamelKolabSession: fixups for authentication
- From: Christian Hilberg <chilberg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-kolab/ek-wip-porting: 11/14] CamelKolabSession: fixups for authentication
- Date: Tue, 13 Mar 2012 17:09:08 +0000 (UTC)
commit cecf6129b21e3cdda102b5bfc5c9c487e21c5c22
Author: Christian Hilberg <hilberg kernelconcepts de>
Date: Tue Mar 13 17:52:52 2012 +0100
CamelKolabSession: fixups for authentication
* added a dupe of the mail_session_authenticate_sync()
function from e-mail-session.c in evolution's libemail-engine
(CamelSession does no longer provide a production-ready
implementation for this)
* reworked password handling (needs further cleanup)
* removed no-longer needed API functions (the ones
needed are now accessible via virtualized functions)
src/camel/camel-kolab-session.c | 381 ++++++++++++++++++++++++---------------
src/camel/camel-kolab-session.h | 31 +---
2 files changed, 240 insertions(+), 172 deletions(-)
---
diff --git a/src/camel/camel-kolab-session.c b/src/camel/camel-kolab-session.c
index b54210b..081e6e4 100644
--- a/src/camel/camel-kolab-session.c
+++ b/src/camel/camel-kolab-session.c
@@ -51,6 +51,7 @@
/* Kolab error reporting */
#include <libekolabutil/kolab-util-error.h>
+#include "camel-kolab-imapx-store.h"
#include "camel-kolab-session.h"
/*----------------------------------------------------------------------------*/
@@ -64,8 +65,6 @@ struct _CamelKolabSessionPrivate {
/* TODO these should be retrieved
* from CamelKolabSettings instead
*/
- gchar *data_dir;
- gchar *config_dir;
gchar *passwd;
/* TODO get rid of this workaround */
@@ -88,8 +87,6 @@ camel_kolab_session_init (CamelKolabSession *self)
g_assert (CAMEL_IS_KOLAB_SESSION (self));
priv = CAMEL_KOLAB_SESSION_PRIVATE (self);
- priv->data_dir = NULL;
- priv->config_dir = NULL;
priv->nss_tok_pwd = NULL;
priv->passwd = NULL;
priv->is_initialized = FALSE;
@@ -110,15 +107,9 @@ camel_kolab_session_finalize (GObject *object)
CamelKolabSession *self = NULL;
CamelKolabSessionPrivate *priv = NULL;
- g_assert (CAMEL_IS_KOLAB_SESSION (self));
-
self = CAMEL_KOLAB_SESSION (object);
priv = CAMEL_KOLAB_SESSION_PRIVATE (self);
- if (priv->data_dir != NULL)
- g_free (priv->data_dir);
- if (priv->config_dir != NULL)
- g_free (priv->config_dir);
if (priv->nss_tok_pwd != NULL)
g_free (priv->nss_tok_pwd);
if (priv->passwd)
@@ -128,29 +119,8 @@ camel_kolab_session_finalize (GObject *object)
G_OBJECT_CLASS (camel_kolab_session_parent_class)->finalize (object);
}
-static void
-camel_kolab_session_class_init (CamelKolabSessionClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- CamelSessionClass *session_class = CAMEL_SESSION_CLASS (klass);
- CamelSessionClass *parent_class = CAMEL_SESSION_CLASS (camel_kolab_session_parent_class);
-
- g_type_class_add_private (klass, sizeof (CamelKolabSessionPrivate));
-
- object_class->set_property = G_OBJECT_CLASS (parent_class)->set_property;
- object_class->get_property = G_OBJECT_CLASS (parent_class)->get_property;
- object_class->dispose = camel_kolab_session_dispose;
- object_class->finalize = camel_kolab_session_finalize;
-
- session_class->add_service = parent_class->add_service; /* TODO need to override this */
-
- session_class->authenticate_sync = parent_class->authenticate_sync;
- session_class->authenticate = parent_class->authenticate;
- session_class->authenticate_finish = parent_class->authenticate_finish;
-}
-
/*----------------------------------------------------------------------------*/
-/* password callbacks */
+/* local statics */
/* NSS token pin callback */
static gchar* PR_CALLBACK
@@ -169,185 +139,283 @@ pk11_password (PK11SlotInfo *slot,
}
/*----------------------------------------------------------------------------*/
-
-gboolean
-camel_kolab_session_bringup (CamelKolabSession *self,
- GCancellable *cancellable,
- GError **err)
+/* class functions */
+
+static gchar*
+kolab_session_get_password (CamelSession *self,
+ CamelService *service,
+ const gchar *prompt,
+ const gchar *item,
+ guint32 flags,
+ GError **err)
{
- /* TODO rework to use GInitable */
+ /* TODO rework to CamelSettings */
+ CamelKolabSession *myself = NULL;
CamelKolabSessionPrivate *priv = NULL;
g_assert (CAMEL_IS_KOLAB_SESSION (self));
- (void)cancellable; /* FIXME */ /* cancellable may be NULL */
- g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
-
- priv = CAMEL_KOLAB_SESSION_PRIVATE (self);
+ g_assert (CAMEL_IS_KOLAB_IMAPX_STORE (service));
+ g_return_val_if_fail (err == NULL || *err == NULL, NULL);
- if (priv->is_initialized)
- return TRUE;
+ (void)prompt;
+ (void)item;
+ (void)flags;
- /* TODO need to supply (parts of) storage paths here so the imap
- * objects for the backends will store their files in their
- * own respective directories
- */
+ myself = CAMEL_KOLAB_SESSION (self);
+ priv = CAMEL_KOLAB_SESSION_PRIVATE (myself);
- /* TODO check whether this is The Right Way to
- * initialize the session parent
- */
- if (priv->data_dir == NULL) {
- g_set_error (err,
- KOLAB_CAMEL_KOLAB_ERROR,
- KOLAB_CAMEL_KOLAB_ERROR_GENERIC,
- _("Camel data directory not configured"));
- return FALSE;
- }
-
- /* TODO junk settings */
-
- /* setup further NSS bits here */
- PK11_SetPasswordFunc (pk11_password);
-
- priv->is_initialized = TRUE;
- g_debug ("%s: camel session initialized",
- __func__);
-
- return TRUE;
+ return g_strdup (priv->passwd);
}
-gboolean
-camel_kolab_session_shutdown (CamelKolabSession *self,
- GCancellable *cancellable,
- GError **err)
+static void
+kolab_session_forget_password (CamelSession *self,
+ CamelService *service,
+ const gchar *item,
+ GError **err)
{
+ /* TODO rework to CamelSettings */
+
+ CamelKolabSession *myself = NULL;
CamelKolabSessionPrivate *priv = NULL;
g_assert (CAMEL_IS_KOLAB_SESSION (self));
- (void)cancellable; /* FIXME */ /* cancellable may be NULL */
- g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
+ g_assert (CAMEL_IS_KOLAB_IMAPX_STORE (service));
+ g_return_if_fail (err == NULL || *err == NULL);
- priv = CAMEL_KOLAB_SESSION_PRIVATE (self);
-
- if (! priv->is_initialized)
- return TRUE;
+ (void)item;
- g_debug ("%s: camel session shut down",
- __func__);
+ myself = CAMEL_KOLAB_SESSION (self);
+ priv = CAMEL_KOLAB_SESSION_PRIVATE (myself);
- return TRUE;
+ if (priv->passwd != NULL) {
+ g_free (priv->passwd);
+ priv->passwd = NULL;
+ }
}
-/*----------------------------------------------------------------------------*/
-
-void
-camel_kolab_session_set_data_dir (CamelKolabSession *self,
- gchar *datadir)
+static gboolean
+kolab_session_authenticate_sync (CamelSession *session,
+ CamelService *service,
+ const gchar *mechanism,
+ GCancellable *cancellable,
+ GError **error)
{
- /* TODO rework to use CamelSettings */
+ CamelServiceAuthType *authtype = NULL;
+ CamelAuthenticationResult result;
+ CamelProvider *provider;
+ CamelSettings *settings;
+ const gchar *password;
+ guint32 password_flags;
+ GError *local_error = NULL;
+
+ /* this is a dupe of mail_session_authenticate_sync()
+ * from e-mail-session.c in evolution's libemail-engine.
+ *
+ * Once libemail-engine becomes part of E-D-S, we
+ * might be able to just drop this dupe and use
+ * the original function from there directly
+ */
- CamelKolabSessionPrivate *priv = NULL;
+ /* Do not chain up. Camel's default method is only an example for
+ * subclasses to follow. Instead we mimic most of its logic here. */
+
+ provider = camel_service_get_provider (service);
+ settings = camel_service_get_settings (service);
+
+ /* APOP is one case where a non-SASL mechanism name is passed, so
+ * don't bail if the CamelServiceAuthType struct comes back NULL. */
+ if (mechanism != NULL)
+ authtype = camel_sasl_authtype (mechanism);
+
+ /* If the SASL mechanism does not involve a user
+ * password, then it gets one shot to authenticate. */
+ if (authtype != NULL && !authtype->need_password) {
+ result = camel_service_authenticate_sync (
+ service, mechanism, cancellable, error);
+ if (result == CAMEL_AUTHENTICATION_REJECTED)
+ g_set_error (
+ error, CAMEL_SERVICE_ERROR,
+ CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
+ _("%s authentication failed"), mechanism);
+ return (result == CAMEL_AUTHENTICATION_ACCEPTED);
+ }
- g_assert (CAMEL_IS_KOLAB_SESSION (self));
- g_assert (datadir != NULL);
+ /* Some SASL mechanisms can attempt to authenticate without a
+ * user password being provided (e.g. single-sign-on credentials),
+ * but can fall back to a user password. Handle that case next. */
+ if (mechanism != NULL) {
+ CamelProvider *provider;
+ CamelSasl *sasl;
+ const gchar *service_name;
+ gboolean success = FALSE;
+
+ provider = camel_service_get_provider (service);
+ service_name = provider->protocol;
+
+ /* XXX Would be nice if camel_sasl_try_empty_password_sync()
+ * returned CamelAuthenticationResult so it's easier to
+ * detect errors. */
+ sasl = camel_sasl_new (service_name, mechanism, service);
+ if (sasl != NULL) {
+ success = camel_sasl_try_empty_password_sync (
+ sasl, cancellable, &local_error);
+ g_object_unref (sasl);
+ }
+
+ if (success)
+ return TRUE;
+ }
- priv = CAMEL_KOLAB_SESSION_PRIVATE (self);
+ /* Abort authentication if we got cancelled.
+ * Otherwise clear any errors and press on. */
+ if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return FALSE;
- if (priv->data_dir != NULL)
- g_free (priv->data_dir);
+ g_clear_error (&local_error);
- priv->data_dir = datadir;
-}
+ password_flags = CAMEL_SESSION_PASSWORD_SECRET;
-const gchar*
-camel_kolab_session_get_data_dir (CamelKolabSession *self)
-{
- /* TODO rework to use CamelSettings */
+retry:
+ password = camel_service_get_password (service);
- CamelKolabSessionPrivate *priv = NULL;
+ if (password == NULL) {
+ CamelNetworkSettings *network_settings;
+ const gchar *host;
+ const gchar *user;
+ gchar *prompt;
+ gchar *new_passwd;
- g_assert (CAMEL_IS_KOLAB_SESSION (self));
- priv = CAMEL_KOLAB_SESSION_PRIVATE (self);
+ network_settings = CAMEL_NETWORK_SETTINGS (settings);
+ host = camel_network_settings_get_host (network_settings);
+ user = camel_network_settings_get_user (network_settings);
- return priv->data_dir;
-}
+ prompt = camel_session_build_password_prompt (
+ provider->name, user, host);
-void
-camel_kolab_session_set_config_dir (CamelKolabSession *self,
- const gchar *configdir)
-{
- /* TODO rework to use CamelSettings */
+ new_passwd = camel_session_get_password (
+ session, service, prompt, "password",
+ password_flags, &local_error);
+ camel_service_set_password (service, new_passwd);
+ password = camel_service_get_password (service);
+ g_free (new_passwd);
- CamelKolabSessionPrivate *priv = NULL;
+ g_free (prompt);
- g_assert (CAMEL_IS_KOLAB_SESSION (self));
- g_assert (configdir != NULL);
+ if (local_error != NULL) {
+ g_propagate_error (error, local_error);
+ return FALSE;
+ }
- priv = CAMEL_KOLAB_SESSION_PRIVATE (self);
+ if (password == NULL) {
+ g_set_error (
+ error, CAMEL_SERVICE_ERROR,
+ CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
+ _("No password was provided"));
+ return FALSE;
+ }
+ }
- if (priv->config_dir != NULL)
- g_free (priv->config_dir);
+ result = camel_service_authenticate_sync (
+ service, mechanism, cancellable, error);
- priv->config_dir = g_strdup (configdir);
+ if (result == CAMEL_AUTHENTICATION_REJECTED) {
+ password_flags |= CAMEL_SESSION_PASSWORD_REPROMPT;
+ camel_service_set_password (service, NULL);
+ goto retry;
+ }
+
+ return (result == CAMEL_AUTHENTICATION_ACCEPTED);
}
-const gchar*
-camel_kolab_session_get_config_dir (CamelKolabSession *self)
+/*----------------------------------------------------------------------------*/
+/* class init */
+
+static void
+camel_kolab_session_class_init (CamelKolabSessionClass *klass)
{
- /* TODO rework to use CamelSettings */
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ CamelSessionClass *session_class = CAMEL_SESSION_CLASS (klass);
+ CamelSessionClass *parent_class = CAMEL_SESSION_CLASS (camel_kolab_session_parent_class);
- CamelKolabSessionPrivate *priv = NULL;
+ g_type_class_add_private (klass, sizeof (CamelKolabSessionPrivate));
- g_assert (CAMEL_IS_KOLAB_SESSION (self));
- priv = CAMEL_KOLAB_SESSION_PRIVATE (self);
+ object_class->set_property = G_OBJECT_CLASS (parent_class)->set_property;
+ object_class->get_property = G_OBJECT_CLASS (parent_class)->get_property;
+ object_class->dispose = camel_kolab_session_dispose;
+ object_class->finalize = camel_kolab_session_finalize;
- return priv->config_dir;
+ session_class->add_service = parent_class->add_service;
+ session_class->get_password = kolab_session_get_password;
+ session_class->forget_password = kolab_session_forget_password;
+#if 0
+ session_class->alert_user = kolab_session_alert_user;
+ session_class->get_filter_driver = kolab_session_get_filter_driver;
+ session_class->lookup_addressbook = kolab_session_lookup_addressbook;
+ session_class->forward_to = kolab_session_forward_to;
+ session_class->get_socks_proxy = kolab_session_get_socks_proxy;
+#endif
+ session_class->authenticate_sync = kolab_session_authenticate_sync;
}
-const gchar*
-camel_kolab_session_get_password (CamelKolabSession *self)
+/*----------------------------------------------------------------------------*/
+/* public API */
+
+gboolean
+camel_kolab_session_bringup (CamelKolabSession *self,
+ GCancellable *cancellable,
+ GError **err)
{
- /* TODO rework to CamelSettings */
+ /* TODO rework to use GInitable */
CamelKolabSessionPrivate *priv = NULL;
g_assert (CAMEL_IS_KOLAB_SESSION (self));
+ (void)cancellable; /* FIXME */ /* cancellable may be NULL */
+ g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
+
priv = CAMEL_KOLAB_SESSION_PRIVATE (self);
- return priv->passwd;
-}
+ if (priv->is_initialized)
+ return TRUE;
-void
-camel_kolab_session_forget_password (CamelKolabSession *self)
-{
- /* TODO rework to CamelSettings */
+ /* TODO need to supply (parts of) storage paths here so the imap
+ * objects for the backends will store their files in their
+ * own respective directories
+ */
- CamelKolabSessionPrivate *priv = NULL;
+ /* TODO junk settings */
- g_assert (CAMEL_IS_KOLAB_SESSION (self));
- priv = CAMEL_KOLAB_SESSION_PRIVATE (self);
+ /* setup further NSS bits here */
+ PK11_SetPasswordFunc (pk11_password);
- if (priv->passwd != NULL) {
- g_free (priv->passwd);
- priv->passwd = NULL;
- }
+ priv->is_initialized = TRUE;
+ g_debug ("%s: camel session initialized",
+ __func__);
+
+ return TRUE;
}
-void
-camel_kolab_session_set_password (CamelKolabSession *self,
- const gchar *passwd)
+gboolean
+camel_kolab_session_shutdown (CamelKolabSession *self,
+ GCancellable *cancellable,
+ GError **err)
{
- /* TODO rework to CamelSettings */
-
CamelKolabSessionPrivate *priv = NULL;
g_assert (CAMEL_IS_KOLAB_SESSION (self));
+ (void)cancellable; /* FIXME */ /* cancellable may be NULL */
+ g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
+
priv = CAMEL_KOLAB_SESSION_PRIVATE (self);
- if (priv->passwd != NULL)
- g_free (priv->passwd);
+ if (! priv->is_initialized)
+ return TRUE;
- priv->passwd = g_strdup (passwd);
+ g_debug ("%s: camel session shut down",
+ __func__);
+
+ return TRUE;
}
void
@@ -371,4 +439,21 @@ camel_kolab_session_set_token_pin (CamelKolabSession *self,
nss_tok_pin = g_strdup (pin);
}
+void
+camel_kolab_session_set_password (CamelKolabSession *self,
+ const gchar *passwd)
+{
+ /* TODO rework to CamelSettings */
+
+ CamelKolabSessionPrivate *priv = NULL;
+
+ g_assert (CAMEL_IS_KOLAB_SESSION (self));
+ priv = CAMEL_KOLAB_SESSION_PRIVATE (self);
+
+ if (priv->passwd != NULL)
+ g_free (priv->passwd);
+
+ priv->passwd = g_strdup (passwd);
+}
+
/*----------------------------------------------------------------------------*/
diff --git a/src/camel/camel-kolab-session.h b/src/camel/camel-kolab-session.h
index 03c1323..78be880 100644
--- a/src/camel/camel-kolab-session.h
+++ b/src/camel/camel-kolab-session.h
@@ -47,6 +47,11 @@
#include <libekolabutil/camel-system-headers.h>
/*----------------------------------------------------------------------------*/
+
+#define CAMEL_KOLAB_SESSION_PROP_DATA_DIR "user-data-dir"
+#define CAMEL_KOLAB_SESSION_PROP_CACHE_DIR "user-cache-dir"
+
+/*----------------------------------------------------------------------------*/
/* Standard GObject macros */
#define CAMEL_TYPE_KOLAB_SESSION \
@@ -95,34 +100,12 @@ camel_kolab_session_shutdown (CamelKolabSession *self,
GError **err);
void
-camel_kolab_session_set_password (CamelKolabSession *self,
- const gchar *passwd);
-
-void
camel_kolab_session_set_token_pin (CamelKolabSession *self,
const gchar *pin);
void
-camel_kolab_session_set_data_dir (CamelKolabSession *self,
- gchar *datadir);
-
-const gchar*
-camel_kolab_session_get_data_dir (CamelKolabSession *self);
-
-void
-camel_kolab_session_set_config_dir (CamelKolabSession *self,
- const gchar *configdir);
-
-const gchar*
-camel_kolab_session_get_config_dir (CamelKolabSession *self);
-
-const gchar*
-camel_kolab_session_get_password (CamelKolabSession *self);
-
-void
-camel_kolab_session_forget_password (CamelKolabSession *self);
-
-
+camel_kolab_session_set_password (CamelKolabSession *self,
+ const gchar *passwd);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]