diff --git a/src/server/e-soup-auth-negotiate.c b/src/server/e-soup-auth-negotiate.c
index a0ed8fe..6d92391 100644
--- a/src/server/e-soup-auth-negotiate.c
+++ b/src/server/e-soup-auth-negotiate.c
@@ -26,6 +26,8 @@
 #include <libsoup/soup.h>
 #include "e-soup-auth-negotiate.h"
 
+#include <gssapi/gssapi.h>
+
 /*
  * The following set of functions hacks in Negotiate/GSSAPI support for EWS.
  * Ideally, libsoup should provide the support already.  Unfortunately, it
@@ -44,7 +46,8 @@
  */
 
 typedef struct {
-	CamelSasl *gssapi_sasl;
+	gss_name_t target_name;
+	gss_ctx_id_t gss_context;
 	gchar *token;
 	gchar *challenge;
 	gint  auth_started;
@@ -53,52 +56,6 @@ typedef struct {
 
 static GHashTable *msgs_table;
 
-static gchar *
-e_soup_auth_negotiate_gssapi_challenge (CamelSasl *sasl, const gchar *what,
-					gboolean is_base64, GError **error)
-{
-	GByteArray *ain, *aout = NULL;
-	gchar *response = NULL;
-	GError *local_error = NULL;
-
-	g_return_val_if_fail (sasl != NULL, NULL);
-
-	ain = g_byte_array_new ();
-
-	if (what && *what) {
-		if (is_base64) {
-			guchar *bytes;
-			gsize len = 0;
-
-			bytes = g_base64_decode (what, &len);
-			if (bytes) {
-				g_byte_array_append (ain, bytes, len);
-				g_free (bytes);
-			}
-		} else {
-			g_byte_array_append (ain, (const guchar *) what,
-					     strlen (what));
-		}
-	}
-
-	aout = camel_sasl_challenge_sync (sasl, ain, NULL, &local_error);
-
-	if (local_error) {
-		g_propagate_error (error, local_error);
-	} else if (aout && aout->len) {
-		response = g_base64_encode (aout->data, aout->len);
-	} else {
-		response = g_strdup ("");
-	}
-
-	g_byte_array_unref (ain);
-
-	if (aout)
-		g_byte_array_unref (aout);
-
-	return response;
-}
-
 static gboolean e_soup_auth_negotiate_update (SoupAuth *auth, SoupMessage *msg,
 					      GHashTable *auth_params);
 static gboolean e_soup_auth_negotiate_is_ready (SoupAuth *auth,
@@ -110,14 +67,18 @@ static void
 e_soup_auth_negotiate_delete_context (SoupMessage *msg, gpointer user_data)
 {
 	SoupMessageState *state = g_hash_table_lookup (msgs_table, msg);
+	OM_uint32 minor;
 
 	g_hash_table_remove (msgs_table, msg);
 	g_signal_handlers_disconnect_by_func (
 		msg, G_CALLBACK (e_soup_auth_negotiate_message_finished),
 		user_data);
 
-	if (state->auth_started)
-		g_object_unref (state->gssapi_sasl);
+	if (state->target_name != GSS_C_NO_NAME)
+		gss_release_name (&minor, &state->target_name);
+	if (state->gss_context != GSS_C_NO_CONTEXT)
+		gss_delete_sec_context (&minor, &state->gss_context,
+					GSS_C_NO_BUFFER);
 	g_free (state->token);
 	g_free (state->challenge);
 	g_slice_free (SoupMessageState, state);
@@ -151,6 +112,8 @@ e_soup_auth_negotiate_get_message_state (SoupMessage *msg, SoupAuth *auth)
 			msg, "finished",
 			G_CALLBACK (e_soup_auth_negotiate_message_finished),
 			auth);
+		state->target_name = GSS_C_NO_NAME;
+		state->gss_context = GSS_C_NO_CONTEXT;
 	}
 
 	return state;
@@ -229,9 +192,51 @@ e_soup_auth_negotiate_get_protection_space (SoupAuth *auth, SoupURI *source_uri)
 }
 
 static gboolean
+set_msg_gss_error (SoupMessage *msg, const gchar *where, OM_uint32 err_maj,
+		   OM_uint32 err_min)
+{
+        OM_uint32 major, minor, msg_ctx = 0;
+        gss_buffer_desc status;
+	GString *str = g_string_new(where);
+
+	do {
+                major = gss_display_status(&minor, err_maj, GSS_C_GSS_CODE,
+                                           GSS_C_NO_OID, &msg_ctx, &status);
+                if (GSS_ERROR(major))
+                        break;
+                g_string_append_printf(str, ": %s", (gchar *)status.value);
+                gss_release_buffer(&minor, &status);
+
+                major = gss_display_status(&minor, err_min, GSS_C_MECH_CODE,
+                                           GSS_C_NO_OID, &msg_ctx, &status);
+                if (GSS_ERROR(major))
+                        break;
+		g_string_append_printf(str, ": %s", (gchar *)status.value);
+                gss_release_buffer(&minor, &status);
+
+        } while (msg_ctx);
+
+	soup_message_set_status_full (msg, SOUP_STATUS_BAD_REQUEST,
+				      str->str);
+	g_string_free (str, TRUE);
+
+	return FALSE;
+}
+
+static const char spnego_OID[] = "\x2b\x06\x01\x05\x05\x02";
+static const gss_OID_desc gss_mech_spnego = {
+        6,
+        &spnego_OID
+};
+
+static gboolean
 e_soup_auth_negotiate_is_ready (SoupAuth *auth, SoupMessage *msg)
 {
 	SoupMessageState *state;
+	gss_buffer_desc in = GSS_C_EMPTY_BUFFER;
+	gss_buffer_desc out = GSS_C_EMPTY_BUFFER;
+	OM_uint32 major, minor;
+	gsize toklen;
 
 	/*
 	 * Here we finally update the token and then inform the auth manager
@@ -241,53 +246,52 @@ e_soup_auth_negotiate_is_ready (SoupAuth *auth, SoupMessage *msg)
 	state = e_soup_auth_negotiate_get_message_state (msg, auth);
 
 	if (state->challenge_available) {
-		GError *error = NULL;
 
 		if (!state->auth_started) {
-			CamelSasl *gssapi_sasl;
+			gss_buffer_desc namebuf;
 			SoupURI *soup_uri;
 			char const *host;
 
-			gssapi_sasl = g_object_new (
-				camel_sasl_gssapi_get_type (),
-				"mechanism", "GSSAPI",
-				"service-name", "HTTP",
-				NULL);
-
 			soup_uri = soup_message_get_uri (msg);
 			host = soup_uri_get_host (soup_uri);
 
-			/* We are required to pass a username, but it doesn't
-			   ever get used since we're not actually doing SASL
-			   here. So "" is fine. */
-			camel_sasl_gssapi_override_host_and_user (
-				CAMEL_SASL_GSSAPI (gssapi_sasl), host, "");
+			namebuf.value = g_strdup_printf("HTTP@%s", host);
+			namebuf.length = strlen(namebuf.value);
+
+			major = gss_import_name (&minor, &namebuf,
+						 (gss_OID)GSS_C_NT_HOSTBASED_SERVICE,
+						 &state->target_name);
+			if (GSS_ERROR(major))
+				return set_msg_gss_error (msg, "gss_import_name", major, minor);
 
-			state->gssapi_sasl = gssapi_sasl;
+			free (namebuf.value);
 
 			state->auth_started = TRUE;
 		}
 
-		g_free (state->token);
-		state->token = e_soup_auth_negotiate_gssapi_challenge (
-				state->gssapi_sasl,
-				state->challenge ? state->challenge : "\r\n",
-				state->challenge != NULL,
-				&error);
-
-		g_free (state->challenge);
-		state->challenge = NULL;
+		if (state->challenge) {
+			in.value = g_base64_decode (state->challenge, &toklen);
+			in.length = toklen;
+		}
+
 		state->challenge_available = FALSE;
 
-		if (error) {
-			/* cannot use SOUP_STATUS_UNAUTHORIZED, because it may hide an
-			 * error message, which is a local error of Kerberos/GSSAPI
-			 * call
-			 */
-			soup_message_set_status_full (
-				msg, SOUP_STATUS_BAD_REQUEST, error->message);
-			return FALSE;
-		}
+		major = gss_init_sec_context (&minor, GSS_C_NO_CREDENTIAL, &state->gss_context,
+					      state->target_name, (gss_OID)&gss_mech_spnego,
+					      GSS_C_MUTUAL_FLAG, GSS_C_INDEFINITE,
+					      GSS_C_NO_CHANNEL_BINDINGS, &in, NULL, &out,
+					      NULL, NULL);
+		g_free (in.value);
+		if (major != GSS_S_COMPLETE && major != GSS_S_CONTINUE_NEEDED)
+			return set_msg_gss_error (msg, "gss_init_sec_context", major, minor);
+
+		g_free (state->token);
+		if (out.length)
+			state->token = g_base64_encode (out.value, out.length);
+		else
+			state->token = NULL;
+
+		gss_release_buffer (&minor, &out);
 	}
 
 	if (state->token != NULL)
