aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--camel/ChangeLog26
-rw-r--r--camel/Makefile.am2
-rw-r--r--camel/camel-sasl-popb4smtp.c155
-rw-r--r--camel/camel-sasl-popb4smtp.h59
-rw-r--r--camel/camel-sasl.c5
-rw-r--r--camel/providers/smtp/camel-smtp-provider.c4
-rw-r--r--camel/providers/smtp/camel-smtp-transport.c38
7 files changed, 277 insertions, 12 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog
index cf15b16eb5..8de029bd0b 100644
--- a/camel/ChangeLog
+++ b/camel/ChangeLog
@@ -1,3 +1,29 @@
+2001-08-03 Not Zed <NotZed@Ximian.com>
+
+ * providers/smtp/camel-smtp-transport.c (smtp_connect): special
+ case popb4smtp auth before we try and connect, and do the magic
+ here first.
+
+2001-08-02 Not Zed <NotZed@Ximian.com>
+
+ * providers/smtp/camel-smtp-transport.c (smtp_connect): Check for
+ POPB4SMTP separate to the esmtp auth list.
+ (smtp_auth): If creating the sasl object means it is
+ already authenticated, then exit early. Sort of 'clean hack' to
+ help popb4smtp work.
+ (smtp_auth): Unref the sasl object, clean up a memleak i think.
+
+ * providers/smtp/camel-smtp-provider.c
+ (camel_provider_module_init): Added POPB4SMTP auth type.
+
+ * camel-sasl.c (camel_sasl_authtype): Added POPB4SMTP type.
+
+ * camel-sasl-popb4smtp.c: New file for pop before smtp
+ 'authentication'.
+
+ * Makefile.am (libcamel_la_SOURCES, HEADERS): Add
+ camel-sasl-popb4smtp.[ch].
+
2001-08-01 Not Zed <NotZed@Ximian.com>
* providers/local/camel-mbox-folder.c (mbox_lock): If we fail to
diff --git a/camel/Makefile.am b/camel/Makefile.am
index 7dafb8bf83..572ad3bafa 100644
--- a/camel/Makefile.am
+++ b/camel/Makefile.am
@@ -77,6 +77,7 @@ libcamel_la_SOURCES = \
camel-sasl-kerberos4.c \
camel-sasl-login.c \
camel-sasl-plain.c \
+ camel-sasl-popb4smtp.c \
camel-search-private.c \
camel-seekable-stream.c \
camel-seekable-substream.c \
@@ -162,6 +163,7 @@ libcamelinclude_HEADERS = \
camel-sasl-kerberos4.h \
camel-sasl-login.h \
camel-sasl-plain.h \
+ camel-sasl-popb4smtp.h \
camel-seekable-stream.h \
camel-seekable-substream.h \
camel-service.h \
diff --git a/camel/camel-sasl-popb4smtp.c b/camel/camel-sasl-popb4smtp.c
new file mode 100644
index 0000000000..7acd8e385c
--- /dev/null
+++ b/camel/camel-sasl-popb4smtp.c
@@ -0,0 +1,155 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Michael Zucchi <notzed@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.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <time.h>
+#include "camel-sasl-popb4smtp.h"
+#include "camel-service.h"
+#include "camel-session.h"
+
+CamelServiceAuthType camel_sasl_popb4smtp_authtype = {
+ N_("POP before SMTP"),
+
+ N_("This option will authorise a POP connection before attempting SMTP"),
+
+ "POPB4SMTP",
+ FALSE,
+};
+
+/* last time the pop was accessed (through the auth method anyway), *time_t */
+static GHashTable *poplast;
+
+/* use 1 hour as our pop timeout */
+#define POPB4SMTP_TIMEOUT (60*60)
+
+#ifdef ENABLE_THREADS
+#include <pthread.h>
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+#define POPB4SMTP_LOCK(l) pthread_mutex_lock(&l)
+#define POPB4SMTP_UNLOCK(l) pthread_mutex_unlock(&l)
+#else
+#define POPB4SMTP_LOCK(l)
+#define POPB4SMTP_UNLOCK(l)
+#endif
+
+static CamelSaslClass *parent_class = NULL;
+
+/* Returns the class for a CamelSaslPOPB4SMTP */
+#define CSP_CLASS(so) CAMEL_SASL_POPB4SMTP_CLASS (CAMEL_OBJECT_GET_CLASS (so))
+
+static GByteArray *popb4smtp_challenge (CamelSasl *sasl, GByteArray *token, CamelException *ex);
+
+static void
+camel_sasl_popb4smtp_class_init (CamelSaslPOPB4SMTPClass *camel_sasl_popb4smtp_class)
+{
+ CamelSaslClass *camel_sasl_class = CAMEL_SASL_CLASS (camel_sasl_popb4smtp_class);
+
+ parent_class = CAMEL_SASL_CLASS (camel_type_get_global_classfuncs (camel_sasl_get_type ()));
+
+ /* virtual method overload */
+ camel_sasl_class->challenge = popb4smtp_challenge;
+
+ poplast = g_hash_table_new(g_str_hash, g_str_equal);
+}
+
+CamelType
+camel_sasl_popb4smtp_get_type (void)
+{
+ static CamelType type = CAMEL_INVALID_TYPE;
+
+ if (type == CAMEL_INVALID_TYPE) {
+ type = camel_type_register (camel_sasl_get_type (),
+ "CamelSaslPOPB4SMTP",
+ sizeof (CamelSaslPOPB4SMTP),
+ sizeof (CamelSaslPOPB4SMTPClass),
+ (CamelObjectClassInitFunc) camel_sasl_popb4smtp_class_init,
+ NULL,
+ NULL,
+ NULL);
+ }
+
+ return type;
+}
+
+static GByteArray *
+popb4smtp_challenge (CamelSasl *sasl, GByteArray *token, CamelException *ex)
+{
+ char *popuri;
+ CamelSession *session = sasl->service->session;
+ CamelStore *store;
+ time_t now, *timep;
+
+ sasl->authenticated = FALSE;
+
+ popuri = camel_session_get_password(session, _("POP Source URI"), FALSE,
+ sasl->service, "popb4smtp_uri", ex);
+
+ if (popuri == NULL) {
+ camel_exception_setv(ex, 1, _("POP Before SMTP auth using an unknown transport"));
+ return NULL;
+ }
+
+ if (strncasecmp(popuri, "pop:", 4) != 0) {
+ camel_exception_setv(ex, 1, _("POP Before SMTP auth using a non-pop source"));
+ return NULL;
+ }
+
+ /* check if we've done it before recently in this session */
+ now = time(0);
+
+ /* need to lock around the whole thing until finished with timep */
+
+ POPB4SMTP_LOCK(lock);
+ timep = g_hash_table_lookup(poplast, popuri);
+ if (timep) {
+ if ((*timep + POPB4SMTP_TIMEOUT) > now) {
+ sasl->authenticated = TRUE;
+ POPB4SMTP_UNLOCK(lock);
+ g_free(popuri);
+ return NULL;
+ }
+ } else {
+ timep = g_malloc0(sizeof(*timep));
+ g_hash_table_insert(poplast, g_strdup(popuri), timep);
+ }
+
+ /* connect to pop session */
+ store = camel_session_get_store(session, popuri, ex);
+ if (store) {
+ sasl->authenticated = TRUE;
+ camel_object_unref((CamelObject *)store);
+ *timep = now;
+ } else {
+ sasl->authenticated = FALSE;
+ *timep = 0;
+ }
+
+ POPB4SMTP_UNLOCK(lock);
+
+ g_free(popuri);
+
+ return NULL;
+}
diff --git a/camel/camel-sasl-popb4smtp.h b/camel/camel-sasl-popb4smtp.h
new file mode 100644
index 0000000000..187789a4df
--- /dev/null
+++ b/camel/camel-sasl-popb4smtp.h
@@ -0,0 +1,59 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Michael Zucchi <notzed@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_POPB4SMTP_H
+#define CAMEL_SASL_POPB4SMTP_H
+
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif /* __cplusplus }*/
+
+#include <camel/camel-sasl.h>
+
+#define CAMEL_SASL_POPB4SMTP_TYPE (camel_sasl_popb4smtp_get_type ())
+#define CAMEL_SASL_POPB4SMTP(obj) (CAMEL_CHECK_CAST((obj), CAMEL_SASL_POPB4SMTP_TYPE, CamelSaslPOPB4SMTP))
+#define CAMEL_SASL_POPB4SMTP_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_SASL_POPB4SMTP_TYPE, CamelSaslPOPB4SMTPClass))
+#define CAMEL_IS_SASL_POPB4SMTP(o) (CAMEL_CHECK_TYPE((o), CAMEL_SASL_POPB4SMTP_TYPE))
+
+typedef struct _CamelSaslPOPB4SMTP {
+ CamelSasl parent_object;
+
+} CamelSaslPOPB4SMTP;
+
+
+typedef struct _CamelSaslPOPB4SMTPClass {
+ CamelSaslClass parent_class;
+
+} CamelSaslPOPB4SMTPClass;
+
+
+/* Standard Camel function */
+CamelType camel_sasl_popb4smtp_get_type (void);
+
+extern CamelServiceAuthType camel_sasl_popb4smtp_authtype;
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* CAMEL_SASL_POPB4SMTP_H */
diff --git a/camel/camel-sasl.c b/camel/camel-sasl.c
index 4d27b37b75..7f58a84bb7 100644
--- a/camel/camel-sasl.c
+++ b/camel/camel-sasl.c
@@ -34,6 +34,7 @@
#include "camel-sasl-kerberos4.h"
#include "camel-sasl-login.h"
#include "camel-sasl-plain.h"
+#include "camel-sasl-popb4smtp.h"
static CamelObjectClass *parent_class = NULL;
@@ -196,6 +197,8 @@ camel_sasl_new (const char *service_name, const char *mechanism, CamelService *s
sasl = (CamelSasl *)camel_object_new (CAMEL_SASL_PLAIN_TYPE);
else if (!strcmp (mechanism, "LOGIN"))
sasl = (CamelSasl *)camel_object_new (CAMEL_SASL_LOGIN_TYPE);
+ else if (!strcmp (mechanism, "POPB4SMTP"))
+ sasl = (CamelSasl *)camel_object_new (CAMEL_SASL_POPB4SMTP_TYPE);
else
return NULL;
@@ -251,6 +254,8 @@ camel_sasl_authtype (const char *mechanism)
return &camel_sasl_plain_authtype;
else if (!strcmp (mechanism, "LOGIN"))
return &camel_sasl_login_authtype;
+ else if (!strcmp(mechanism, "POPB4SMTP"))
+ return &camel_sasl_popb4smtp_authtype;
else
return NULL;
}
diff --git a/camel/providers/smtp/camel-smtp-provider.c b/camel/providers/smtp/camel-smtp-provider.c
index 299cdc1ccb..a52f3c3a14 100644
--- a/camel/providers/smtp/camel-smtp-provider.c
+++ b/camel/providers/smtp/camel-smtp-provider.c
@@ -54,8 +54,8 @@ camel_provider_module_init (CamelSession *session)
{
smtp_provider.object_types[CAMEL_PROVIDER_TRANSPORT] =
camel_smtp_transport_get_type ();
- smtp_provider.authtypes = g_list_append (camel_sasl_authtype_list (TRUE),
- camel_sasl_authtype ("LOGIN"));
+ smtp_provider.authtypes = g_list_append(camel_sasl_authtype_list(TRUE), camel_sasl_authtype ("LOGIN"));
+ smtp_provider.authtypes = g_list_append(smtp_provider.authtypes, camel_sasl_authtype ("POPB4SMTP"));
smtp_provider.service_cache = g_hash_table_new (camel_url_hash, camel_url_equal);
camel_session_register_provider (session, &smtp_provider);
diff --git a/camel/providers/smtp/camel-smtp-transport.c b/camel/providers/smtp/camel-smtp-transport.c
index 93963ffe1b..86674fdc2a 100644
--- a/camel/providers/smtp/camel-smtp-transport.c
+++ b/camel/providers/smtp/camel-smtp-transport.c
@@ -233,7 +233,7 @@ connect_to_server (CamelService *service, CamelException *ex)
struct hostent *h;
guint32 addrlen;
int port, ret;
-
+
if (!CAMEL_SERVICE_CLASS (parent_class)->connect (service, ex))
return FALSE;
@@ -343,6 +343,25 @@ smtp_connect (CamelService *service, CamelException *ex)
{
CamelSmtpTransport *transport = CAMEL_SMTP_TRANSPORT (service);
+ /* We (probably) need to check popb4smtp before we connect ... */
+ if (strcmp(service->url->authmech, "POPB4SMTP") == 0) {
+ int truth;
+ GByteArray *chal;
+ CamelSasl *sasl;
+
+ sasl = camel_sasl_new("smtp", "POPB4SMTP", service);
+ chal = camel_sasl_challenge(sasl, NULL, ex);
+ truth = camel_sasl_authenticated(sasl);
+ if (chal)
+ g_byte_array_free(chal, TRUE);
+ camel_object_unref((CamelObject *)sasl);
+
+ if (!truth)
+ return FALSE;
+
+ return connect_to_server(service, ex);
+ }
+
if (!connect_to_server (service, ex))
return FALSE;
@@ -352,11 +371,11 @@ smtp_connect (CamelService *service, CamelException *ex)
CamelServiceAuthType *authtype;
gboolean authenticated = FALSE;
char *errbuf = NULL;
-
+
if (!transport->is_esmtp || !g_hash_table_lookup (transport->authtypes, service->url->authmech)) {
camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE,
_("SMTP server %s does not support requested "
- "authentication type %s"), service->url->host,
+ "authentication type %s"), service->url->host,
service->url->authmech);
camel_service_disconnect (service, TRUE, NULL);
return FALSE;
@@ -737,17 +756,17 @@ smtp_auth (CamelSmtpTransport *transport, const char *mech, CamelException *ex)
gchar *cmdbuf, *respbuf = NULL, *challenge;
CamelSasl *sasl;
+ camel_operation_start_transient(NULL, _("SMTP Authentication"));
+
sasl = camel_sasl_new ("smtp", mech, CAMEL_SERVICE (transport));
if (!sasl) {
- g_free (respbuf);
+ camel_operation_end(NULL);
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
_("Error creating SASL authentication object."));
return FALSE;
}
- camel_operation_start_transient(NULL, _("SMTP Authentication"));
-
- challenge = camel_sasl_challenge_base64 (sasl, NULL, ex);
+ challenge = camel_sasl_challenge_base64(sasl, NULL, ex);
if (challenge) {
cmdbuf = g_strdup_printf ("AUTH %s %s\r\n", mech, challenge);
g_free (challenge);
@@ -812,6 +831,7 @@ smtp_auth (CamelSmtpTransport *transport, const char *mech, CamelException *ex)
goto lose;
}
+ camel_object_unref((CamelObject *)sasl);
camel_operation_end(NULL);
return TRUE;
@@ -829,9 +849,7 @@ smtp_auth (CamelSmtpTransport *transport, const char *mech, CamelException *ex)
_("Bad authentication response from server.\n"));
}
- if (sasl)
- camel_object_unref (CAMEL_OBJECT (sasl));
-
+ camel_object_unref (CAMEL_OBJECT (sasl));
camel_operation_end(NULL);
return FALSE;