aboutsummaryrefslogtreecommitdiffstats
path: root/camel
diff options
context:
space:
mode:
Diffstat (limited to 'camel')
-rw-r--r--camel/ChangeLog18
-rw-r--r--camel/Makefile.am8
-rw-r--r--camel/camel-mime-utils.c24
-rw-r--r--camel/camel-mime-utils.h3
-rw-r--r--camel/camel-sasl-cram-md5.c180
-rw-r--r--camel/camel-sasl-cram-md5.h62
-rw-r--r--camel/camel-sasl-kerberos4.c262
-rw-r--r--camel/camel-sasl-kerberos4.h65
-rw-r--r--camel/camel-sasl-plain.c133
-rw-r--r--camel/camel-sasl-plain.h62
-rw-r--r--camel/camel-sasl.c87
-rw-r--r--camel/camel-sasl.h67
-rw-r--r--camel/providers/imap/camel-imap-auth.c26
13 files changed, 972 insertions, 25 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog
index 0ad8b32e1c..e370e7bbc3 100644
--- a/camel/ChangeLog
+++ b/camel/ChangeLog
@@ -1,3 +1,21 @@
+2001-02-28 Jeffrey Stedfast <fejj@ximian.com>
+
+ * Makefile.am: Added camel-sasl*.[c,h] to the build.
+
+ * camel-sasl.[c,h]: new "abstract" SASL class
+
+ * camel-sasl-kerberos4.[c,h]: new SASL class for KERBEROS_V4
+
+ * camel-sasl-cram-md5.[c,h]: new SASL class for CRAM-MD5
+
+ * camel-sasl-plain.[c,h]: new SASL class for PLAIN
+
+ * providers/imap/camel-imap-auth.c: Removed the base64 functions.
+
+ * camel-mime-utils.c (base64_encode_simple): Moved here from
+ camel-imap-auth.c
+ (base64_decode_simple): Same.
+
2001-02-26 Dan Winship <danw@ximian.com>
* providers/imap/camel-imap-folder.c (imap_sync): Group messages
diff --git a/camel/Makefile.am b/camel/Makefile.am
index f2f46c925d..82e48e58d5 100644
--- a/camel/Makefile.am
+++ b/camel/Makefile.am
@@ -49,6 +49,10 @@ libcamel_la_SOURCES = \
camel-operation.c \
camel-provider.c \
camel-remote-store.c \
+ camel-sasl.c \
+ camel-sasl-cram-md5.c \
+ camel-sasl-kerberos4.c \
+ camel-sasl-plain.c \
camel-search-private.c \
camel-seekable-stream.c \
camel-seekable-substream.c \
@@ -108,6 +112,10 @@ libcamelinclude_HEADERS = \
camel-operation.h \
camel-provider.h \
camel-remote-store.h \
+ camel-sasl.h \
+ camel-sasl-cram-md5.h \
+ camel-sasl-kerberos4.h \
+ camel-sasl-plain.h \
camel-seekable-stream.h \
camel-seekable-substream.h \
camel-service.h \
diff --git a/camel/camel-mime-utils.c b/camel/camel-mime-utils.c
index 10d2c99001..49dce438e1 100644
--- a/camel/camel-mime-utils.c
+++ b/camel/camel-mime-utils.c
@@ -465,6 +465,30 @@ base64_decode_step(unsigned char *in, int len, unsigned char *out, int *state, u
return outptr-out;
}
+char *
+base64_encode_simple (const char *data, int len)
+{
+ unsigned char *out;
+ int state = 0, outlen;
+ unsigned int save = 0;
+
+ out = g_malloc (len * 4 / 3 + 5);
+ outlen = base64_encode_close ((unsigned char *)data, len, FALSE,
+ out, &state, &save);
+ out[outlen] = '\0';
+ return (char *)out;
+}
+
+int
+base64_decode_simple (char *data, int len)
+{
+ int state = 0;
+ unsigned int save = 0;
+
+ return base64_decode_step ((unsigned char *)data, len,
+ (unsigned char *)data, &state, &save);
+}
+
/**
* uudecode_step: uudecode a chunk of data
diff --git a/camel/camel-mime-utils.h b/camel/camel-mime-utils.h
index e37589d4a9..691653d43b 100644
--- a/camel/camel-mime-utils.h
+++ b/camel/camel-mime-utils.h
@@ -191,4 +191,7 @@ int quoted_decode_step(unsigned char *in, int len, unsigned char *out, int *save
int quoted_encode_step(unsigned char *in, int len, unsigned char *out, int *state, int *save);
int quoted_encode_close(unsigned char *in, int len, unsigned char *out, int *state, int *save);
+char *base64_encode_simple (const char *data, int len);
+int base64_decode_simple (char *data, int len);
+
#endif /* ! _CAMEL_MIME_UTILS_H */
diff --git a/camel/camel-sasl-cram-md5.c b/camel/camel-sasl-cram-md5.c
new file mode 100644
index 0000000000..0ad32aae04
--- /dev/null
+++ b/camel/camel-sasl-cram-md5.c
@@ -0,0 +1,180 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright 2001 Ximian, Inc. (www.ximian.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 "camel-sasl-cram-md5.h"
+#include "camel-mime-utils.h"
+#include <e-util/md5-utils.h>
+#include <stdio.h>
+#include <string.h>
+
+static CamelSaslClass *parent_class = NULL;
+
+/* Returns the class for a CamelSaslCramMd5 */
+#define CSCM_CLASS(so) CAMEL_SASL_CRAM_MD5_CLASS (CAMEL_OBJECT_GET_CLASS (so))
+
+static GByteArray *cram_md5_challenge (CamelSasl *sasl, const char *token, CamelException *ex);
+
+enum {
+ STATE_AUTH
+};
+
+struct _CamelSaslCramMd5Private {
+ int state;
+};
+
+static void
+camel_sasl_cram_md5_class_init (CamelSaslCramMd5Class *camel_sasl_cram_md5_class)
+{
+ CamelSaslClass *camel_sasl_class = CAMEL_SASL_CLASS (camel_sasl_cram_md5_class);
+
+ parent_class = CAMEL_SASL_CLASS (camel_type_get_global_classfuncs (camel_sasl_get_type ()));
+
+ /* virtual method overload */
+ camel_sasl_class->challenge = cram_md5_challenge;
+}
+
+static void
+camel_sasl_cram_md5_init (gpointer object, gpointer klass)
+{
+ CamelSaslCramMd5 *sasl_cram = CAMEL_SASL_CRAM_MD5 (object);
+
+ sasl_cram->priv = g_new0 (struct _CamelSaslCramMd5Private, 1);
+}
+
+static void
+camel_sasl_cram_md5_finalize (CamelObject *object)
+{
+ CamelSaslCramMd5 *sasl = CAMEL_SASL_CRAM_MD5 (object);
+
+ g_free (sasl->username);
+ g_free (sasl->priv);
+}
+
+
+CamelType
+camel_sasl_cram_md5_get_type (void)
+{
+ static CamelType type = CAMEL_INVALID_TYPE;
+
+ if (type == CAMEL_INVALID_TYPE) {
+ type = camel_type_register (camel_sasl_get_type (),
+ "CamelSaslCramMd5",
+ sizeof (CamelSaslCramMd5),
+ sizeof (CamelSaslCramMd5Class),
+ (CamelObjectClassInitFunc) camel_sasl_cram_md5_class_init,
+ NULL,
+ (CamelObjectInitFunc) camel_sasl_cram_md5_init,
+ (CamelObjectFinalizeFunc) camel_sasl_cram_md5_finalize);
+ }
+
+ return type;
+}
+
+CamelSasl *
+camel_sasl_cram_md5_new (const char *username, const char *passwd)
+{
+ CamelSaslCramMd5 *sasl_cram;
+
+ if (!username) return NULL;
+ if (!passwd) return NULL;
+
+ sasl_cram = CAMEL_SASL_CRAM_MD5 (camel_object_new (camel_sasl_cram_md5_get_type ()));
+ sasl_cram->username = g_strdup (username);
+ sasl_cram->passwd = g_strdup (passwd);
+
+ return CAMEL_SASL (sasl_cram);
+}
+
+/* CRAM-MD5 algorithm:
+ * MD5 ((passwd XOR opad), MD5 ((passwd XOR ipad), timestamp))
+ */
+
+static GByteArray *
+cram_md5_challenge (CamelSasl *sasl, const char *token, CamelException *ex)
+{
+ CamelSaslCramMd5 *sasl_cram = CAMEL_SASL_CRAM_MD5 (sasl);
+ struct _CamelSaslCramMd5Private *priv = sasl_cram->priv;
+ char *timestamp, *passwd, *buf, *enc;
+ guchar digest[16], md5asc[33], *s, *p;
+ GByteArray *ret = NULL;
+ guchar ipad[64];
+ guchar opad[64];
+ MD5Context ctx;
+ int i, pw_len;
+
+ switch (priv->state) {
+ case STATE_AUTH:
+ timestamp = g_strdup (token);
+ base64_decode_simple (timestamp, strlen (timestamp));
+
+ passwd = sasl_cram->passwd;
+ pw_len = strlen (sasl_cram->passwd);
+ if (pw_len > 64) {
+ md5_init (&ctx);
+ md5_update (&ctx, passwd, pw_len);
+ md5_final (&ctx, digest);
+ passwd = g_strdup (digest);
+ pw_len = 16;
+ }
+
+ memset (ipad, 0, sizeof (ipad));
+ memset (opad, 0, sizeof (opad));
+ memcpy (ipad, passwd, pw_len);
+ memcpy (opad, passwd, pw_len);
+
+ for (i = 0; i < 64; i++) {
+ ipad[i] ^= 0x36;
+ opad[i] ^= 0x5c;
+ }
+
+ md5_init (&ctx);
+ md5_update (&ctx, ipad, 64);
+ md5_update (&ctx, timestamp, strlen (timestamp));
+ md5_final (&ctx, digest);
+
+ md5_init (&ctx);
+ md5_update (&ctx, opad, 64);
+ md5_update (&ctx, digest, 16);
+ md5_final (&ctx, digest);
+
+ /* lowercase hexify that bad-boy... */
+ for (s = digest, p = md5asc; p < md5asc + 32; s++, p += 2)
+ sprintf (p, "%.2x", *s);
+
+ buf = g_strdup_printf ("%s %s", sasl_cram->username, md5asc);
+ enc = base64_encode_simple (buf, strlen (buf));
+ g_free (buf);
+
+ ret = g_byte_array_new ();
+ g_byte_array_append (ret, enc, strlen (enc));
+ g_free (enc);
+
+ break;
+ default:
+ break;
+ }
+
+ priv->state++;
+
+ return ret;
+}
diff --git a/camel/camel-sasl-cram-md5.h b/camel/camel-sasl-cram-md5.h
new file mode 100644
index 0000000000..12f4d211fa
--- /dev/null
+++ b/camel/camel-sasl-cram-md5.h
@@ -0,0 +1,62 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright 2001 Ximian, Inc. (www.ximian.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.
+ *
+ */
+
+#ifndef CAMEL_SASL_CRAM_MD5_H
+#define CAMEL_SASL_CRAM_MD5_H
+
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif /* __cplusplus }*/
+
+#include <camel/camel-sasl.h>
+
+#define CAMEL_SASL_CRAM_MD5_TYPE (camel_sasl_cram_md5_get_type ())
+#define CAMEL_SASL_CRAM_MD5(obj) (CAMEL_CHECK_CAST((obj), CAMEL_SASL_CRAM_MD5_TYPE, CamelSaslCramMd5))
+#define CAMEL_SASL_CRAM_MD5_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_SASL_CRAM_MD5_TYPE, CamelSaslCramMd5Class))
+#define CAMEL_IS_SASL_CRAM_MD5(o) (CAMEL_CHECK_TYPE((o), CAMEL_SASL_CRAM_MD5_TYPE))
+
+typedef struct _CamelSaslCramMd5 {
+ CamelSasl parent_object;
+ struct _CamelSaslCramMd5Private *priv;
+
+ char *username, *passwd;
+} CamelSaslCramMd5;
+
+
+typedef struct _CamelSaslCramMd5Class {
+ CamelSaslClass parent_class;
+
+} CamelSaslCramMd5Class;
+
+
+/* Standard Camel function */
+CamelType camel_sasl_cram_md5_get_type (void);
+
+/* public methods */
+CamelSasl * camel_sasl_cram_md5_new (const char *username, const char *passwd);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* CAMEL_SASL_CRAM_MD5_H */
diff --git a/camel/camel-sasl-kerberos4.c b/camel/camel-sasl-kerberos4.c
new file mode 100644
index 0000000000..28ef780773
--- /dev/null
+++ b/camel/camel-sasl-kerberos4.c
@@ -0,0 +1,262 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright 2001 Ximian, Inc. (www.ximian.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 "camel-sasl-kerberos4.h"
+#include "camel-mime-utils.h"
+#include <string.h>
+
+
+#ifdef HAVE_KRB4
+#include <krb.h>
+/* MIT krb4 des.h #defines _. Sigh. We don't need it. */
+#undef _
+#endif
+
+#define KERBEROS_V4_PROTECTION_NONE 1
+#define KERBEROS_V4_PROTECTION_INTEGRITY 2
+#define KERBEROS_V4_PROTECTION_PRIVACY 4
+
+static CamelSaslClass *parent_class = NULL;
+
+/* Returns the class for a CamelSaslKerberos4 */
+#define CSK4_CLASS(so) CAMEL_SASL_KERBEROS4_CLASS (CAMEL_OBJECT_GET_CLASS (so))
+
+#ifdef HAVE_KRB4
+static GByteArray *krb4_challenge (CamelSasl *sasl, const char *token, CamelException *ex);
+#endif
+
+enum {
+ STATE_NONCE,
+ STATE_NONCE_PLUS_ONE,
+ STATE_FINAL
+};
+
+struct _CamelSaslKerberos4Private {
+ int state;
+
+ guint32 nonce_n;
+ guint32 nonce_h;
+ guint32 plus1;
+
+#ifdef HAVE_KRB4
+ KTEXT_ST authenticator;
+ CREDENTIALS credentials;
+ des_cblock session;
+ des_key_schedule schedule;
+#endif /* HAVE_KRB4 */
+};
+
+static void
+camel_sasl_kerberos4_class_init (CamelSaslKerberos4Class *camel_sasl_kerberos4_class)
+{
+#ifdef HAVE_KRB4
+ CamelSaslClass *camel_sasl_class = CAMEL_SASL_CLASS (camel_sasl_kerberos4_class);
+#endif
+
+ parent_class = CAMEL_SASL_CLASS (camel_type_get_global_classfuncs (camel_sasl_get_type ()));
+
+ /* virtual method overload */
+#ifdef HAVE_KRB4
+ camel_sasl_class->challenge = krb4_challenge;
+#endif
+}
+
+static void
+camel_sasl_kerberos4_init (gpointer object, gpointer klass)
+{
+ CamelSaslKerberos4 *sasl_krb4 = CAMEL_SASL_KERBEROS4 (object);
+
+ sasl_krb4->priv = g_new0 (struct _CamelSaslKerberos4Private, 1);
+}
+
+static void
+camel_sasl_kerberos4_finalize (CamelObject *object)
+{
+ CamelSaslKerberos4 *sasl = CAMEL_SASL_KERBEROS4 (object);
+
+ g_free (sasl->protocol);
+ g_free (sasl->username);
+ g_free (sasl->priv);
+}
+
+
+CamelType
+camel_sasl_kerberos4_get_type (void)
+{
+ static CamelType type = CAMEL_INVALID_TYPE;
+
+ if (type == CAMEL_INVALID_TYPE) {
+ type = camel_type_register (camel_sasl_get_type (),
+ "CamelSaslKerberos4",
+ sizeof (CamelSaslKerberos4),
+ sizeof (CamelSaslKerberos4Class),
+ (CamelObjectClassInitFunc) camel_sasl_kerberos4_class_init,
+ NULL,
+ (CamelObjectInitFunc) camel_sasl_kerberos4_init,
+ (CamelObjectFinalizeFunc) camel_sasl_kerberos4_finalize);
+ }
+
+ return type;
+}
+
+CamelSasl *
+camel_sasl_kerberos4_new (const char *protocol, const char *username, struct hostent *host)
+{
+ CamelSaslKerberos4 *sasl_krb4;
+
+ if (!protocol) return NULL;
+ if (!username) return NULL;
+ if (!host) return NULL;
+
+#ifdef HAVE_KRB4
+ sasl_krb4 = CAMEL_SASL_KERBEROS4 (camel_object_new (camel_sasl_kerberos4_get_type ()));
+ sasl_krb4->protocol = g_strdup (protocol);
+ g_strdown (sasl_krb4->protocol);
+ sasl_krb4->username = g_strdup (username);
+ sasl_krb4->host = host;
+
+ return CAMEL_SASL (sasl_krb4);
+#else
+ return NULL;
+#endif /* HAVE_KRB4 */
+}
+
+#ifdef HAVE_KRB4
+static GByteArray *
+krb4_challenge (CamelSasl *sasl, const char *token, CamelException *ex)
+{
+ CamelSaslKerberos4 *sasl_krb4 = CAMEL_SASL_KERBEROS4 (sasl);
+ struct CamelSaslKerberos4Private *priv = sasl_krb4->priv;
+ char *buf = NULL, *data = NULL;
+ GByteArray *ret = NULL;
+ char *inst, *realm;
+ struct hostent *h;
+ int status, len;
+
+ if (token)
+ data = g_strdup (token);
+ else
+ goto fail;
+
+ switch (priv->state) {
+ case STATE_NONCE:
+ if (strlen (data) != 8 || base64_decode_simple (data, 8) != 4)
+ goto break_and_lose;
+
+ memcpy (&priv->nonce_n, data, 4);
+ priv->nonce_h = ntohl (priv->nonce_n);
+
+ /* Our response is an authenticator including that number. */
+ h = sasl_krb4->host;
+ 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, sasl_krb4->protocol, inst, realm, priv->nonce_h);
+ if (status == KSUCCESS) {
+ status = krb_get_cred (sasl_krb4->protocol, 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);
+ break;
+ case STATE_NONCE_PLUS_ONE:
+ len = strlen (data);
+ base64_decode_simple (data, len);
+
+ /* 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 (&priv->plus1, data, 4);
+ if (ntohl (priv->plus1) != priv->nonce_h + 1)
+ goto lose;
+
+ /* "the fifth octet contain[s] a bit-mask specifying the
+ * protection mechanisms supported by the server"
+ */
+ if (!(data[4] & KERBEROS_V4_PROTECTION_NONE)) {
+ g_warning ("Server does not support `no protection' :-(");
+ goto break_and_lose;
+ }
+
+ len = strlen (sasl_krb4->username) + 9;
+ len += 8 - len % 8;
+ data = g_malloc0 (len);
+ memcpy (data, &priv->nonce_n, 4);
+ data[4] = KERBEROS_V4_PROTECTION_NONE;
+ data[5] = data[6] = data[7] = 0;
+ strcpy (data + 8, sasl_krb4->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);
+ break;
+ case STATE_FINAL:
+ sasl->authenticated = TRUE;
+ break;
+ default:
+ break;
+ }
+
+ g_free (data);
+ priv->state++;
+
+ if (buf) {
+ ret = g_byte_array_new ();
+ g_byte_array_append (ret, buf, strlen (buf));
+ g_free (buf);
+ }
+
+ return ret;
+
+ break_and_lose:
+ /* Get the server out of "waiting for continuation data" mode. */
+ g_free (data);
+ ret = g_byte_array_new ();
+ g_byte_array_append (ret, "*", 1);
+ return ret;
+
+ 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:
+ g_free (data);
+ return NULL;
+}
+#endif HAVE_KRB4
diff --git a/camel/camel-sasl-kerberos4.h b/camel/camel-sasl-kerberos4.h
new file mode 100644
index 0000000000..5b674ba766
--- /dev/null
+++ b/camel/camel-sasl-kerberos4.h
@@ -0,0 +1,65 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright 2001 Ximian, Inc. (www.ximian.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.
+ *
+ */
+
+#ifndef CAMEL_SASL_KERBEROS4_H
+#define CAMEL_SASL_KERBEROS4_H
+
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif /* __cplusplus }*/
+
+#include <camel/camel-sasl.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+
+#define CAMEL_SASL_KERBEROS4_TYPE (camel_sasl_kerberos4_get_type ())
+#define CAMEL_SASL_KERBEROS4(obj) (CAMEL_CHECK_CAST((obj), CAMEL_SASL_KERBEROS4_TYPE, CamelSaslKerberos4))
+#define CAMEL_SASL_KERBEROS4_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_SASL_KERBEROS4_TYPE, CamelSaslKerberos4Class))
+#define CAMEL_IS_SASL_KERBEROS4(o) (CAMEL_CHECK_TYPE((o), CAMEL_SASL_KERBEROS4_TYPE))
+
+typedef struct _CamelSaslKerberos4 {
+ CamelSasl parent_object;
+ struct _CamelSaslKerberos4Private *priv;
+
+ struct hostent *host;
+ char *protocol, *username;
+} CamelSaslKerberos4;
+
+
+typedef struct _CamelSaslKerberos4Class {
+ CamelSaslClass parent_class;
+
+} CamelSaslKerberos4Class;
+
+
+/* Standard Camel function */
+CamelType camel_sasl_kerberos4_get_type (void);
+
+/* public methods */
+CamelSasl * camel_sasl_kerberos4_new (const char *protocol, const char *username, struct hostent *host);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* CAMEL_SASL_KERBEROS4_H */
diff --git a/camel/camel-sasl-plain.c b/camel/camel-sasl-plain.c
new file mode 100644
index 0000000000..5d986350c9
--- /dev/null
+++ b/camel/camel-sasl-plain.c
@@ -0,0 +1,133 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright 2001 Ximian, Inc. (www.ximian.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 "camel-sasl-plain.h"
+#include <string.h>
+
+static CamelSaslClass *parent_class = NULL;
+
+/* Returns the class for a CamelSaslPlain */
+#define CSP_CLASS(so) CAMEL_SASL_PLAIN_CLASS (CAMEL_OBJECT_GET_CLASS (so))
+
+static GByteArray *plain_challenge (CamelSasl *sasl, const char *token, CamelException *ex);
+
+enum {
+ STATE_LOGIN
+};
+
+struct _CamelSaslPlainPrivate {
+ int state;
+};
+
+static void
+camel_sasl_plain_class_init (CamelSaslPlainClass *camel_sasl_plain_class)
+{
+ CamelSaslClass *camel_sasl_class = CAMEL_SASL_CLASS (camel_sasl_plain_class);
+
+ parent_class = CAMEL_SASL_CLASS (camel_type_get_global_classfuncs (camel_sasl_get_type ()));
+
+ /* virtual method overload */
+ camel_sasl_class->challenge = plain_challenge;
+}
+
+static void
+camel_sasl_plain_init (gpointer object, gpointer klass)
+{
+ CamelSaslPlain *sasl_plain = CAMEL_SASL_PLAIN (object);
+
+ sasl_plain->priv = g_new0 (struct _CamelSaslPlainPrivate, 1);
+}
+
+static void
+camel_sasl_plain_finalize (CamelObject *object)
+{
+ CamelSaslPlain *sasl = CAMEL_SASL_PLAIN (object);
+
+ g_free (sasl->login);
+ g_free (sasl->auth_id);
+ g_free (sasl->passwd);
+ g_free (sasl->priv);
+}
+
+
+CamelType
+camel_sasl_plain_get_type (void)
+{
+ static CamelType type = CAMEL_INVALID_TYPE;
+
+ if (type == CAMEL_INVALID_TYPE) {
+ type = camel_type_register (camel_sasl_get_type (),
+ "CamelSaslPlain",
+ sizeof (CamelSaslPlain),
+ sizeof (CamelSaslPlainClass),
+ (CamelObjectClassInitFunc) camel_sasl_plain_class_init,
+ NULL,
+ (CamelObjectInitFunc) camel_sasl_plain_init,
+ (CamelObjectFinalizeFunc) camel_sasl_plain_finalize);
+ }
+
+ return type;
+}
+
+CamelSasl *
+camel_sasl_plain_new (const char *login, const char *auth_id, const char *passwd)
+{
+ CamelSaslPlain *sasl_plain;
+
+ if (!auth_id) return NULL;
+ if (!passwd) return NULL;
+
+ sasl_plain = CAMEL_SASL_PLAIN (camel_object_new (camel_sasl_plain_get_type ()));
+ sasl_plain->login = g_strdup (login);
+ sasl_plain->auth_id = g_strdup (auth_id);
+ sasl_plain->passwd = g_strdup (passwd);
+
+ return CAMEL_SASL (sasl_plain);
+}
+
+static GByteArray *
+plain_challenge (CamelSasl *sasl, const char *token, CamelException *ex)
+{
+ CamelSaslPlain *sasl_plain = CAMEL_SASL_PLAIN (sasl);
+ struct _CamelSaslPlainPrivate *priv = sasl_plain->priv;
+ GByteArray *buf = NULL;
+
+ switch (priv->state) {
+ case STATE_LOGIN:
+ /* FIXME: make sure these are "UTF8-SAFE" */
+ buf = g_byte_array_new ();
+ if (sasl_plain->login)
+ g_byte_array_append (buf, sasl_plain->login, strlen (sasl_plain->login));
+ g_byte_array_append (buf, "", 1);
+ g_byte_array_append (buf, sasl_plain->auth_id, strlen (sasl_plain->auth_id));
+ g_byte_array_append (buf, "", 1);
+ g_byte_array_append (buf, sasl_plain->passwd, strlen (sasl_plain->passwd));
+ break;
+ default:
+ break;
+ }
+
+ priv->state++;
+
+ return buf;
+}
diff --git a/camel/camel-sasl-plain.h b/camel/camel-sasl-plain.h
new file mode 100644
index 0000000000..cf4d3d4a97
--- /dev/null
+++ b/camel/camel-sasl-plain.h
@@ -0,0 +1,62 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright 2001 Ximian, Inc. (www.ximian.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.
+ *
+ */
+
+#ifndef CAMEL_SASL_PLAIN_H
+#define CAMEL_SASL_PLAIN_H
+
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif /* __cplusplus }*/
+
+#include <camel/camel-sasl.h>
+
+#define CAMEL_SASL_PLAIN_TYPE (camel_sasl_plain_get_type ())
+#define CAMEL_SASL_PLAIN(obj) (CAMEL_CHECK_CAST((obj), CAMEL_SASL_PLAIN_TYPE, CamelSaslPlain))
+#define CAMEL_SASL_PLAIN_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_SASL_PLAIN_TYPE, CamelSaslPlainClass))
+#define CAMEL_IS_SASL_PLAIN(o) (CAMEL_CHECK_TYPE((o), CAMEL_SASL_PLAIN_TYPE))
+
+typedef struct _CamelSaslPlain {
+ CamelSasl parent_object;
+ struct _CamelSaslPlainPrivate *priv;
+
+ char *login, *auth_id, *passwd;
+} CamelSaslPlain;
+
+
+typedef struct _CamelSaslPlainClass {
+ CamelSaslClass parent_class;
+
+} CamelSaslPlainClass;
+
+
+/* Standard Camel function */
+CamelType camel_sasl_plain_get_type (void);
+
+/* public methods */
+CamelSasl * camel_sasl_plain_new (const char *login, const char *auth_id, const char *passwd);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* CAMEL_SASL_PLAIN_H */
diff --git a/camel/camel-sasl.c b/camel/camel-sasl.c
new file mode 100644
index 0000000000..a5aebe737c
--- /dev/null
+++ b/camel/camel-sasl.c
@@ -0,0 +1,87 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright 2001 Ximian, Inc. (www.ximian.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 "camel-sasl.h"
+
+static CamelObjectClass *parent_class = NULL;
+
+/* Returns the class for a CamelSasl */
+#define CS_CLASS(so) CAMEL_SASL_CLASS (CAMEL_OBJECT_GET_CLASS (so))
+
+static GByteArray *sasl_challenge (CamelSasl *sasl, const char *token, CamelException *ex);
+
+static void
+camel_sasl_class_init (CamelSaslClass *camel_sasl_class)
+{
+ parent_class = camel_type_get_global_classfuncs (CAMEL_OBJECT_TYPE);
+
+ /* virtual method definition */
+ camel_sasl_class->challenge = sasl_challenge;
+}
+
+CamelType
+camel_sasl_get_type (void)
+{
+ static CamelType type = CAMEL_INVALID_TYPE;
+
+ if (type == CAMEL_INVALID_TYPE) {
+ type = camel_type_register (CAMEL_OBJECT_TYPE,
+ "CamelSasl",
+ sizeof (CamelSasl),
+ sizeof (CamelSaslClass),
+ (CamelObjectClassInitFunc) camel_sasl_class_init,
+ NULL,
+ NULL,
+ NULL );
+ }
+
+ return type;
+}
+
+
+static GByteArray *
+sasl_challenge (CamelSasl *sasl, const char *token, CamelException *ex)
+{
+ g_warning ("sasl_challenge: Using default implementation!");
+ return NULL;
+}
+
+/**
+ * camel_sasl_challenge:
+ * @sasl: a sasl object
+ * @token: a token
+ * @ex: exception
+ *
+ * Generate the next sasl challenge to send to the server.
+ *
+ * Return value: a string containing the base64 encoded sasl challenge
+ * or NULL on either an error or if the negotiation is complete. If an
+ * error has occured, @ex will also be set.
+ **/
+GByteArray *
+camel_sasl_challenge (CamelSasl *sasl, const char *token, CamelException *ex)
+{
+ g_return_val_if_fail (CAMEL_IS_SASL (sasl), NULL);
+
+ return CS_CLASS (sasl)->challenge (sasl, token, ex);
+}
diff --git a/camel/camel-sasl.h b/camel/camel-sasl.h
new file mode 100644
index 0000000000..24201a0b03
--- /dev/null
+++ b/camel/camel-sasl.h
@@ -0,0 +1,67 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright 2001 Ximian, Inc. (www.ximian.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.
+ *
+ */
+
+#ifndef CAMEL_SASL_H
+#define CAMEL_SASL_H
+
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif /* __cplusplus }*/
+
+#include <glib.h>
+#include <camel/camel-object.h>
+#include <camel/camel-exception.h>
+
+#define CAMEL_SASL_TYPE (camel_sasl_get_type ())
+#define CAMEL_SASL(obj) (CAMEL_CHECK_CAST((obj), CAMEL_SASL_TYPE, CamelSasl))
+#define CAMEL_SASL_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_SASL_TYPE, CamelSaslClass))
+#define CAMEL_IS_SASL(o) (CAMEL_CHECK_TYPE((o), CAMEL_SASL_TYPE))
+
+typedef struct _CamelSasl {
+ CamelObject parent_object;
+
+ gboolean authenticated;
+} CamelSasl;
+
+
+typedef struct _CamelSaslClass {
+ CamelObjectClass parent_class;
+
+ GByteArray * (*challenge) (CamelSasl *sasl, const char *token, CamelException *ex);
+
+} CamelSaslClass;
+
+
+/* Standard Camel function */
+CamelType camel_sasl_get_type (void);
+
+/* public methods */
+GByteArray *camel_sasl_challenge (CamelSasl *sasl, const char *token, CamelException *ex);
+
+gboolean camel_sasl_authenticated (CamelSasl *sasl);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* CAMEL_SASL_H */
diff --git a/camel/providers/imap/camel-imap-auth.c b/camel/providers/imap/camel-imap-auth.c
index 42abd1fa55..a1daf88888 100644
--- a/camel/providers/imap/camel-imap-auth.c
+++ b/camel/providers/imap/camel-imap-auth.c
@@ -46,30 +46,6 @@
#ifdef HAVE_KRB4
-static char *
-base64_encode_simple (const char *data, int len)
-{
- unsigned char *out;
- int state = 0, outlen;
- unsigned int save = 0;
-
- out = g_malloc (len * 4 / 3 + 5);
- outlen = base64_encode_close ((unsigned char *)data, len, FALSE,
- out, &state, &save);
- out[outlen] = '\0';
- return (char *)out;
-}
-
-static int
-base64_decode_simple (char *data, int len)
-{
- int state = 0;
- unsigned int save = 0;
-
- return base64_decode_step ((unsigned char *)data, len,
- (unsigned char *)data, &state, &save);
-}
-
#define IMAP_KERBEROS_V4_PROTECTION_NONE 1
#define IMAP_KERBEROS_V4_PROTECTION_INTEGRITY 2
#define IMAP_KERBEROS_V4_PROTECTION_PRIVACY 4
@@ -204,7 +180,7 @@ imap_try_kerberos_v4_auth (CamelImapStore *store, CamelException *ex)
camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE,
_("Bad authentication response from server."));
}
-fail:
+ fail:
CAMEL_IMAP_STORE_UNLOCK(store, command_lock);
return FALSE;
}