aboutsummaryrefslogtreecommitdiffstats
path: root/camel/providers/imap/camel-imap-store.c
diff options
context:
space:
mode:
Diffstat (limited to 'camel/providers/imap/camel-imap-store.c')
-rw-r--r--camel/providers/imap/camel-imap-store.c231
1 files changed, 149 insertions, 82 deletions
diff --git a/camel/providers/imap/camel-imap-store.c b/camel/providers/imap/camel-imap-store.c
index bea7a03b18..749785b724 100644
--- a/camel/providers/imap/camel-imap-store.c
+++ b/camel/providers/imap/camel-imap-store.c
@@ -34,6 +34,7 @@
#include <gal/util/e-util.h>
#include "camel-imap-store.h"
+#include "camel-imap-auth.h"
#include "camel-imap-folder.h"
#include "camel-imap-utils.h"
#include "camel-imap-command.h"
@@ -157,6 +158,76 @@ camel_imap_store_get_type (void)
return camel_imap_store_type;
}
+static struct {
+ const char *name;
+ guint32 flag;
+} capabilities[] = {
+ { "IMAP4", IMAP_CAPABILITY_IMAP4 },
+ { "IMAP4REV1", IMAP_CAPABILITY_IMAP4REV1 },
+ { "STATUS", IMAP_CAPABILITY_STATUS },
+ { "NAMESPACE", IMAP_CAPABILITY_NAMESPACE },
+ { "AUTH=KERBEROS_V4", IMAP_CAPABILITY_AUTH_KERBEROS_V4 },
+ { "AUTH=GSSAPI", IMAP_CAPABILITY_AUTH_GSSAPI },
+ { "UIDPLUS", IMAP_CAPABILITY_UIDPLUS },
+ { "LITERAL+", IMAP_CAPABILITY_LITERALPLUS },
+ { NULL, 0 }
+};
+
+static gboolean
+connect_to_server (CamelService *service, CamelException *ex)
+{
+ CamelImapStore *store = CAMEL_IMAP_STORE (service);
+ CamelImapResponse *response;
+ char *result, *buf, *capa, *lasts;
+ int i;
+
+ if (!CAMEL_SERVICE_CLASS (remote_store_class)->connect (service, ex))
+ return FALSE;
+
+ store->command = 0;
+
+ /* Read the greeting, if any. FIXME: deal with PREAUTH */
+ if (camel_remote_store_recv_line (CAMEL_REMOTE_STORE (service),
+ &buf, ex) < 0) {
+ return FALSE;
+ }
+ g_free (buf);
+ store->connected = TRUE;
+
+ /* Find out the IMAP capabilities */
+ store->capabilities = 0;
+ response = camel_imap_command (store, NULL, ex, "CAPABILITY");
+ if (!response)
+ return FALSE;
+ result = camel_imap_response_extract (response, "CAPABILITY", ex);
+ if (!result)
+ return FALSE;
+
+ /* Skip over "* CAPABILITY". */
+ capa = imap_next_word (result + 2);
+
+ for (capa = strtok_r (capa, " ", &lasts); capa;
+ capa = strtok_r (NULL, " ", &lasts)) {
+ for (i = 0; capabilities[i].name; i++) {
+ if (g_strcasecmp (capa, capabilities[i].name) == 0) {
+ store->capabilities |= capabilities[i].flag;
+ break;
+ }
+ }
+ }
+ g_free (result);
+
+ if (store->capabilities & IMAP_CAPABILITY_IMAP4REV1) {
+ store->server_level = IMAP_LEVEL_IMAP4REV1;
+ store->capabilities |= IMAP_CAPABILITY_STATUS;
+ } else if (store->capabilities & IMAP_CAPABILITY_IMAP4)
+ store->server_level = IMAP_LEVEL_IMAP4;
+ else
+ store->server_level = IMAP_LEVEL_UNKNOWN;
+
+ return TRUE;
+}
+
static CamelServiceAuthType password_authtype = {
N_("Password"),
@@ -167,44 +238,45 @@ static CamelServiceAuthType password_authtype = {
TRUE
};
+#ifdef HAVE_KRB4
+static CamelServiceAuthType kerberos_v4_authtype = {
+ N_("Kerberos 4"),
+
+ N_("This option will connect to the IMAP server using "
+ "Kerberos 4 authentication."),
+
+ "KERBEROS_V4",
+ FALSE
+};
+#endif
+
static GList *
query_auth_types_connected (CamelService *service, CamelException *ex)
{
-#if 0
- GList *ret = NULL;
- gboolean passwd = TRUE;
-
- if (service->url) {
- passwd = try_connect (service, ex);
- if (camel_exception_get_id (ex) != CAMEL_EXCEPTION_NONE)
- return NULL;
- }
-
- if (passwd)
- ret = g_list_append (ret, &password_authtype);
-
- if (!ret) {
- camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
- _("Could not connect to IMAP server on %s."),
- service->url->host ? service->url->host :
- _("(unknown host)"));
- }
-
- return ret;
-#else
- g_warning ("imap::query_auth_types_connected: not implemented. Defaulting.");
- /* FIXME: use the classfunc instead of the local? */
- return query_auth_types_generic (service, ex);
+ GList *types;
+
+ if (!connect_to_server (service, ex))
+ return NULL;
+
+ types = CAMEL_SERVICE_CLASS (remote_store_class)->query_auth_types_connected (service, ex);
+#ifdef HAVE_KRB4
+ if (CAMEL_IMAP_STORE (service)->capabilities &
+ IMAP_CAPABILITY_AUTH_KERBEROS_V4)
+ types = g_list_prepend (types, &kerberos_v4_authtype);
#endif
+ return g_list_prepend (types, &password_authtype);
}
static GList *
query_auth_types_generic (CamelService *service, CamelException *ex)
{
- GList *prev;
+ GList *types;
- prev = CAMEL_SERVICE_CLASS (remote_store_class)->query_auth_types_generic (service, ex);
- return g_list_prepend (prev, &password_authtype);
+ types = CAMEL_SERVICE_CLASS (remote_store_class)->query_auth_types_generic (service, ex);
+#ifdef HAVE_KRB4
+ types = g_list_prepend (types, &kerberos_v4_authtype);
+#endif
+ return g_list_prepend (types, &password_authtype);
}
static gboolean
@@ -212,65 +284,78 @@ imap_connect (CamelService *service, CamelException *ex)
{
CamelImapStore *store = CAMEL_IMAP_STORE (service);
CamelSession *session = camel_service_get_session (CAMEL_SERVICE (store));
- gchar *result, *buf, *errbuf = NULL, *namespace;
+ gchar *result, *errbuf = NULL, *namespace;
CamelImapResponse *response;
gboolean authenticated = FALSE;
int len;
- if (CAMEL_SERVICE_CLASS (remote_store_class)->connect (service, ex) == FALSE)
+ if (connect_to_server (service, ex) == 0)
return FALSE;
- store->command = 0;
- if (!store->storage_path) {
- store->storage_path =
- camel_session_get_storage_path (session, service, ex);
- if (camel_exception_is_set (ex))
+ /* authenticate the user */
+#ifdef HAVE_KRB4
+ if (service->url->authmech &&
+ !g_strcasecmp (service->url->authmech, "KERBEROS_V4")) {
+ if (!(store->capabilities & IMAP_CAPABILITY_AUTH_KERBEROS_V4)) {
+ camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE,
+ "IMAP server %s does not "
+ "support requested "
+ "authentication type %s",
+ service->url->host,
+ service->url->authmech);
+ camel_service_disconnect (service, NULL);
return FALSE;
+ }
+
+ authenticated = imap_try_kerberos_v4_auth (store, ex);
+ if (camel_exception_is_set (ex)) {
+ camel_service_disconnect (service, NULL);
+ return FALSE;
+ }
}
-
- /* Read the greeting, if any. */
- if (camel_remote_store_recv_line (CAMEL_REMOTE_STORE (service), &buf, ex) < 0) {
- return FALSE;
- }
- g_free (buf);
-
- /* authenticate the user */
+#endif
+
while (!authenticated) {
if (errbuf) {
/* We need to un-cache the password before prompting again */
- camel_session_query_authenticator (session,
- CAMEL_AUTHENTICATOR_TELL, NULL,
- TRUE, service, "password", ex);
+ camel_session_query_authenticator (
+ session, CAMEL_AUTHENTICATOR_TELL, NULL,
+ TRUE, service, "password", ex);
g_free (service->url->passwd);
service->url->passwd = NULL;
}
-
+
if (!service->url->authmech && !service->url->passwd) {
- gchar *prompt;
-
- prompt = g_strdup_printf (_("%sPlease enter the IMAP password for %s@%s"),
- errbuf ? errbuf : "", service->url->user, service->url->host);
+ char *prompt;
+
+ prompt = g_strdup_printf (_("%sPlease enter the IMAP "
+ "password for %s@%s"),
+ errbuf ? errbuf : "",
+ service->url->user,
+ service->url->host);
service->url->passwd =
- camel_session_query_authenticator (session,
- CAMEL_AUTHENTICATOR_ASK, prompt,
- TRUE, service, "password", ex);
+ camel_session_query_authenticator (
+ session, CAMEL_AUTHENTICATOR_ASK,
+ prompt, TRUE, service, "password", ex);
g_free (prompt);
g_free (errbuf);
errbuf = NULL;
-
+
if (!service->url->passwd) {
camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL,
"You didn\'t enter a password.");
+ camel_service_disconnect (service, NULL);
return FALSE;
}
}
-
+
response = camel_imap_command (store, NULL, ex,
"LOGIN \"%s\" \"%s\"",
service->url->user,
service->url->passwd);
if (!response) {
- errbuf = g_strdup_printf (_("Unable to authenticate to IMAP server.\n%s\n\n"),
+ errbuf = g_strdup_printf (_("Unable to authenticate "
+ "to IMAP server.\n%s\n\n"),
camel_exception_get_description (ex));
camel_exception_clear (ex);
} else {
@@ -278,32 +363,14 @@ imap_connect (CamelService *service, CamelException *ex)
camel_imap_response_free (response);
}
}
-
- /* At this point we know we're connected... */
- store->connected = TRUE;
-
- /* Now lets find out the IMAP capabilities */
- response = camel_imap_command (store, NULL, ex, "CAPABILITY");
- if (!response)
- return FALSE;
- result = camel_imap_response_extract (response, "CAPABILITY", ex);
- if (!result)
- return FALSE;
- /* parse for capabilities here. */
- if (e_strstrcase (result, "IMAP4REV1"))
- store->server_level = IMAP_LEVEL_IMAP4REV1;
- else if (e_strstrcase (result, "IMAP4"))
- store->server_level = IMAP_LEVEL_IMAP4;
- else
- store->server_level = IMAP_LEVEL_UNKNOWN;
-
- if ((store->server_level >= IMAP_LEVEL_IMAP4REV1) ||
- (e_strstrcase (result, "STATUS")))
- store->has_status_capability = TRUE;
- else
- store->has_status_capability = FALSE;
- g_free (result);
+ /* Find our storage path. */
+ if (!store->storage_path) {
+ store->storage_path =
+ camel_session_get_storage_path (session, service, ex);
+ if (camel_exception_is_set (ex))
+ return FALSE;
+ }
/* Find the hierarchy separator for our namespace. */
namespace = service->url->path;