special case popb4smtp auth before we try and connect, and do the magic
authorNot Zed <NotZed@Ximian.com>
Fri, 3 Aug 2001 15:33:57 +0000 (15:33 +0000)
committerMichael Zucci <zucchi@src.gnome.org>
Fri, 3 Aug 2001 15:33:57 +0000 (15:33 +0000)
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].

camel/ChangeLog
camel/Makefile.am
camel/camel-sasl-popb4smtp.c [new file with mode: 0644]
camel/camel-sasl-popb4smtp.h [new file with mode: 0644]
camel/camel-sasl.c
camel/providers/smtp/camel-smtp-provider.c
camel/providers/smtp/camel-smtp-transport.c

index cf15b16..8de029b 100644 (file)
@@ -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
index 7dafb8b..572ad3b 100644 (file)
@@ -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 (file)
index 0000000..7acd8e3
--- /dev/null
@@ -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 (file)
index 0000000..187789a
--- /dev/null
@@ -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 */
index 4d27b37..7f58a84 100644 (file)
@@ -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;
 }
index 299cdc1..a52f3c3 100644 (file)
@@ -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);
index 93963ff..86674fd 100644 (file)
@@ -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;