[evolution-data-server] pop3: Adapt to Camel's new authentication API.
- From: Matthew Barnes <mbarnes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] pop3: Adapt to Camel's new authentication API.
- Date: Sat, 15 Oct 2011 14:59:54 +0000 (UTC)
commit ed034cb952d7086990e5ae171a7846a3d8a7f485
Author: Matthew Barnes <mbarnes redhat com>
Date: Sat Oct 15 09:51:22 2011 -0400
pop3: Adapt to Camel's new authentication API.
camel/providers/pop3/camel-pop3-store.c | 387 ++++++++++++++-----------------
1 files changed, 173 insertions(+), 214 deletions(-)
---
diff --git a/camel/providers/pop3/camel-pop3-store.c b/camel/providers/pop3/camel-pop3-store.c
index 39d7294..bf07f27 100644
--- a/camel/providers/pop3/camel-pop3-store.c
+++ b/camel/providers/pop3/camel-pop3-store.c
@@ -207,13 +207,14 @@ connect_to_server (CamelService *service,
return FALSE;
}
-static gint
+static CamelAuthenticationResult
try_sasl (CamelPOP3Store *store,
- const gchar *mech,
+ const gchar *mechanism,
GCancellable *cancellable,
GError **error)
{
CamelPOP3Stream *stream = store->engine->stream;
+ CamelAuthenticationResult result;
CamelService *service;
CamelURL *url;
guchar *line, *resp;
@@ -225,18 +226,16 @@ try_sasl (CamelPOP3Store *store,
service = CAMEL_SERVICE (store);
url = camel_service_get_camel_url (service);
- sasl = camel_sasl_new ("pop", mech, service);
+ sasl = camel_sasl_new ("pop", mechanism, service);
if (sasl == NULL) {
g_set_error (
error, CAMEL_SERVICE_ERROR,
CAMEL_SERVICE_ERROR_URL_INVALID,
- _("Unable to connect to POP server %s: "
- "No support for requested authentication mechanism."),
- url->host);
- return -1;
+ _("No support for %s authentication"), mechanism);
+ return CAMEL_AUTHENTICATION_ERROR;
}
- string = g_strdup_printf ("AUTH %s\r\n", mech);
+ string = g_strdup_printf ("AUTH %s\r\n", mechanism);
ret = camel_stream_write_string (
CAMEL_STREAM (stream), string, cancellable, error);
g_free (string);
@@ -247,25 +246,20 @@ try_sasl (CamelPOP3Store *store,
while (1) {
if (camel_pop3_stream_line (stream, &line, &len, cancellable, error) == -1)
goto ioerror;
- if (strncmp((gchar *) line, "+OK", 3) == 0)
- break;
- if (strncmp((gchar *) line, "-ERR", 4) == 0) {
- gchar *tmp;
- tmp = get_valid_utf8_error (
- (gchar *) store->engine->line);
- g_set_error (
- error, CAMEL_SERVICE_ERROR,
- CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
- /* Translators: Last %s is an optional explanation beginning with ": " separator */
- _("SASL '%s' Login failed for POP server %s%s"),
- mech, url->host, (tmp != NULL) ? tmp : "");
- g_free (tmp);
+ if (strncmp ((gchar *) line, "+OK", 3) == 0) {
+ result = CAMEL_AUTHENTICATION_ACCEPTED;
+ break;
+ }
- goto done;
+ if (strncmp ((gchar *) line, "-ERR", 4) == 0) {
+ result = CAMEL_AUTHENTICATION_REJECTED;
+ break;
}
- /* If we dont get continuation, or the sasl object's run out of work, or we dont get a challenge,
- * its a protocol error, so fail, and try reset the server */
+
+ /* If we dont get continuation, or the sasl object's run out
+ * of work, or we dont get a challenge, its a protocol error,
+ * so fail, and try reset the server. */
if (strncmp((gchar *) line, "+ ", 2) != 0
|| camel_sasl_get_authenticated (sasl)
|| (resp = (guchar *) camel_sasl_challenge_base64_sync (sasl, (const gchar *) line + 2, cancellable, NULL)) == NULL) {
@@ -278,6 +272,7 @@ try_sasl (CamelPOP3Store *store,
_("Cannot login to POP server %s: "
"SASL Protocol error"),
url->host);
+ result = CAMEL_AUTHENTICATION_ERROR;
goto done;
}
@@ -292,175 +287,19 @@ try_sasl (CamelPOP3Store *store,
goto ioerror;
}
- g_object_unref (sasl);
- return 0;
- ioerror:
+ goto done;
+
+ioerror:
g_prefix_error (
error, _("Failed to authenticate on POP server %s: "),
url->host);
+ result = CAMEL_AUTHENTICATION_ERROR;
- done:
+done:
g_object_unref (sasl);
- return -1;
-}
-
-static gint
-pop3_try_authenticate (CamelService *service,
- gboolean reprompt,
- const gchar *errmsg,
- GCancellable *cancellable,
- GError **error)
-{
- CamelPOP3Store *store = (CamelPOP3Store *) service;
- CamelPOP3Command *pcu = NULL, *pcp = NULL;
- CamelURL *url;
- const gchar *password;
- gint status;
-
- url = camel_service_get_camel_url (service);
- password = camel_service_get_password (service);
-
- /* override, testing only */
- /*printf("Forcing authmech to 'login'\n");
- url->authmech = g_strdup("LOGIN");*/
-
- if (password == NULL) {
- gchar *base_prompt;
- gchar *full_prompt;
- gchar *new_passwd;
- guint32 flags = CAMEL_SESSION_PASSWORD_SECRET;
-
- if (reprompt)
- flags |= CAMEL_SESSION_PASSWORD_REPROMPT;
-
- base_prompt = camel_session_build_password_prompt (
- "POP", url->user, url->host);
-
- if (errmsg != NULL)
- full_prompt = g_strconcat (errmsg, base_prompt, NULL);
- else
- full_prompt = g_strdup (base_prompt);
-
- /* XXX This is a tad awkward. Maybe define a
- * camel_service_ask_password() that calls
- * camel_session_get_password() and caches
- * the password itself? */
- new_passwd = camel_session_get_password (
- camel_service_get_session (service), service,
- full_prompt, "password", flags, error);
- camel_service_set_password (service, new_passwd);
- password = camel_service_get_password (service);
- g_free (new_passwd);
-
- g_free (base_prompt);
- g_free (full_prompt);
-
- if (password == NULL)
- return -1;
- }
-
- if (!url->authmech) {
- /* pop engine will take care of pipelining ability */
- pcu = camel_pop3_engine_command_new (
- store->engine, 0, NULL, NULL, cancellable, error,
- "USER %s\r\n", url->user);
- pcp = camel_pop3_engine_command_new (
- store->engine, 0, NULL, NULL, cancellable, error,
- "PASS %s\r\n", password);
- } else if (strcmp (url->authmech, "+APOP") == 0 && store->engine->apop) {
- gchar *secret, *md5asc, *d;
-
- d = store->engine->apop;
-
- while (*d != '\0') {
- if (!isascii ((gint) * d)) {
-
- /* README for Translators: The string APOP should not be translated */
- g_set_error (
- error, CAMEL_SERVICE_ERROR,
- CAMEL_SERVICE_ERROR_URL_INVALID,
- _("Unable to connect to POP server %s: "
- "Invalid APOP ID received. Impersonation "
- "attack suspected. Please contact your admin."),
- url->host);
-
- return 0;
- }
- d++;
- }
-
- secret = g_alloca (strlen (store->engine->apop) + strlen (password) + 1);
- sprintf(secret, "%s%s", store->engine->apop, password);
- md5asc = g_compute_checksum_for_string (G_CHECKSUM_MD5, secret, -1);
- pcp = camel_pop3_engine_command_new (
- store->engine, 0, NULL, NULL, cancellable, error,
- "APOP %s %s\r\n", url->user, md5asc);
- g_free (md5asc);
- } else {
- CamelServiceAuthType *auth;
- GList *l;
-
- l = store->engine->auth;
- while (l) {
- auth = l->data;
- if (strcmp (auth->authproto, url->authmech) == 0)
- return try_sasl (
- store, url->authmech,
- cancellable, error);
- l = l->next;
- }
-
- g_set_error (
- error, CAMEL_SERVICE_ERROR,
- CAMEL_SERVICE_ERROR_URL_INVALID,
- _("Unable to connect to POP server %s: "
- "No support for requested authentication mechanism."),
- url->host);
-
- return 0;
- }
-
- while ((status = camel_pop3_engine_iterate (store->engine, pcp, cancellable, error)) > 0)
- ;
-
- if (status == -1) {
- g_prefix_error (
- error,
- _("Unable to connect to POP server %s.\n"
- "Error sending password: "), url->host);
- } else if (pcu && pcu->state != CAMEL_POP3_COMMAND_OK) {
- gchar *tmp;
-
- tmp = get_valid_utf8_error ((gchar *) store->engine->line);
- g_set_error (
- error, CAMEL_SERVICE_ERROR,
- CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
- /* Translators: Last %s is an optional explanation beginning with ": " separator */
- _("Unable to connect to POP server %s.\n"
- "Error sending username%s"),
- url->host, (tmp != NULL) ? tmp : "");
- g_free (tmp);
- } else if (pcp->state != CAMEL_POP3_COMMAND_OK) {
- gchar *tmp;
-
- tmp = get_valid_utf8_error ((gchar *) store->engine->line);
- g_set_error (
- error, CAMEL_SERVICE_ERROR,
- CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
- /* Translators: Last %s is an optional explanation beginning with ": " separator */
- _("Unable to connect to POP server %s.\n"
- "Error sending password%s"),
- url->host, (tmp != NULL) ? tmp : "");
- g_free (tmp);
- }
-
- camel_pop3_engine_command_free (store->engine, pcp);
-
- if (pcu)
- camel_pop3_engine_command_free (store->engine, pcu);
- return status;
+ return result;
}
static void
@@ -505,13 +344,18 @@ pop3_store_connect_sync (CamelService *service,
GError **error)
{
CamelPOP3Store *store = (CamelPOP3Store *) service;
- gboolean reprompt = FALSE;
+ CamelSession *session;
+ CamelURL *url;
+ const gchar *mechanism;
const gchar *user_data_dir;
- gchar *errbuf = NULL;
- GError *local_error = NULL;
+ gboolean success;
+ session = camel_service_get_session (service);
user_data_dir = camel_service_get_user_data_dir (service);
+ url = camel_service_get_camel_url (service);
+ mechanism = url->authmech;
+
if (store->cache == NULL) {
store->cache = camel_data_cache_new (user_data_dir, error);
if (store->cache) {
@@ -525,32 +369,10 @@ pop3_store_connect_sync (CamelService *service,
if (!connect_to_server (service, cancellable, error))
return FALSE;
- while (1) {
- pop3_try_authenticate (
- service, reprompt, errbuf,
- cancellable, &local_error);
- g_free (errbuf);
- errbuf = NULL;
-
- /* we only re-prompt if we failed to authenticate,
- * any other error and we just abort */
- if (g_error_matches (local_error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE)) {
- gchar *tmp = camel_utf8_make_valid (local_error->message);
- errbuf = g_markup_printf_escaped ("%s\n\n", tmp);
- g_free (tmp);
-
- g_clear_error (&local_error);
-
- camel_service_set_password (service, NULL);
- reprompt = TRUE;
- } else
- break;
- }
-
- g_free (errbuf);
+ success = camel_session_authenticate_sync (
+ session, service, mechanism, cancellable, error);
- if (local_error != NULL) {
- g_propagate_error (error, local_error);
+ if (!success) {
camel_service_disconnect_sync (service, TRUE, NULL);
return FALSE;
}
@@ -593,6 +415,142 @@ pop3_store_disconnect_sync (CamelService *service,
return success;
}
+static CamelAuthenticationResult
+pop3_store_authenticate_sync (CamelService *service,
+ const gchar *mechanism,
+ GCancellable *cancellable,
+ GError **error)
+{
+ CamelPOP3Store *store = CAMEL_POP3_STORE (service);
+ CamelAuthenticationResult result;
+ CamelPOP3Command *pcu = NULL;
+ CamelPOP3Command *pcp = NULL;
+ CamelURL *url;
+ const gchar *password;
+ gint status;
+
+ url = camel_service_get_camel_url (service);
+ password = camel_service_get_password (service);
+
+ if (mechanism == NULL) {
+ if (password == NULL) {
+ g_set_error_literal (
+ error, CAMEL_SERVICE_ERROR,
+ CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
+ _("Authentication password not available"));
+ return CAMEL_AUTHENTICATION_ERROR;
+ }
+
+ /* pop engine will take care of pipelining ability */
+ pcu = camel_pop3_engine_command_new (
+ store->engine, 0, NULL, NULL, cancellable, error,
+ "USER %s\r\n", url->user);
+ pcp = camel_pop3_engine_command_new (
+ store->engine, 0, NULL, NULL, cancellable, error,
+ "PASS %s\r\n", password);
+
+ } else if (strcmp (mechanism, "+APOP") == 0 && store->engine->apop) {
+ gchar *secret, *md5asc, *d;
+
+ if (password == NULL) {
+ g_set_error_literal (
+ error, CAMEL_SERVICE_ERROR,
+ CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
+ _("Authentication password not available"));
+ return CAMEL_AUTHENTICATION_ERROR;
+ }
+
+ d = store->engine->apop;
+
+ while (*d != '\0') {
+ if (!isascii ((gint) * d)) {
+
+ /* Translators: Do not translate APOP. */
+ g_set_error (
+ error, CAMEL_SERVICE_ERROR,
+ CAMEL_SERVICE_ERROR_URL_INVALID,
+ _("Unable to connect to POP server %s: "
+ "Invalid APOP ID received. Impersonation "
+ "attack suspected. Please contact your admin."),
+ url->host);
+
+ return CAMEL_AUTHENTICATION_ERROR;
+ }
+ d++;
+ }
+
+ secret = g_alloca (
+ strlen (store->engine->apop) +
+ strlen (password) + 1);
+ sprintf (secret, "%s%s", store->engine->apop, password);
+ md5asc = g_compute_checksum_for_string (
+ G_CHECKSUM_MD5, secret, -1);
+ pcp = camel_pop3_engine_command_new (
+ store->engine, 0, NULL, NULL, cancellable, error,
+ "APOP %s %s\r\n", url->user, md5asc);
+ g_free (md5asc);
+
+ } else {
+ GList *link;
+
+ link = store->engine->auth;
+ while (link != NULL) {
+ CamelServiceAuthType *auth = link->data;
+
+ if (g_strcmp0 (auth->authproto, mechanism) == 0)
+ return try_sasl (
+ store, mechanism,
+ cancellable, error);
+ link = g_list_next (link);
+ }
+
+ g_set_error (
+ error, CAMEL_SERVICE_ERROR,
+ CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
+ _("No support for %s authentication"), mechanism);
+ return CAMEL_AUTHENTICATION_ERROR;
+ }
+
+ while ((status = camel_pop3_engine_iterate (store->engine, pcp, cancellable, error)) > 0)
+ ;
+
+ if (status == -1) {
+ g_prefix_error (
+ error,
+ _("Unable to connect to POP server %s.\n"
+ "Error sending password: "), url->host);
+ result = CAMEL_AUTHENTICATION_ERROR;
+
+ } else if (pcu && pcu->state != CAMEL_POP3_COMMAND_OK) {
+ gchar *tmp;
+
+ /* Abort authentication if the server rejects the user
+ * name. Reprompting for a password won't do any good. */
+ tmp = get_valid_utf8_error ((gchar *) store->engine->line);
+ g_set_error (
+ error, CAMEL_SERVICE_ERROR,
+ CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
+ /* Translators: Last %s is an optional explanation
+ * beginning with ": " separator. */
+ _("Unable to connect to POP server %s.\n"
+ "Error sending username%s"),
+ url->host, (tmp != NULL) ? tmp : "");
+ g_free (tmp);
+ result = CAMEL_AUTHENTICATION_ERROR;
+
+ } else if (pcp->state != CAMEL_POP3_COMMAND_OK)
+ result = CAMEL_AUTHENTICATION_REJECTED;
+ else
+ result = CAMEL_AUTHENTICATION_ACCEPTED;
+
+ camel_pop3_engine_command_free (store->engine, pcp);
+
+ if (pcu != NULL)
+ camel_pop3_engine_command_free (store->engine, pcu);
+
+ return result;
+}
+
static GList *
pop3_store_query_auth_types_sync (CamelService *service,
GCancellable *cancellable,
@@ -734,6 +692,7 @@ camel_pop3_store_class_init (CamelPOP3StoreClass *class)
service_class->get_name = pop3_store_get_name;
service_class->connect_sync = pop3_store_connect_sync;
service_class->disconnect_sync = pop3_store_disconnect_sync;
+ service_class->authenticate_sync = pop3_store_authenticate_sync;
service_class->query_auth_types_sync = pop3_store_query_auth_types_sync;
store_class = CAMEL_STORE_CLASS (class);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]