diff -ruNp evolution-data-server-1.8.2.orig/addressbook/libebook/e-book.c evolution-data-server-1.8.2/addressbook/libebook/e-book.c
--- evolution-data-server-1.8.2.orig/addressbook/libebook/e-book.c	2006-11-06 09:24:54.000000000 -0500
+++ evolution-data-server-1.8.2/addressbook/libebook/e-book.c	2007-04-18 15:16:13.000000000 -0400
@@ -16,6 +16,8 @@
 #include <glib/gi18n-lib.h>
 #include <libedataserver/e-component-listener.h>
 
+#include <gnome-certauth/gca-nss-certificate-source.h>
+
 #include "e-book-marshal.h"
 #include "e-book-listener.h"
 
@@ -3277,6 +3279,7 @@ fetch_corba_book (EBook       *book,
 		  GError     **error)
 {
 	GNOME_Evolution_Addressbook_Book corba_book = CORBA_OBJECT_NIL;
+	GObject *nss_source;
 	gchar *uri;
 	gchar *source_xml;
 	GList *factories;
@@ -3293,6 +3296,7 @@ fetch_corba_book (EBook       *book,
 	/* try to find a list of factories that can handle the protocol */
 	factories = activate_factories_for_uri (book, uri);
 	if (!factories) {
+		g_free (uri);
 		g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_PROTOCOL_NOT_SUPPORTED,
 			     _("%s: no factories available for URI `%s'"), "e_book_load_uri", uri);
 		return FALSE;
@@ -3304,11 +3308,27 @@ fetch_corba_book (EBook       *book,
 	 */
 	book->priv->listener = e_book_listener_new ();
 	if (book->priv->listener == NULL) {
+		g_free (uri);
 		g_warning ("e_book_load_uri: Could not create EBookListener!\n");
 		g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_OTHER_ERROR,
 			     _("%s: Could not create EBookListener"), "e_book_load_uri");
 		return FALSE;
 	}
+	nss_source = g_object_new (GCA_TYPE_NSS_CERTIFICATE_SOURCE,
+				   "poa", bonobo_poa_get_threaded (ORBIT_THREAD_HINT_PER_REQUEST),
+				   NULL);
+	if (!nss_source) {
+		g_object_unref (book->priv->listener);
+		book->priv->listener = NULL;
+		g_free (uri);
+		g_warning ("e_book_load_uri: Could not create GcaNssCertificateSource!\n");
+		g_set_error (error, E_BOOK_ERROR, E_BOOK_ERROR_OTHER_ERROR,
+			     _("%s: Could not create GcaNssCertificateSource"), "e_book_load_uri");
+		return FALSE;
+	}
+	bonobo_object_add_interface (BONOBO_OBJECT (book->priv->listener),
+				     BONOBO_OBJECT (nss_source));
+
 	book->priv->listener_signal = g_signal_connect_object (book->priv->listener, "response",
 							       G_CALLBACK (e_book_handle_response),
 							       book, 0);
diff -ruNp evolution-data-server-1.8.2.orig/addressbook/libedata-book/e-book-backend.c evolution-data-server-1.8.2/addressbook/libedata-book/e-book-backend.c
--- evolution-data-server-1.8.2.orig/addressbook/libedata-book/e-book-backend.c	2005-08-18 02:55:45.000000000 -0400
+++ evolution-data-server-1.8.2/addressbook/libedata-book/e-book-backend.c	2007-04-18 15:16:13.000000000 -0400
@@ -28,6 +28,8 @@ struct _EBookBackendPrivate {
 /* Signal IDs */
 enum {
 	LAST_CLIENT_GONE,
+	ADD_CLIENT,
+	REMOVE_CLIENT,
 	LAST_SIGNAL
 };
 
@@ -571,6 +573,8 @@ e_book_backend_add_client (EBookBackend 
 	backend->priv->clients = g_list_prepend (backend->priv->clients, book);
 	g_mutex_unlock (backend->priv->clients_mutex);
 
+	g_signal_emit (backend, e_book_backend_signals[ADD_CLIENT], 0, book);
+
 	return TRUE;
 }
 
@@ -593,6 +597,8 @@ e_book_backend_remove_client (EBookBacke
 	   lock) */
 	g_object_ref (backend);
 
+	g_signal_emit (backend, e_book_backend_signals[REMOVE_CLIENT], 0, book);
+
 	/* Disconnect */
 	g_mutex_lock (backend->priv->clients_mutex);
 	backend->priv->clients = g_list_remove (backend->priv->clients, book);
@@ -1069,6 +1075,24 @@ e_book_backend_class_init (EBookBackendC
 			      NULL, NULL,
 			      e_data_book_marshal_NONE__NONE,
 			      G_TYPE_NONE, 0);
+
+	e_book_backend_signals[ADD_CLIENT] = 
+		g_signal_new ("add_client",
+			      G_OBJECT_CLASS_TYPE (object_class),
+			      G_SIGNAL_RUN_FIRST,
+			      G_STRUCT_OFFSET (EBookBackendClass, add_client),
+			      NULL, NULL,
+			      e_data_book_marshal_NONE__POINTER,
+			      G_TYPE_NONE, 1, G_TYPE_POINTER);
+
+	e_book_backend_signals[REMOVE_CLIENT] = 
+		g_signal_new ("remove_client",
+			      G_OBJECT_CLASS_TYPE (object_class),
+			      G_SIGNAL_RUN_FIRST,
+			      G_STRUCT_OFFSET (EBookBackendClass, remove_client),
+			      NULL, NULL,
+			      e_data_book_marshal_NONE__POINTER,
+			      G_TYPE_NONE, 1, G_TYPE_POINTER);
 }
 
 /**
diff -ruNp evolution-data-server-1.8.2.orig/addressbook/libedata-book/e-book-backend.h evolution-data-server-1.8.2/addressbook/libedata-book/e-book-backend.h
--- evolution-data-server-1.8.2.orig/addressbook/libedata-book/e-book-backend.h	2005-03-15 13:42:51.000000000 -0500
+++ evolution-data-server-1.8.2/addressbook/libedata-book/e-book-backend.h	2007-04-18 15:16:13.000000000 -0400
@@ -70,10 +70,10 @@ struct _EBookBackendClass {
 
 	/* Notification signals */
 	void (* last_client_gone) (EBookBackend *backend);
+	void (*add_client) (EBookBackend *backend, EDataBook *book);
+	void (*remove_client) (EBookBackend *backend, EDataBook *book);
 
 	/* Padding for future expansion */
-	void (*_pas_reserved0) (void);
-	void (*_pas_reserved1) (void);
 	void (*_pas_reserved2) (void);
 	void (*_pas_reserved3) (void);
 	void (*_pas_reserved4) (void);
diff -ruNp evolution-data-server-1.8.2.orig/addressbook/libedata-book/e-data-book.c evolution-data-server-1.8.2/addressbook/libedata-book/e-data-book.c
--- evolution-data-server-1.8.2.orig/addressbook/libedata-book/e-data-book.c	2006-03-23 05:08:37.000000000 -0500
+++ evolution-data-server-1.8.2/addressbook/libedata-book/e-data-book.c	2007-04-18 15:16:13.000000000 -0400
@@ -88,7 +88,7 @@ impl_GNOME_Evolution_Addressbook_Book_au
 							CORBA_Environment *ev)
 {
 	EDataBook *book = E_DATA_BOOK (bonobo_object (servant));
-
+	fprintf (stderr, "authenticateUser()\n");
 	e_book_backend_authenticate_user (e_data_book_get_backend (book), book,
 					  opid, user, passwd, auth_method);
 }
@@ -871,6 +871,8 @@ e_data_book_report_auth_required (EDataB
 
 	CORBA_Environment ev;
 
+	fprintf (stderr, "report_auth_required()\n");
+
 	CORBA_exception_init (&ev);
 	
 	GNOME_Evolution_Addressbook_BookListener_notifyAuthRequired (
diff -ruNp evolution-data-server-1.8.2.orig/calendar/libecal/e-cal.c evolution-data-server-1.8.2/calendar/libecal/e-cal.c
--- evolution-data-server-1.8.2.orig/calendar/libecal/e-cal.c	2007-04-18 15:15:48.000000000 -0400
+++ evolution-data-server-1.8.2/calendar/libecal/e-cal.c	2007-04-18 15:16:13.000000000 -0400
@@ -32,6 +32,8 @@
 #include <bonobo/bonobo-exception.h>
 #include <bonobo/bonobo-main.h>
 
+#include <gnome-certauth/gca-nss-certificate-source.h>
+
 #include <libedataserver/e-component-listener.h>
 #include <libedataserver/e-url.h>
 #include "e-cal-marshal.h"
@@ -387,6 +389,8 @@ destroy_cal (ECal *ecal)
 	CORBA_Environment ev;
 	int result;
 
+	fprintf (stderr, "destroying cal: %p\n", ecal);
+
 	priv = ecal->priv;
 
 	CORBA_exception_init (&ev);
@@ -986,19 +990,20 @@ cal_query_cb (ECalListener *listener, EC
 	g_mutex_unlock (op->mutex);	
 }
 
-static gboolean  
+static gpointer
 reopen_with_auth (gpointer data)
 {
 	ECalendarStatus status;
 	
 	open_calendar (E_CAL (data), TRUE, NULL, &status, TRUE);
-	return FALSE;
+	return NULL;
 }
 
 static void
 auth_required_cb (ECalListener *listener, gpointer data)
 {
-	g_idle_add (reopen_with_auth, data);	
+	//g_idle_add (reopen_with_auth, data);	
+	g_thread_create (reopen_with_auth, data, FALSE, NULL);
 
 }
 
@@ -1140,6 +1145,7 @@ static void
 e_cal_init (ECal *ecal, ECalClass *klass)
 {
 	ECalPrivate *priv;
+	GObject *nss_source;
 
 	priv = g_new0 (ECalPrivate, 1);
 	ecal->priv = priv;
@@ -1150,6 +1156,16 @@ e_cal_init (ECal *ecal, ECalClass *klass
 	priv->mutex = g_mutex_new ();
 	priv->listener = e_cal_listener_new (cal_set_mode_cb, ecal);
 
+	nss_source = g_object_new (GCA_TYPE_NSS_CERTIFICATE_SOURCE,
+				   "poa", bonobo_poa_get_threaded (ORBIT_THREAD_HINT_PER_REQUEST),
+				   NULL);
+	if (!nss_source) {
+		g_warning ("e_cal_init: Could not create GcaNssCertificateSource!\n");
+	} else {
+		bonobo_object_add_interface (BONOBO_OBJECT (priv->listener),
+					     BONOBO_OBJECT (nss_source));
+	}
+
 	priv->cal_address = NULL;
 	priv->alarm_email_address = NULL;
 	priv->ldap_attribute = NULL;
@@ -1707,6 +1723,8 @@ open_calendar (ECal *ecal, gboolean only
 	
 	g_mutex_lock (ecal->priv->mutex);
 
+	fprintf (stderr, "trying to open: %p\n", ecal);
+
 	if (!needs_auth && priv->load_state == E_CAL_LOAD_LOADED) {
 		g_mutex_unlock (ecal->priv->mutex);
 		return TRUE;
@@ -1724,7 +1742,7 @@ open_calendar (ECal *ecal, gboolean only
 	g_mutex_unlock (priv->mutex);
 
 	/* see if the backend needs authentication */
-	if ( (priv->mode !=  CAL_MODE_LOCAL) && e_source_get_property (priv->source, "auth")) {
+	if ( needs_auth && (priv->mode !=  CAL_MODE_LOCAL) && e_source_get_property (priv->source, "auth")) {
 		char *prompt, *key;
 		const char *parent_user;
 
diff -ruNp evolution-data-server-1.8.2.orig/calendar/libedata-cal/e-cal-backend.c evolution-data-server-1.8.2/calendar/libedata-cal/e-cal-backend.c
--- evolution-data-server-1.8.2.orig/calendar/libedata-cal/e-cal-backend.c	2006-07-10 06:35:52.000000000 -0400
+++ evolution-data-server-1.8.2/calendar/libedata-cal/e-cal-backend.c	2007-04-18 15:16:13.000000000 -0400
@@ -66,6 +66,8 @@ enum {
 	LAST_CLIENT_GONE,
 	OPENED,
 	REMOVED,
+	ADD_CLIENT,
+	REMOVE_CLIENT,
 	LAST_SIGNAL
 };
 static guint e_cal_backend_signals[LAST_SIGNAL];
@@ -237,6 +239,22 @@ e_cal_backend_class_init (ECalBackendCla
 			      G_TYPE_NONE, 1,
 			      G_TYPE_INT);
 
+	e_cal_backend_signals[ADD_CLIENT] =
+		g_signal_new ("add_client",
+			      G_TYPE_FROM_CLASS (class),
+			      G_SIGNAL_RUN_FIRST,
+			      0, NULL, NULL,
+			      g_cclosure_marshal_VOID__POINTER,
+			      G_TYPE_NONE, 1, G_TYPE_POINTER);
+
+	e_cal_backend_signals[ADD_CLIENT] =
+		g_signal_new ("remove_client",
+			      G_TYPE_FROM_CLASS (class),
+			      G_SIGNAL_RUN_FIRST,
+			      0, NULL, NULL,
+			      g_cclosure_marshal_VOID__POINTER,
+			      G_TYPE_NONE, 1, G_TYPE_POINTER);
+
 	class->last_client_gone = NULL;
 	class->opened = NULL;
 	class->obj_updated = NULL;
@@ -420,6 +438,8 @@ e_cal_backend_add_client (ECalBackend *b
 	g_mutex_lock (priv->clients_mutex);
 	priv->clients = g_list_append (priv->clients, cal);
 	g_mutex_unlock (priv->clients_mutex);
+
+	g_signal_emit (backend, e_cal_backend_signals[ADD_CLIENT], 0, cal);
 }
 
 /**
@@ -444,6 +464,8 @@ e_cal_backend_remove_client (ECalBackend
 
 	priv = backend->priv;
 
+	g_signal_emit (backend, e_cal_backend_signals[REMOVE_CLIENT], 0, cal);
+
 	/* Disconnect */
 	g_mutex_lock (priv->clients_mutex);
 	priv->clients = g_list_remove (priv->clients, cal);
diff -ruNp evolution-data-server-1.8.2.orig/config.h.in evolution-data-server-1.8.2/config.h.in
--- evolution-data-server-1.8.2.orig/config.h.in	2006-11-20 06:08:53.000000000 -0500
+++ evolution-data-server-1.8.2/config.h.in	2007-04-18 15:16:13.000000000 -0400
@@ -85,6 +85,9 @@
 /* Define if the GNU gettext() function is already present or preinstalled. */
 #undef HAVE_GETTEXT
 
+/* Define if you have gnome-certauth */
+#undef HAVE_GNOME_CERTAUTH
+
 /* Define to 1 if you have the `gnu_get_libc_version' function. */
 #undef HAVE_GNU_GET_LIBC_VERSION
 
diff -ruNp evolution-data-server-1.8.2.orig/configure.in evolution-data-server-1.8.2/configure.in
--- evolution-data-server-1.8.2.orig/configure.in	2007-04-18 15:15:49.000000000 -0400
+++ evolution-data-server-1.8.2/configure.in	2007-04-18 15:16:13.000000000 -0400
@@ -351,8 +351,6 @@ ac_cv_lkstrftime=yes
 ])
 AC_MSG_RESULT($ac_cv_lkstrftime)
 
-PKG_PROG_PKG_CONFIG
-
 dnl ********************************************************************************
 dnl security extension support (SSL and S/MIME)
 dnl
@@ -1243,6 +1241,11 @@ dnl ************************************
 dnl Flags for the various libraries we build
 dnl ****************************************
 
+PKG_CHECK_EXISTS([gnome-certauth-0.0],[
+	gnome_certauth="gnome-certauth-0.0 >= 0.0"
+	AC_DEFINE([HAVE_GNOME_CERTAUTH], [1], [Define if you have gnome-certauth])
+])
+
 dnl --- libedataserver and libedataserverui flags
 
 E_DATA_SERVER_DEPS="libxml-2.0 gobject-2.0 >= $GLIB_REQUIRED libbonobo-2.0 >= $LIBBONOBO_REQUIRED gconf-2.0 $mozilla_nspr"
@@ -1259,7 +1262,7 @@ AC_SUBST(E_DATA_SERVER_UI_LIBS)
 
 dnl --- evolution-addressbook flags
 
-EVOLUTION_ADDRESSBOOK_DEPS="libxml-2.0 gobject-2.0 gconf-2.0 libbonobo-2.0 >= $LIBBONOBO_REQUIRED libgnome-2.0 gnome-vfs-2.0"
+EVOLUTION_ADDRESSBOOK_DEPS="libxml-2.0 gobject-2.0 gconf-2.0 libbonobo-2.0 >= $LIBBONOBO_REQUIRED libgnome-2.0 gnome-vfs-2.0 $gnome_certauth"
 
 EVO_SET_COMPILE_FLAGS(EVOLUTION_ADDRESSBOOK, $EVOLUTION_ADDRESSBOOK_DEPS)
 AC_SUBST(EVOLUTION_ADDRESSBOOK_CFLAGS)
@@ -1267,7 +1270,7 @@ AC_SUBST(EVOLUTION_ADDRESSBOOK_LIBS)
 
 dnl --- evolution-calendar flags
 
-EVOLUTION_CALENDAR_DEPS="libxml-2.0 gobject-2.0 gconf-2.0 libbonobo-2.0 >= $LIBBONOBO_REQUIRED libgnome-2.0 gnome-vfs-2.0"
+EVOLUTION_CALENDAR_DEPS="libxml-2.0 gobject-2.0 gconf-2.0 libbonobo-2.0 >= $LIBBONOBO_REQUIRED libgnome-2.0 gnome-vfs-2.0 $gnome_certauth"
 
 EVO_SET_COMPILE_FLAGS(EVOLUTION_CALENDAR, $EVOLUTION_CALENDAR_DEPS)
 AC_SUBST(EVOLUTION_CALENDAR_CFLAGS)
diff -ruNp evolution-data-server-1.8.2.orig/servers/exchange/lib/e2k-autoconfig.c evolution-data-server-1.8.2/servers/exchange/lib/e2k-autoconfig.c
--- evolution-data-server-1.8.2.orig/servers/exchange/lib/e2k-autoconfig.c	2006-05-10 04:24:12.000000000 -0400
+++ evolution-data-server-1.8.2/servers/exchange/lib/e2k-autoconfig.c	2007-04-18 15:16:13.000000000 -0400
@@ -337,6 +337,13 @@ get_ctx_auth_handler (SoupMessage *msg, 
 	}
 }
 
+void
+e2k_autoconfig_set_creds (E2kAutoconfig *ac,
+			  E2kCreds      *creds)
+{
+	ac->creds = creds;
+}
+
 /*
  * e2k_autoconfig_get_context:
  * @ac: an autoconfig context
@@ -395,8 +402,12 @@ e2k_autoconfig_get_context (E2kAutoconfi
 		*result = E2K_AUTOCONFIG_FAILED;
 		return NULL;
 	}
-	e2k_context_set_auth (ctx, ac->username, ac->nt_domain,
-			      ac->use_ntlm ? "NTLM" : "Basic", ac->password);
+	if (ac->creds) {
+		e2k_context_set_creds (ctx, ac->creds);
+	} else {
+		e2k_context_set_auth (ctx, ac->username, ac->nt_domain,
+				      ac->use_ntlm ? "NTLM" : "Basic", ac->password);
+	}
 
 	msg = e2k_soup_message_new (ctx, ac->owa_uri, SOUP_METHOD_GET);
 	soup_message_add_header (msg->request_headers, "Accept-Language",
diff -ruNp evolution-data-server-1.8.2.orig/servers/exchange/lib/e2k-autoconfig.h evolution-data-server-1.8.2/servers/exchange/lib/e2k-autoconfig.h
--- evolution-data-server-1.8.2.orig/servers/exchange/lib/e2k-autoconfig.h	2005-07-01 01:43:21.000000000 -0400
+++ evolution-data-server-1.8.2/servers/exchange/lib/e2k-autoconfig.h	2007-04-18 15:16:13.000000000 -0400
@@ -47,6 +47,7 @@ typedef struct {
 	gboolean require_ntlm, use_ntlm;
 	gboolean saw_basic, saw_ntlm;
 	gboolean nt_domain_defaulted, gc_server_autodetected;
+	E2kCreds *creds;
 } E2kAutoconfig;
 
 E2kAutoconfig       *e2k_autoconfig_new                  (const char *owa_uri,
@@ -64,7 +65,8 @@ void                 e2k_autoconfig_set_
 							  const char *username);
 void                 e2k_autoconfig_set_password         (E2kAutoconfig *ac,
 							  const char *password);
-
+void                 e2k_autoconfig_set_creds            (E2kAutoconfig *ac,
+							  E2kCreds      *creds);
 E2kContext          *e2k_autoconfig_get_context          (E2kAutoconfig *ac,
 							  E2kOperation *op,
 							  E2kAutoconfigResult *result);
diff -ruNp evolution-data-server-1.8.2.orig/servers/exchange/lib/e2k-context.c evolution-data-server-1.8.2/servers/exchange/lib/e2k-context.c
--- evolution-data-server-1.8.2.orig/servers/exchange/lib/e2k-context.c	2007-04-18 15:15:48.000000000 -0400
+++ evolution-data-server-1.8.2/servers/exchange/lib/e2k-context.c	2007-04-18 15:16:13.000000000 -0400
@@ -52,7 +52,6 @@
 #include <libedataserver/e-proxy.h>
 #include <libsoup/soup-address.h>
 #include <libsoup/soup-message-filter.h>
-#include <libsoup/soup-session-async.h>
 #include <libsoup/soup-session-sync.h>
 #include <libsoup/soup-socket.h>
 #include <libsoup/soup-uri.h>
@@ -60,6 +59,18 @@
 #include <libxml/tree.h>
 #include <libxml/xmlmemory.h>
 
+#if 1
+#define GCA_TRACE(s, ...) fprintf (stderr, "%d:%s:%s():%d "s"\n", getpid(), __FILE__, __PRETTY_FUNCTION__, __LINE__, __VA_ARGS__)
+#else
+#define GCA_TRACE(s, ...)
+#endif
+
+#define GCA_TRACEMSG(s) GCA_TRACE("%s", (s))
+#define GCA_ENTER GCA_TRACEMSG("ENTER")
+#define GCA_EXIT GCA_TRACEMSG("EXIT")
+#define GCA_HASLOCK GCA_TRACEMSG("HAS LOCK")
+#define GCA_ALREADYLOCKED GCA_TRACEMSG("ALREADY LOCKED")
+
 #ifdef G_OS_WIN32
 /* The strtok() in Microsoft's C library is MT-safe (not stateless,
  * but that is not needed here).
@@ -90,8 +101,8 @@ enum {
 static guint signals [LAST_SIGNAL] = { 0 };
 
 struct _E2kContextPrivate {
-	SoupSession *session, *async_session;
-	char *owa_uri, *username, *password;
+	SoupSession *session;
+	char *owa_uri;
 	time_t last_timestamp;
 
 	/* Notification listener */
@@ -106,8 +117,18 @@ struct _E2kContextPrivate {
 	char *cookie;
 	gboolean cookie_verified;
 	EProxy* proxy;
+
+	E2kCreds *creds;
+	gboolean free_creds;
 };
 
+typedef struct {
+	E2kCreds creds;
+	char *username;
+	char *authmech;
+	char *password;
+} E2kAuthCreds;
+
 /* For operations with progress */
 #define E2K_CONTEXT_MIN_BATCH_SIZE 25
 #define E2K_CONTEXT_MAX_BATCH_SIZE 100
@@ -136,9 +157,7 @@ proxy_settings_changed (EProxy *proxy, g
 {
 	SoupUri *proxy_uri = NULL;
 	E2kContext* ctx = (E2kContext *)user_data;
-	if (!ctx || !ctx->priv || 
-	    (!ctx->priv->session && !ctx->priv->async_session) ||
-	    (!ctx->priv->owa_uri))
+	if (!ctx || !ctx->priv || !ctx->priv->session || !ctx->priv->owa_uri)
 		return;
 
 	if (!e_proxy_require_proxy_for_uri (proxy, ctx->priv->owa_uri))
@@ -149,9 +168,6 @@ proxy_settings_changed (EProxy *proxy, g
 	if (ctx->priv->session)
 		g_object_set (ctx->priv->session, SOUP_SESSION_PROXY_URI,
 			      proxy_uri, NULL);
-	if (ctx->priv->async_session)
-		g_object_set (ctx->priv->async_session, SOUP_SESSION_PROXY_URI,
-			      proxy_uri, NULL);
 }
 
 static void
@@ -177,6 +193,31 @@ destroy_sub_list (gpointer uri, gpointer
 }
 
 static void
+release_creds (E2kContext *ctx)
+{
+	E2kAuthCreds *creds;
+
+	if (!ctx->priv->creds) {
+		return;
+	}
+
+	if (!ctx->priv->free_creds) {
+		ctx->priv->creds = NULL;
+		return;
+	}
+
+	creds = (E2kAuthCreds *)ctx->priv->creds;
+			
+	g_free (creds->username);
+	g_free (creds->authmech);
+	g_free (creds->password);
+	
+	g_free (creds);
+	ctx->priv->free_creds = FALSE;
+	ctx->priv->creds = NULL;
+}
+
+static void
 dispose (GObject *object)
 {
 	E2kContext *ctx = E2K_CONTEXT (object);
@@ -184,10 +225,6 @@ dispose (GObject *object)
 	if (ctx->priv) {
 		if (ctx->priv->owa_uri)
 			g_free (ctx->priv->owa_uri);
-		if (ctx->priv->username)
-			g_free (ctx->priv->username);
-		if (ctx->priv->password)
-			g_free (ctx->priv->password);
 
 		if (ctx->priv->get_local_address_sock)
 			g_object_unref (ctx->priv->get_local_address_sock);
@@ -208,8 +245,6 @@ dispose (GObject *object)
 
 		if (ctx->priv->session)
 			g_object_unref (ctx->priv->session);
-		if (ctx->priv->async_session)
-			g_object_unref (ctx->priv->async_session);
 
 		g_free (ctx->priv->cookie);
 
@@ -217,6 +252,9 @@ dispose (GObject *object)
 			g_object_unref (ctx->priv->proxy);
 			ctx->priv->proxy = NULL;
 		}
+
+		release_creds (ctx);
+
 		g_free (ctx->priv);
 		ctx->priv = NULL;
 		
@@ -378,51 +416,73 @@ session_authenticate (SoupSession *sessi
 {
 	E2kContext *ctx = user_data;
 
-	*username = g_strdup (ctx->priv->username);
-	*password = g_strdup (ctx->priv->password);
+	if (ctx->priv->creds && ctx->priv->creds->http_authenticate) {
+		ctx->priv->creds->http_authenticate (ctx->priv->creds,
+						     auth_type, auth_realm,
+						     username, password);
+	}
+}
+
+static int
+session_certificate_requested (SoupSession *session,
+			       const gnutls_datum_t *req_ca_rdn,
+			       int nreqs,
+			       gnutls_datum_t **cert_der_ret,
+			       int *cert_der_ret_length,
+			       gpointer user_data)
+{
+	E2kContext *ctx = user_data;
+	int ret = 0;
+	GCA_ENTER;
+	g_return_val_if_fail (E2K_IS_CONTEXT (ctx), -1);
+
+	if (ctx->priv->creds && ctx->priv->creds->ssl_cert_request) {
+		ret = ctx->priv->creds->ssl_cert_request (
+			ctx->priv->creds,
+			req_ca_rdn, nreqs,
+			cert_der_ret, cert_der_ret_length);
+	}
+	GCA_EXIT;
+	return ret;
+}
+
+static int
+session_sign_data (SoupSession *session,
+		   gnutls_datum_t *cert,
+		   const gnutls_datum_t *hash_data,
+		   gnutls_datum_t *sig_data,
+		   gpointer user_data)
+{
+	E2kContext *ctx = user_data;
+	int ret = 0;
+	GCA_ENTER;
+	g_return_val_if_fail (E2K_IS_CONTEXT (ctx), -1);
+
+	if (ctx->priv->creds && ctx->priv->creds->ssl_cert_sign) {
+		ret = ctx->priv->creds->ssl_cert_sign (
+			ctx->priv->creds, cert,
+			hash_data, sig_data);
+	}
+	GCA_EXIT;
+	return ret;
 }
 
-/**
- * e2k_context_set_auth:
- * @ctx: the context
- * @username: the Windows username (not including domain) of the user
- * @domain: the NT domain, or %NULL to use the default (if using NTLM)
- * @authmech: the HTTP Authorization type to use; either "Basic" or "NTLM"
- * @password: the user's password
- *
- * Sets the authentication information on @ctx. This will have the
- * side effect of cancelling any pending requests on @ctx.
- **/
 void
-e2k_context_set_auth (E2kContext *ctx, const char *username,
-		      const char *domain, const char *authmech,
-		      const char *password)
+e2k_context_set_creds (E2kContext *ctx,
+		       E2kCreds   *creds)
 {
 	guint timeout = E2K_SOUP_SESSION_TIMEOUT;
 	SoupUri* uri = NULL;
+	char *authmech = NULL;
 
 	g_return_if_fail (E2K_IS_CONTEXT (ctx));
 
-	if (username) {
-		g_free (ctx->priv->username);
-		if (domain) {
-			ctx->priv->username =
-				g_strdup_printf ("%s\\%s", domain,
-						 username);
-		} else
-			ctx->priv->username = g_strdup (username);
-	}
-
-	if (password) {
-		g_free (ctx->priv->password);
-		ctx->priv->password = g_strdup (password);
-	}
-
 	/* Destroy the old sessions so we don't reuse old auths */
 	if (ctx->priv->session)
 		g_object_unref (ctx->priv->session);
-	if (ctx->priv->async_session)
-		g_object_unref (ctx->priv->async_session);
+
+	release_creds (ctx);
+	ctx->priv->creds = creds;
 
 	/* Set a default timeout value of 30 seconds.
 	   FIXME: Make timeout configurable 
@@ -434,6 +494,10 @@ e2k_context_set_auth (E2kContext *ctx, c
         if (e_proxy_require_proxy_for_uri (ctx->priv->proxy, ctx->priv->owa_uri))
                 uri = e_proxy_peek_uri (ctx->priv->proxy);
 
+	if (ctx->priv->creds->http_auth_method) {
+		authmech = ctx->priv->creds->http_auth_method (ctx->priv->creds);
+	}
+
 	ctx->priv->session = soup_session_sync_new_with_options (
 		SOUP_SESSION_USE_NTLM, !authmech || !strcmp (authmech, "NTLM"),
 		SOUP_SESSION_TIMEOUT, timeout,
@@ -441,16 +505,76 @@ e2k_context_set_auth (E2kContext *ctx, c
 		NULL);
 	g_signal_connect (ctx->priv->session, "authenticate",
 			  G_CALLBACK (session_authenticate), ctx);
+	g_signal_connect (ctx->priv->session, "certificate-requested",
+			  G_CALLBACK (session_certificate_requested), ctx);
+	g_signal_connect (ctx->priv->session, "sign-data",
+			  G_CALLBACK (session_sign_data), ctx);
 	soup_session_add_filter (ctx->priv->session,
 				 SOUP_MESSAGE_FILTER (ctx));
+	g_free (authmech);
+}
 
-	ctx->priv->async_session = soup_session_async_new_with_options (
-		SOUP_SESSION_USE_NTLM, !authmech || !strcmp (authmech, "NTLM"),
-		SOUP_SESSION_PROXY_URI, uri, NULL);
-	g_signal_connect (ctx->priv->async_session, "authenticate",
-			  G_CALLBACK (session_authenticate), ctx);
-	soup_session_add_filter (ctx->priv->async_session,
-				 SOUP_MESSAGE_FILTER (ctx));
+static char *
+auth_creds_http_auth_method (E2kCreds *e2k_creds)
+{
+	E2kAuthCreds *creds = (E2kAuthCreds *)e2k_creds;
+	return creds->authmech ? g_strdup (creds->authmech) : NULL;
+}
+
+static void
+auth_creds_http_authenticate (E2kCreds *e2k_creds,
+			      const char *auth_type, const char *auth_realm,
+			      char **username, char **password)
+{
+	E2kAuthCreds *creds = (E2kAuthCreds *)e2k_creds;
+	*username = g_strdup (creds->username);
+	*password = g_strdup (creds->password);
+}
+
+/**
+ * e2k_context_set_auth:
+ * @ctx: the context
+ * @username: the Windows username (not including domain) of the user
+ * @domain: the NT domain, or %NULL to use the default (if using NTLM)
+ * @authmech: the HTTP Authorization type to use; either "Basic" or "NTLM"
+ * @password: the user's password
+ *
+ * Sets the authentication information on @ctx. This will have the
+ * side effect of cancelling any pending requests on @ctx.
+ **/
+void
+e2k_context_set_auth (E2kContext *ctx, const char *username,
+		      const char *domain, const char *authmech,
+		      const char *password)
+{
+	E2kAuthCreds *creds;
+
+	g_return_if_fail (E2K_IS_CONTEXT (ctx));
+
+	creds = g_new0 (E2kAuthCreds, 1);
+	if (username) {
+		if (domain) {
+			creds->username =
+				g_strdup_printf ("%s\\%s", domain, username);
+		} else
+			creds->username = g_strdup (username);
+	}
+
+	if (authmech) {
+		creds->authmech = g_strdup (authmech);
+	}
+
+	if (password) {
+		creds->password = g_strdup (password);
+	}
+
+	creds->creds.http_auth_method = auth_creds_http_auth_method;
+	creds->creds.http_authenticate = auth_creds_http_authenticate;
+
+	e2k_context_set_creds (ctx, &creds->creds);
+	/* we can't set this before because release_creds would then
+	 * free it */
+	ctx->priv->free_creds = TRUE;
 }
 
 /**
@@ -594,6 +718,8 @@ e2k_context_fba (E2kContext *ctx, SoupMe
 	SoupMessage *post_msg;
 	GString *form_body, *cookie_str;
 	const GSList *cookies, *c;
+	char *username = NULL;
+	char *password = NULL;
 
 	g_return_val_if_fail (E2K_IS_CONTEXT (ctx), FALSE);
 
@@ -612,7 +738,7 @@ e2k_context_fba (E2kContext *ctx, SoupMe
 		/* Otherwise, it's just expired. */
 	}
 
-	if (!ctx->priv->username || !ctx->priv->password)
+	if (!ctx->priv->creds || !ctx->priv->creds->http_authenticate)
 		return FALSE;
 
 	in_fba_auth = TRUE;
@@ -652,6 +778,15 @@ e2k_context_fba (E2kContext *ctx, SoupMe
 		action = g_strdup (value);
 	xmlFree (value);
 
+	/* we already checked this above */
+	ctx->priv->creds->http_authenticate (ctx->priv->creds,
+					     "", "", /* fake these... */
+					     &username, &password);
+
+	if (!username || !password) {
+		goto failed;
+	}
+
 	form_body = g_string_new (NULL);
 	while ((node = e2k_xml_find (node, "input"))) {
 		name = xmlGetProp (node, "name");
@@ -670,11 +805,11 @@ e2k_context_fba (E2kContext *ctx, SoupMe
 			g_string_append_c (form_body, '&');
 		} else if (!g_ascii_strcasecmp (name, "username")) {
 			g_string_append (form_body, "username=");
-			e2k_uri_append_encoded (form_body, ctx->priv->username, FALSE, NULL);
+			e2k_uri_append_encoded (form_body, username, FALSE, NULL);
 			g_string_append_c (form_body, '&');
 		} else if (!g_ascii_strcasecmp (name, "password")) {
 			g_string_append (form_body, "password=");
-			e2k_uri_append_encoded (form_body, ctx->priv->password, FALSE, NULL);
+			e2k_uri_append_encoded (form_body, password, FALSE, NULL);
 			g_string_append_c (form_body, '&');
 		}
 
@@ -682,6 +817,12 @@ e2k_context_fba (E2kContext *ctx, SoupMe
 			xmlFree (value);
 		xmlFree (name);
 	}
+	g_free (username);
+	username = NULL;
+
+	g_free (password);
+	password = NULL;
+
 	g_string_append_printf (form_body, "trusted=%d", E2K_FBA_FLAG_TRUSTED);
 	xmlFreeDoc (doc);
 	doc = NULL;
@@ -731,6 +872,8 @@ e2k_context_fba (E2kContext *ctx, SoupMe
 	in_fba_auth = FALSE;
 	if (doc)
 		xmlFreeDoc (doc);
+	g_free (username);
+	g_free (password);
 	return FALSE;
 }
 
@@ -886,7 +1029,7 @@ e2k_context_queue_message (E2kContext *c
 {
 	g_return_if_fail (E2K_IS_CONTEXT (ctx));
 
-	soup_session_queue_message (ctx->priv->async_session, msg,
+	soup_session_queue_message (ctx->priv->session, msg,
 				    callback, user_data);
 }
 
diff -ruNp evolution-data-server-1.8.2.orig/servers/exchange/lib/e2k-context.h evolution-data-server-1.8.2/servers/exchange/lib/e2k-context.h
--- evolution-data-server-1.8.2.orig/servers/exchange/lib/e2k-context.h	2005-06-10 06:51:08.000000000 -0400
+++ evolution-data-server-1.8.2/servers/exchange/lib/e2k-context.h	2007-04-18 15:16:13.000000000 -0400
@@ -9,6 +9,8 @@
 
 #include <glib-object.h>
 
+#include <gnutls/gnutls.h>
+
 #include "e2k-types.h"
 #include "e2k-operation.h"
 #include "e2k-http-utils.h"
@@ -47,6 +49,25 @@ void           e2k_context_set_auth     
 					     const char  *domain,
 					     const char  *authmech,
 					     const char  *password);
+struct _E2kCreds {
+	char *(*http_auth_method) (E2kCreds *creds);
+	void (*http_authenticate) (E2kCreds *creds,
+				   const char *auth_type, const char *auth_realm,
+				   char **username, char **password);
+	int (*ssl_cert_request) (E2kCreds *creds,
+				 const gnutls_datum_t *req_ca_rdn_der,
+				 int nreqs,
+				 gnutls_datum_t **cert_der_ret,
+				 int *cert_der_ret_length);
+	int (*ssl_cert_sign) (E2kCreds *creds,
+			      const gnutls_datum_t *cert,
+			      const gnutls_datum_t *hash_data,
+			      gnutls_datum_t *sig_data);
+};
+
+void           e2k_context_set_creds        (E2kContext *ctx,
+					     E2kCreds   *creds);
+
 gboolean       e2k_context_fba              (E2kContext  *ctx,
 					     SoupMessage *failed_msg);
 
diff -ruNp evolution-data-server-1.8.2.orig/servers/exchange/lib/e2k-types.h evolution-data-server-1.8.2/servers/exchange/lib/e2k-types.h
--- evolution-data-server-1.8.2.orig/servers/exchange/lib/e2k-types.h	2005-06-10 06:51:08.000000000 -0400
+++ evolution-data-server-1.8.2/servers/exchange/lib/e2k-types.h	2007-04-18 15:16:13.000000000 -0400
@@ -14,6 +14,7 @@ typedef struct _E2kAddrList             
 typedef struct _E2kContext                    E2kContext;
 typedef struct _E2kContextPrivate             E2kContextPrivate;
 typedef struct _E2kContextClass               E2kContextClass;
+typedef struct _E2kCreds                      E2kCreds;
 
 typedef struct _E2kGlobalCatalog              E2kGlobalCatalog;
 typedef struct _E2kGlobalCatalogPrivate       E2kGlobalCatalogPrivate;
diff -ruNp evolution-data-server-1.8.2.orig/servers/exchange/storage/exchange-account.c evolution-data-server-1.8.2/servers/exchange/storage/exchange-account.c
--- evolution-data-server-1.8.2.orig/servers/exchange/storage/exchange-account.c	2007-04-18 15:15:49.000000000 -0400
+++ evolution-data-server-1.8.2/servers/exchange/storage/exchange-account.c	2007-04-18 15:16:13.000000000 -0400
@@ -40,6 +40,9 @@
 #include "e2k-utils.h"
 #include "exchange-hierarchy-foreign.h"
 
+#include <sys/types.h>
+#include <unistd.h>
+
 /* This is an ugly hack to avoid API break */
 /* Added for get_authtype */
 #include "exchange-esource.h"
@@ -54,11 +57,23 @@
 #include <stdlib.h>
 #include <string.h>
 
-#define d(x)
+#define TRACE(s, ...) d(fprintf (stderr, "%d:%s:%s():%d "s"\n", getpid(), __FILE__, __PRETTY_FUNCTION__, __LINE__, __VA_ARGS__))
+#define TRACEMSG(s) TRACE("%s", (s))
+#define ENTER TRACEMSG("ENTER")
+#define EXIT TRACEMSG("EXIT")
+#define HASLOCK TRACEMSG("HAS LOCK")
+#define ALREADYLOCKED TRACEMSG("ALREADY LOCKED")
+
+#define d(x) x
 #define ADS_UF_DONT_EXPIRE_PASSWORD 0x10000
 #define ONE_HUNDRED_NANOSECOND 0.000000100
 #define SECONDS_IN_DAY 86400
 
+typedef struct {
+	E2kCreds creds;
+	ExchangeAccount *account;
+} AccountCreds;
+
 struct _ExchangeAccountPrivate {
 	E2kContext *ctx;
 	E2kGlobalCatalog *gc;
@@ -87,6 +102,10 @@ struct _ExchangeAccountPrivate {
 
 	GMutex *discover_data_lock;
 	GList *discover_datas;
+
+	AccountCreds creds;
+	GMutex *creds_mutex;
+	GSList *creds_list;
 };
 
 enum {
@@ -230,6 +249,13 @@ dispose (GObject *object)
 		account->priv->fresh_folders = NULL;
 	}
 
+	if (account->priv->creds_mutex) {
+		g_mutex_free (account->priv->creds_mutex);
+		account->priv->creds_mutex = NULL;
+	}
+	g_slist_free (account->priv->creds_list);
+	account->priv->creds_list = NULL;
+
 	G_OBJECT_CLASS (parent_class)->dispose (object);
 }
 
@@ -1168,14 +1194,21 @@ exchange_account_set_offline (ExchangeAc
 		
 	g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account), FALSE);
 
-	g_mutex_lock (account->priv->connect_lock);
-	if (account->priv->ctx) {
-		g_object_unref (account->priv->ctx);
-		account->priv->ctx = NULL;
-	}
+	ENTER;
 
-	account->priv->account_online = OFFLINE_MODE;
-	g_mutex_unlock (account->priv->connect_lock);
+	if (g_mutex_trylock (account->priv->connect_lock)) {
+		HASLOCK;
+		if (account->priv->ctx) {
+			g_object_unref (account->priv->ctx);
+			account->priv->ctx = NULL;
+		}
+
+		account->priv->account_online = OFFLINE_MODE;
+		g_mutex_unlock (account->priv->connect_lock);
+	} else {
+		ALREADYLOCKED;
+	}
+	EXIT;
 	return TRUE;
 }
 
@@ -1194,11 +1227,15 @@ gboolean
 exchange_account_set_online (ExchangeAccount *account)
 {
 	g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account), FALSE);
-
-	g_mutex_lock (account->priv->connect_lock);
-	account->priv->account_online = ONLINE_MODE;
-	g_mutex_unlock (account->priv->connect_lock);
-	
+	ENTER;
+	if (g_mutex_trylock (account->priv->connect_lock)) {
+		HASLOCK;
+		account->priv->account_online = ONLINE_MODE;
+		g_mutex_unlock (account->priv->connect_lock);
+	} else {
+		ALREADYLOCKED;
+	}
+	EXIT;
 	return TRUE;
 }
 
@@ -1341,6 +1378,117 @@ hierarchies_created:
 	return TRUE;
 }
 
+/* we are just a patsy */
+static char *
+account_creds_http_auth_method (E2kCreds *ecreds)
+{
+	AccountCreds *creds = (AccountCreds *)ecreds;
+	ExchangeAccount *account = creds->account;
+	E2kCreds *sub_creds;
+	char *method;
+
+	g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account), NULL);
+
+	g_mutex_lock (account->priv->creds_mutex);
+	sub_creds = g_slist_nth_data (account->priv->creds_list, 1);
+	method = sub_creds ? sub_creds->http_auth_method (sub_creds) : NULL;
+	g_mutex_unlock (account->priv->creds_mutex);
+
+	return method;
+}
+
+static void
+account_creds_http_authenticate (E2kCreds *ecreds,
+			   const char *auth_type, const char *auth_realm,
+			   char **username, char **password)
+{
+	AccountCreds *creds = (AccountCreds *)ecreds;
+	ExchangeAccount *account = creds->account;
+	E2kCreds *sub_creds;
+
+	g_return_if_fail (EXCHANGE_IS_ACCOUNT (account));
+
+	g_mutex_lock (account->priv->creds_mutex);
+	sub_creds = g_slist_nth_data (account->priv->creds_list, 1);
+	if (sub_creds) {
+		sub_creds->http_authenticate (sub_creds, auth_type, auth_realm, username, password);
+	}
+	g_mutex_unlock (account->priv->creds_mutex);
+}
+
+static int
+account_creds_ssl_cert_request (E2kCreds *ecreds,
+				const gnutls_datum_t *req_ca_rdn_der,
+				int nreqs,
+				gnutls_datum_t **cert_der_ret,
+				int *cert_der_ret_length)
+{
+	AccountCreds *creds = (AccountCreds *)ecreds;
+	ExchangeAccount *account = creds->account;
+	E2kCreds *sub_creds;
+	int ret = 0;
+	ENTER;
+	g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account), -1);
+
+	g_mutex_lock (account->priv->creds_mutex);
+	HASLOCK;
+	sub_creds = g_slist_nth_data (account->priv->creds_list, 0);
+	if (sub_creds) {
+		TRACEMSG("delegating cert request...");
+		sub_creds->ssl_cert_request (sub_creds,
+					     req_ca_rdn_der, nreqs,
+					     cert_der_ret, cert_der_ret_length);
+	}
+	g_mutex_unlock (account->priv->creds_mutex);
+	EXIT;
+	return ret;
+}
+
+static int
+account_creds_ssl_cert_sign (E2kCreds *ecreds,
+			     const gnutls_datum_t *cert_der,
+			     const gnutls_datum_t *hash_data,
+			     gnutls_datum_t *sig_data)
+{
+	AccountCreds *creds = (AccountCreds *)ecreds;
+	ExchangeAccount *account = creds->account;
+	E2kCreds *sub_creds;
+	int ret = 0;
+
+	g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account), -1);
+
+	g_mutex_lock (account->priv->creds_mutex);
+	sub_creds = g_slist_nth_data (account->priv->creds_list, 0);
+	if (sub_creds) {
+		ret = sub_creds->ssl_cert_sign (sub_creds,
+						cert_der,
+						hash_data, sig_data);
+	}
+	g_mutex_unlock (account->priv->creds_mutex);
+
+	return ret;
+}
+
+void
+exchange_account_add_creds (ExchangeAccount *account,
+			    E2kCreds        *creds)
+{
+	g_return_if_fail (EXCHANGE_IS_ACCOUNT (account));
+	g_mutex_lock (account->priv->creds_mutex);
+	account->priv->creds_list = g_slist_prepend (account->priv->creds_list, creds);
+	g_mutex_unlock (account->priv->creds_mutex);
+}
+
+void
+exchange_account_remove_creds (ExchangeAccount *account,
+			       E2kCreds        *creds)
+{
+	g_return_if_fail (EXCHANGE_IS_ACCOUNT (account));
+	g_mutex_lock (account->priv->creds_mutex);
+	account->priv->creds_list = g_slist_remove (account->priv->creds_list, creds);
+	g_mutex_unlock (account->priv->creds_mutex);
+}
+
 /**
  * exchange_account_connect:
  * @account: an #ExchangeAccount
@@ -1368,14 +1516,15 @@ exchange_account_connect (ExchangeAccoun
 	E2kGlobalCatalogEntry *entry;
 	E2kOperation gcop;
 	char *user_name = NULL;
-
+	ENTER;
 	*info_result = EXCHANGE_ACCOUNT_UNKNOWN_ERROR; 
 	g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account), NULL);
 
 	*info_result = EXCHANGE_ACCOUNT_CONNECT_SUCCESS;
-	exchange_account_is_offline (account, &mode);
 
 	g_mutex_lock (account->priv->connect_lock);
+	HASLOCK;
+	exchange_account_is_offline (account, &mode);
 
 	if (account->priv->connecting || mode == OFFLINE_MODE) {
 		g_mutex_unlock (account->priv->connect_lock);
@@ -1386,10 +1535,17 @@ exchange_account_connect (ExchangeAccoun
 		else {
 			*info_result = EXCHANGE_ACCOUNT_CONNECT_ERROR;
 		}
+		EXIT;
 		return NULL;
 	} else if (account->priv->ctx) {
 		g_mutex_unlock (account->priv->connect_lock);
+		EXIT;
 		return account->priv->ctx;
+	} else if (!pword && !account->priv->creds_list) {
+		g_mutex_unlock (account->priv->connect_lock);
+		*info_result = EXCHANGE_ACCOUNT_PASSWORD_INCORRECT;
+		EXIT;
+		return NULL;
 	}
 
 	account->priv->connecting = TRUE;
@@ -1401,7 +1557,7 @@ exchange_account_connect (ExchangeAccoun
 
 	ac = e2k_autoconfig_new (account->home_uri,
 				 user_name,
-				 NULL,
+				 pword,
 				 account->priv->auth_pref);
 	g_free (user_name);
 
@@ -1409,15 +1565,10 @@ exchange_account_connect (ExchangeAccoun
 				      account->priv->ad_limit);
 
 	if (!pword) {
-		account->priv->connecting = FALSE;
-		g_mutex_unlock (account->priv->connect_lock);
-		*info_result = EXCHANGE_ACCOUNT_PASSWORD_INCORRECT;
-		e2k_autoconfig_free (ac);
-		return NULL;
+		TRACEMSG("setting creds...");
+		e2k_autoconfig_set_creds (ac, &account->priv->creds.creds);
 	}
 
-	e2k_autoconfig_set_password (ac, pword);
-
  try_connect_again:
 	account->priv->ctx = e2k_autoconfig_get_context (ac, NULL, &result);
 
@@ -1427,12 +1578,14 @@ exchange_account_connect (ExchangeAccoun
 		account->priv->nt_domain = NULL;
 
 	if (result != E2K_AUTOCONFIG_OK) {
+		TRACE("result was not ok: %d", result);
 #ifdef HAVE_KRB5
 		if ( is_password_expired (account, ac)) {
 			*info_result = EXCHANGE_ACCOUNT_PASSWORD_EXPIRED;
 			account->priv->connecting = FALSE;
 			g_mutex_unlock (account->priv->connect_lock);
 			e2k_autoconfig_free (ac);
+			EXIT;
 			return NULL;
 		}
 #endif
@@ -1443,6 +1596,7 @@ exchange_account_connect (ExchangeAccoun
 			e2k_autoconfig_free (ac);
 			account->priv->connecting = FALSE;
 			g_mutex_unlock (account->priv->connect_lock);
+			EXIT;
 			return NULL;
 
 		case E2K_AUTOCONFIG_AUTH_ERROR_TRY_DOMAIN:
@@ -1450,6 +1604,7 @@ exchange_account_connect (ExchangeAccoun
 			e2k_autoconfig_free (ac);
 			account->priv->connecting = FALSE;
 			g_mutex_unlock (account->priv->connect_lock);
+			EXIT;
 			return NULL;
 
 		case E2K_AUTOCONFIG_AUTH_ERROR_TRY_NTLM:
@@ -1507,6 +1662,7 @@ exchange_account_connect (ExchangeAccoun
 		}
 
 		g_mutex_unlock (account->priv->connect_lock);
+		EXIT;
 		return NULL;
 	}
 
@@ -1523,6 +1679,7 @@ exchange_account_connect (ExchangeAccoun
 		account->priv->connecting = FALSE;
 		*info_result = EXCHANGE_ACCOUNT_UNKNOWN_ERROR;
 		g_mutex_unlock (account->priv->connect_lock);
+		EXIT;
 		return NULL; /* FIXME: what error has happened? */
 	}
 
@@ -1547,6 +1704,7 @@ exchange_account_connect (ExchangeAccoun
 		g_mutex_unlock (account->priv->connect_lock);
 		if (nresults)
 			e2k_results_free (results, nresults);
+		EXIT;
 		return NULL; /* FIXME: what error has happened? */
 	}
 
@@ -1592,6 +1750,7 @@ skip_quota:
 	g_mutex_unlock (account->priv->connect_lock);
 	if (nresults)
 		e2k_results_free (results, nresults);
+	EXIT;
 	return account->priv->ctx;
 }
 
@@ -2139,5 +2298,13 @@ exchange_account_new (EAccountList *acco
 
 	e2k_uri_free (uri);
 
+	account->priv->creds.creds.http_auth_method = account_creds_http_auth_method;
+	account->priv->creds.creds.http_authenticate = account_creds_http_authenticate;
+	account->priv->creds.creds.ssl_cert_request = account_creds_ssl_cert_request;
+	account->priv->creds.creds.ssl_cert_sign = account_creds_ssl_cert_sign;
+	account->priv->creds.account = account;
+
+	account->priv->creds_mutex = g_mutex_new ();
+
 	return account;
 }
diff -ruNp evolution-data-server-1.8.2.orig/servers/exchange/storage/exchange-account.h evolution-data-server-1.8.2/servers/exchange/storage/exchange-account.h
--- evolution-data-server-1.8.2.orig/servers/exchange/storage/exchange-account.h	2006-07-22 05:05:22.000000000 -0400
+++ evolution-data-server-1.8.2/servers/exchange/storage/exchange-account.h	2007-04-18 15:16:13.000000000 -0400
@@ -92,6 +92,11 @@ char                  *exchange_account_
 
 char 		      *exchange_account_get_authtype 	     (ExchangeAccount *account);
 
+void                   exchange_account_add_creds            (ExchangeAccount *acct,
+							      E2kCreds        *creds);
+void                   exchange_account_remove_creds         (ExchangeAccount *acct,
+							      E2kCreds        *creds);
+
 E2kContext            *exchange_account_connect              (ExchangeAccount  *acct,
 							      const char *pword,
 							      ExchangeAccountResult *result);
