From 04eb96bf57a408289840f4a00a98fad188d12aa2 Mon Sep 17 00:00:00 2001 From: Not Zed Date: Fri, 3 Aug 2001 15:33:57 +0000 Subject: [PATCH] special case popb4smtp auth before we try and connect, and do the magic 2001-08-03 Not Zed * 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 * 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]. --- camel/ChangeLog | 26 +++++ camel/Makefile.am | 2 + camel/camel-sasl-popb4smtp.c | 155 ++++++++++++++++++++++++++++ camel/camel-sasl-popb4smtp.h | 59 +++++++++++ camel/camel-sasl.c | 5 + camel/providers/smtp/camel-smtp-provider.c | 4 +- camel/providers/smtp/camel-smtp-transport.c | 38 +++++-- 7 files changed, 277 insertions(+), 12 deletions(-) create mode 100644 camel/camel-sasl-popb4smtp.c create mode 100644 camel/camel-sasl-popb4smtp.h diff --git a/camel/ChangeLog b/camel/ChangeLog index cf15b16..8de029b 100644 --- a/camel/ChangeLog +++ b/camel/ChangeLog @@ -1,3 +1,29 @@ +2001-08-03 Not Zed + + * 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 + + * 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 * providers/local/camel-mbox-folder.c (mbox_lock): If we fail to diff --git a/camel/Makefile.am b/camel/Makefile.am index 7dafb8b..572ad3b 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 0000000..7acd8e3 --- /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 + * + * 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 +#endif + +#include +#include +#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 +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 0000000..187789a --- /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 + * + * 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 + +#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 4d27b37..7f58a84 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 299cdc1..a52f3c3 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 93963ff..86674fd 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; -- 2.7.4