aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--camel/ChangeLog17
-rw-r--r--camel/providers/imap/Makefile.am5
-rw-r--r--camel/providers/imap/camel-imap-auth.c187
-rw-r--r--camel/providers/imap/camel-imap-auth.h39
-rw-r--r--camel/providers/imap/camel-imap-store.c182
-rw-r--r--camel/providers/imap/camel-imap-store.h7
6 files changed, 151 insertions, 286 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog
index 4d17c7e248..f212e25d46 100644
--- a/camel/ChangeLog
+++ b/camel/ChangeLog
@@ -35,6 +35,23 @@
remove IMAP-isms that shouldn't be in the generic code. This still
isn't tested, because we're stuck behind a NAT right now...
+ * providers/imap/camel-imap-store.c: Add an "authtypes" hash table
+ to CamelImapStore recording the supported authtypes.
+ (connect_to_server): Record supported authtypes in the authtypes
+ hash rather than the capabilities bitmask, since now the IMAP code
+ is no longer responsible for keeping track of which authtypes we
+ support.
+ (query_auth_types): Use camel_sasl_authtype_list to get the
+ SASL-supported authtypes.
+ (try_auth): New function to try a SASL auth mechanism. Sort of
+ formerly imap_try_kerberos_v4_auth.
+ (imap_connect): Get rid of the krb4-specific bits and genericize
+ them for any SASL authtype.
+
+ * providers/imap/Makefile.am: Remove camel-imap-auth.[ch] (moved
+ into camel-imap-store.c since it's now constant size) and the
+ KRB4_CFLAGS and KRB4_LDFLAGS references.
+
2001-03-01 Jeffrey Stedfast <fejj@ximian.com>
* camel-sasl-anonymous.c (anon_challenge): Don't base64 encode the
diff --git a/camel/providers/imap/Makefile.am b/camel/providers/imap/Makefile.am
index 341fa6b421..39e160c879 100644
--- a/camel/providers/imap/Makefile.am
+++ b/camel/providers/imap/Makefile.am
@@ -17,11 +17,9 @@ INCLUDES = -I.. \
-I$(top_srcdir) \
-I$(includedir) \
$(GTK_INCLUDEDIR) \
- $(KRB4_CFLAGS) \
-DG_LOG_DOMAIN=\"camel-imap-provider\"
libcamelimap_la_SOURCES = \
- camel-imap-auth.c \
camel-imap-command.c \
camel-imap-folder.c \
camel-imap-provider.c \
@@ -32,7 +30,6 @@ libcamelimap_la_SOURCES = \
camel-imap-wrapper.c
libcamelimapinclude_HEADERS = \
- camel-imap-auth.h \
camel-imap-command.h \
camel-imap-folder.h \
camel-imap-search.h \
@@ -42,7 +39,7 @@ libcamelimapinclude_HEADERS = \
camel-imap-utils.h \
camel-imap-wrapper.h
-libcamelimap_la_LDFLAGS = $(KRB4_LDFLAGS) -version-info 0:0:0
+libcamelimap_la_LDFLAGS = -version-info 0:0:0
noinst_HEADERS = \
camel-imap-private.h
diff --git a/camel/providers/imap/camel-imap-auth.c b/camel/providers/imap/camel-imap-auth.c
deleted file mode 100644
index a1daf88888..0000000000
--- a/camel/providers/imap/camel-imap-auth.c
+++ /dev/null
@@ -1,187 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* camel-imap-auth.c: IMAP AUTHENTICATE implementations */
-
-/*
- * Authors: Dan Winship <danw@helixcode.com>
- *
- * Copyright 2000 Helix Code, Inc. (www.helixcode.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
- *
- */
-
-#include <config.h>
-
-#include <sys/types.h>
-#include <netinet/in.h>
-
-#include <string.h>
-
-#ifdef HAVE_KRB4
-#include <krb.h>
-/* MIT krb4 des.h #defines _. Sigh. We don't need it. */
-#undef _
-#endif
-
-#include "camel-exception.h"
-#include "camel-mime-utils.h"
-
-#include "camel-imap-auth.h"
-#include "camel-imap-command.h"
-#include "camel-imap-utils.h"
-
-#include "camel-imap-private.h"
-
-#ifdef HAVE_KRB4
-
-#define IMAP_KERBEROS_V4_PROTECTION_NONE 1
-#define IMAP_KERBEROS_V4_PROTECTION_INTEGRITY 2
-#define IMAP_KERBEROS_V4_PROTECTION_PRIVACY 4
-
-gboolean
-imap_try_kerberos_v4_auth (CamelImapStore *store, CamelException *ex)
-{
- CamelImapResponse *response;
- char *resp, *data;
- int status, len;
- char *inst, *realm, *buf, *username;
- guint32 nonce_n, nonce_h, plus1;
- struct hostent *h;
- KTEXT_ST authenticator;
- CREDENTIALS credentials;
- des_cblock session;
- des_key_schedule schedule;
-
- CAMEL_IMAP_STORE_LOCK(store, command_lock);
-
- /* The kickoff. */
- response = camel_imap_command (store, NULL, ex,
- "AUTHENTICATE KERBEROS_V4");
- if (!response)
- goto fail;
- resp = camel_imap_response_extract_continuation (response, ex);
- if (!resp)
- goto fail;
-
- data = imap_next_word (resp);
-
- /* First server response is a base64-encoded 32-bit random number
- * ("nonce") in network byte order.
- */
- if (strlen (data) != 8 || base64_decode_simple (data, 8) != 4) {
- g_free (resp);
- goto break_and_lose;
- }
- memcpy (&nonce_n, data, 4);
- g_free (resp);
- nonce_h = ntohl (nonce_n);
-
- /* Our response is an authenticator including that number. */
- h = camel_service_gethost (CAMEL_SERVICE (store), ex);
- if (!h)
- goto break_and_lose;
- inst = g_strndup (h->h_name, strcspn (h->h_name, "."));
- g_strdown (inst);
- realm = g_strdup (krb_realmofhost (h->h_name));
- status = krb_mk_req (&authenticator, "imap", inst, realm, nonce_h);
- if (status == KSUCCESS) {
- status = krb_get_cred ("imap", inst, realm, &credentials);
- memcpy (session, credentials.session, sizeof (session));
- memset (&credentials, 0, sizeof (credentials));
- }
- g_free (inst);
- g_free (realm);
-
- if (status != KSUCCESS) {
- camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE,
- _("Could not get Kerberos ticket:\n%s"),
- krb_err_txt[status]);
- goto break_and_lose;
- }
- des_key_sched (&session, schedule);
-
- buf = base64_encode_simple (authenticator.dat, authenticator.length);
- response = camel_imap_command_continuation (store, ex, buf);
- g_free (buf);
- if (!response)
- goto lose;
- resp = camel_imap_response_extract_continuation (response, ex);
- if (!resp)
- goto lose;
- data = imap_next_word (resp);
-
- len = strlen (data);
- base64_decode_simple (data, strlen (data));
-
- /* This one is encrypted. */
- des_ecb_encrypt ((des_cblock *)data, (des_cblock *)data, schedule, 0);
-
- /* Check that the returned value is the original nonce plus one. */
- memcpy (&plus1, data, 4);
- if (ntohl (plus1) != nonce_h + 1) {
- g_free (resp);
- goto lose;
- }
-
- /* "the fifth octet contain[s] a bit-mask specifying the
- * protection mechanisms supported by the server"
- */
- if (!(data[4] & IMAP_KERBEROS_V4_PROTECTION_NONE)) {
- g_warning ("Server does not support `no protection' :-(");
- g_free (resp);
- goto break_and_lose;
- }
- g_free (resp);
-
- username = CAMEL_SERVICE (store)->url->user;
- len = strlen (username) + 9;
- len += 8 - len % 8;
- data = g_malloc0 (len);
- memcpy (data, &nonce_n, 4);
- data[4] = IMAP_KERBEROS_V4_PROTECTION_NONE;
- data[5] = data[6] = data[7] = 0;
- strcpy (data + 8, username);
-
- des_pcbc_encrypt ((des_cblock *)data, (des_cblock *)data, len,
- schedule, &session, 1);
- memset (&session, 0, sizeof (session));
- buf = base64_encode_simple (data, len);
- g_free (data);
-
- response = camel_imap_command_continuation (store, ex, buf);
- if (!response)
- goto lose;
- camel_imap_response_free (response);
- CAMEL_IMAP_STORE_UNLOCK(store, command_lock);
- return TRUE;
-
- break_and_lose:
- /* Get the server out of "waiting for continuation data" mode. */
- response = camel_imap_command_continuation (store, NULL, "*");
- if (response)
- camel_imap_response_free (response);
-
- lose:
- memset (&session, 0, sizeof (session));
-
- if (!camel_exception_is_set (ex)) {
- camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE,
- _("Bad authentication response from server."));
- }
- fail:
- CAMEL_IMAP_STORE_UNLOCK(store, command_lock);
- return FALSE;
-}
-#endif /* HAVE_KRB4 */
diff --git a/camel/providers/imap/camel-imap-auth.h b/camel/providers/imap/camel-imap-auth.h
deleted file mode 100644
index fbbc5ef709..0000000000
--- a/camel/providers/imap/camel-imap-auth.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* camel-imap-auth.h: IMAP AUTHENTICATE implementations */
-
-/*
- * Authors:
- * Dan Winship <danw@helixcode.com>
- *
- * Copyright (C) 2000 Helix Code, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
- */
-
-#ifndef CAMEL_IMAP_AUTH_H
-#define CAMEL_IMAP_AUTH_H 1
-
-#ifdef __cplusplus
-extern "C" {
-#pragma }
-#endif /* __cplusplus }*/
-
-#include "camel-imap-store.h"
-
-gboolean imap_try_kerberos_v4_auth (CamelImapStore *store, CamelException *ex);
-gboolean imap_try_gssapi_auth (CamelImapStore *store, CamelException *ex);
-
-#endif /* CAMEL_IMAP_AUTH_H */
diff --git a/camel/providers/imap/camel-imap-store.c b/camel/providers/imap/camel-imap-store.c
index 960d6275ca..a924c4dab7 100644
--- a/camel/providers/imap/camel-imap-store.c
+++ b/camel/providers/imap/camel-imap-store.c
@@ -34,7 +34,6 @@
#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"
@@ -45,6 +44,7 @@
#include "camel-stream-buffer.h"
#include "camel-stream-fs.h"
#include "camel-url.h"
+#include "camel-sasl.h"
#include "string-utils.h"
#include "camel-imap-private.h"
@@ -109,7 +109,7 @@ camel_imap_store_class_init (CamelImapStoreClass *camel_imap_store_class)
}
static gboolean
-free_sub (gpointer key, gpointer value, gpointer user_data)
+free_key (gpointer key, gpointer value, gpointer user_data)
{
g_free (key);
return TRUE;
@@ -122,9 +122,14 @@ camel_imap_store_finalize (CamelObject *object)
if (imap_store->subscribed_folders) {
g_hash_table_foreach_remove (imap_store->subscribed_folders,
- free_sub, NULL);
+ free_key, NULL);
g_hash_table_destroy (imap_store->subscribed_folders);
}
+ if (imap_store->authtypes) {
+ g_hash_table_foreach_remove (imap_store->authtypes,
+ free_key, NULL);
+ g_hash_table_destroy (imap_store->authtypes);
+ }
if (imap_store->namespace)
g_free (imap_store->namespace);
#ifdef ENABLE_THREADS
@@ -183,8 +188,6 @@ static struct {
{ "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 }
@@ -214,6 +217,7 @@ connect_to_server (CamelService *service, CamelException *ex)
/* Find out the IMAP capabilities */
store->capabilities = 0;
+ store->authtypes = g_hash_table_new (g_str_hash, g_str_equal);
response = camel_imap_command (store, NULL, ex, "CAPABILITY");
if (!response)
return FALSE;
@@ -226,6 +230,12 @@ connect_to_server (CamelService *service, CamelException *ex)
for (capa = strtok_r (capa, " ", &lasts); capa;
capa = strtok_r (NULL, " ", &lasts)) {
+ if (!strncmp (capa, "AUTH=", 5)) {
+ g_hash_table_insert (store->authtypes,
+ g_strdup (capa + 5),
+ GINT_TO_POINTER (1));
+ continue;
+ }
for (i = 0; capabilities[i].name; i++) {
if (g_strcasecmp (capa, capabilities[i].name) == 0) {
store->capabilities |= capabilities[i].flag;
@@ -256,39 +266,31 @@ 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 (CamelService *service, gboolean connect, CamelException *ex)
{
- GList *types;
-
+ CamelImapStore *store = CAMEL_IMAP_STORE (service);
+ CamelServiceAuthType *authtype;
+ GList *types, *sasl_types, *t;
+
+ if (connect && !connect_to_server (service, ex))
+ return NULL;
+
types = CAMEL_SERVICE_CLASS (remote_store_class)->query_auth_types (service, connect, ex);
-
+
+ sasl_types = camel_sasl_authtype_list ();
if (connect) {
- if (!connect_to_server (service, ex))
- return NULL;
-#ifdef HAVE_KRB4
- if (CAMEL_IMAP_STORE (service)->capabilities &
- IMAP_CAPABILITY_AUTH_KERBEROS_V4)
- types = g_list_prepend (types, &kerberos_v4_authtype);
-#endif
- } else {
-#ifdef HAVE_KRB4
- types = g_list_prepend (types, &kerberos_v4_authtype);
-#endif
+ for (t = types; t; t = t->next) {
+ authtype = t->data;
+
+ if (!g_hash_table_lookup (store->authtypes, authtype->authproto)) {
+ g_list_remove_link (types, t);
+ g_list_free_1 (t);
+ }
+ }
}
-
+ types = g_list_concat (types, sasl_types);
+
return g_list_prepend (types, &password_authtype);
}
@@ -318,6 +320,68 @@ imap_store_refresh_folders (CamelRemoteStore *store, CamelException *ex)
}
static gboolean
+try_auth (CamelImapStore *store, const char *mech, CamelException *ex)
+{
+ CamelSasl *sasl;
+ CamelImapResponse *response;
+ char *resp;
+ char *sasl_resp;
+
+ sasl = camel_sasl_new ("imap", mech, CAMEL_SERVICE (store));
+
+ sasl_resp = camel_sasl_challenge_base64 (sasl, NULL, ex);
+
+ CAMEL_IMAP_STORE_LOCK (store, command_lock);
+ response = camel_imap_command (store, NULL, ex, "AUTHENTICATE %s%s%s",
+ mech, sasl_resp ? " " : "",
+ sasl_resp ? sasl_resp : "");
+ if (!response)
+ goto lose;
+
+ while (!camel_sasl_authenticated (sasl)) {
+ resp = camel_imap_response_extract_continuation (response, ex);
+ if (!resp)
+ goto lose;
+
+ sasl_resp = camel_sasl_challenge_base64 (sasl, resp + 2, ex);
+ g_free (resp);
+ if (camel_exception_is_set (ex))
+ goto break_and_lose;
+
+ response = camel_imap_command_continuation (store, ex, sasl_resp);
+ g_free (sasl_resp);
+ if (!response)
+ goto lose;
+ }
+
+ resp = camel_imap_response_extract_continuation (response, NULL);
+ if (resp) {
+ /* Oops. SASL claims we're done, but the IMAP server
+ * doesn't think so...
+ */
+ g_free (resp);
+ goto lose;
+ }
+
+ CAMEL_IMAP_STORE_UNLOCK (store, command_lock);
+ return TRUE;
+
+ break_and_lose:
+ /* Get the server out of "waiting for continuation data" mode. */
+ response = camel_imap_command_continuation (store, NULL, "*");
+ if (response)
+ camel_imap_response_free (response);
+
+ lose:
+ if (!camel_exception_is_set (ex)) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE,
+ _("Bad authentication response from server."));
+ }
+ CAMEL_IMAP_STORE_UNLOCK (store, command_lock);
+ return FALSE;
+}
+
+static gboolean
imap_connect (CamelService *service, CamelException *ex)
{
CamelImapStore *store = CAMEL_IMAP_STORE (service);
@@ -326,15 +390,13 @@ imap_connect (CamelService *service, CamelException *ex)
CamelImapResponse *response;
gboolean authenticated = FALSE;
int len, i, flags;
+ CamelServiceAuthType *authtype = NULL;
if (connect_to_server (service, ex) == 0)
return FALSE;
- /* 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)) {
+ if (service->url->authmech) {
+ if (!g_hash_table_lookup (store->authtypes, service->url->authmech)) {
camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE,
"IMAP server %s does not "
"support requested "
@@ -345,13 +407,24 @@ imap_connect (CamelService *service, CamelException *ex)
return FALSE;
}
- authenticated = imap_try_kerberos_v4_auth (store, ex);
- if (camel_exception_is_set (ex)) {
+ authtype = camel_sasl_authtype (service->url->authmech);
+ if (!authtype) {
+ camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE,
+ "No support for "
+ "authentication type %s",
+ service->url->authmech);
camel_service_disconnect (service, TRUE, NULL);
return FALSE;
}
+
+ if (!authtype->need_password) {
+ authenticated = try_auth (store, authtype->authproto, ex);
+ if (!authenticated) {
+ camel_service_disconnect (service, TRUE, NULL);
+ return FALSE;
+ }
+ }
}
-#endif
while (!authenticated) {
if (errbuf) {
@@ -363,7 +436,7 @@ imap_connect (CamelService *service, CamelException *ex)
service->url->passwd = NULL;
}
- if (!service->url->authmech && !service->url->passwd) {
+ if (!service->url->passwd) {
char *prompt;
prompt = g_strdup_printf (_("%sPlease enter the IMAP "
@@ -387,20 +460,25 @@ imap_connect (CamelService *service, CamelException *ex)
}
}
- CAMEL_IMAP_STORE_LOCK(store, command_lock);
- response = camel_imap_command (store, NULL, ex,
- "LOGIN %S %S",
- service->url->user,
- service->url->passwd);
- CAMEL_IMAP_STORE_UNLOCK(store, command_lock);
- if (!response) {
+ if (authtype)
+ authenticated = try_auth (store, authtype->authproto, ex);
+ else {
+ CAMEL_IMAP_STORE_LOCK(store, command_lock);
+ response = camel_imap_command (store, NULL, ex,
+ "LOGIN %S %S",
+ service->url->user,
+ service->url->passwd);
+ CAMEL_IMAP_STORE_UNLOCK(store, command_lock);
+ if (response) {
+ camel_imap_response_free (response);
+ authenticated = TRUE;
+ }
+ }
+ if (!authenticated) {
errbuf = g_strdup_printf (_("Unable to authenticate "
"to IMAP server.\n%s\n\n"),
camel_exception_get_description (ex));
camel_exception_clear (ex);
- } else {
- authenticated = TRUE;
- camel_imap_response_free (response);
}
}
@@ -535,7 +613,7 @@ imap_disconnect (CamelService *service, gboolean clean, CamelException *ex)
if (store->subscribed_folders) {
g_hash_table_foreach_remove (store->subscribed_folders,
- free_sub, NULL);
+ free_key, NULL);
g_hash_table_destroy (store->subscribed_folders);
store->subscribed_folders = NULL;
}
diff --git a/camel/providers/imap/camel-imap-store.h b/camel/providers/imap/camel-imap-store.h
index a24723b657..3792e92872 100644
--- a/camel/providers/imap/camel-imap-store.h
+++ b/camel/providers/imap/camel-imap-store.h
@@ -50,10 +50,8 @@ typedef enum {
#define IMAP_CAPABILITY_IMAP4REV1 (1 << 1)
#define IMAP_CAPABILITY_STATUS (1 << 2)
#define IMAP_CAPABILITY_NAMESPACE (1 << 3)
-#define IMAP_CAPABILITY_AUTH_KERBEROS_V4 (1 << 4)
-#define IMAP_CAPABILITY_AUTH_GSSAPI (1 << 5)
-#define IMAP_CAPABILITY_UIDPLUS (1 << 6)
-#define IMAP_CAPABILITY_LITERALPLUS (1 << 7)
+#define IMAP_CAPABILITY_UIDPLUS (1 << 4)
+#define IMAP_CAPABILITY_LITERALPLUS (1 << 5)
struct _CamelImapStore {
CamelRemoteStore parent_object;
@@ -65,6 +63,7 @@ struct _CamelImapStore {
CamelImapServerLevel server_level;
guint32 capabilities;
+ GHashTable *authtypes;
char *namespace, dir_sep, *storage_path, *base_url;