diff --git a/configure.ac b/configure.ac
index 96817ec..063e14d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -326,6 +326,19 @@ AM_CONDITIONAL(HAVE_CURL, test "$CURL" != no)
 AC_SUBST(MISSING_REGRESSION_TEST_PACKAGES)
 AM_CONDITIONAL(MISSING_REGRESSION_TEST_PACKAGES, test -n "$MISSING_REGRESSION_TEST_PACKAGES")
 
+dnl ***********************************************
+dnl *** Check NTLM single-sign-on helper ntlm_auth
+dnl ***********************************************
+AC_PATH_PROG(NTLM_AUTH, ntlm_auth, no)
+AC_SUBST(NTLM_AUTH)
+AC_DEFINE_UNQUOTED(NTLM_AUTH, "$NTLM_AUTH", [Samba's 'winbind' daemon helper 'ntlm_auth' which can be used for NTLM single-sign-on])
+if test "$NTLM_AUTH" != no; then
+    AC_DEFINE(HAVE_NTLM_AUTH, 1, [Whether or not Samba's 'winbind' daemon helper 'ntlm_auth' is installed])
+    AC_MSG_NOTICE([use Samba's 'winbind' daemon for NTLM single-sign-on: $NTLM_AUTH])
+else
+    AC_DEFINE(HAVE_NTLM_AUTH, 0, [Whether or not Samba's 'winbind' daemon helper 'ntlm_auth' is installed])
+fi
+
 dnl *************************
 dnl *** Output Everything ***
 dnl *************************
diff --git a/libsoup/soup-auth-manager-ntlm.c b/libsoup/soup-auth-manager-ntlm.c
index 49db613..06e004a 100644
--- a/libsoup/soup-auth-manager-ntlm.c
+++ b/libsoup/soup-auth-manager-ntlm.c
@@ -12,6 +12,11 @@
 
 #include <ctype.h>
 #include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <errno.h>
 
 #include "soup-auth-manager-ntlm.h"
 #include "soup-auth-ntlm.h"
@@ -42,6 +47,10 @@ G_DEFINE_TYPE_WITH_CODE (SoupAuthManagerNTLM, soup_auth_manager_ntlm, SOUP_TYPE_
 
 typedef enum {
 	SOUP_NTLM_NEW,
+	SOUP_NTLM_SENT_SSO_REQUEST,
+	SOUP_NTLM_RECEIVED_SSO_CHALLENGE,
+	SOUP_NTLM_SENT_SSO_RESPONSE,
+	SOUP_NTLM_SSO_FAILED,
 	SOUP_NTLM_SENT_REQUEST,
 	SOUP_NTLM_RECEIVED_CHALLENGE,
 	SOUP_NTLM_SENT_RESPONSE,
@@ -49,12 +58,21 @@ typedef enum {
 } SoupNTLMState;
 
 typedef struct {
+	gint fd_in;
+	gint fd_out;
+	GPid pid;
+} NTLMHelper;
+
+typedef struct {
 	SoupSocket *socket;
 	SoupNTLMState state;
 	char *response_header;
+	char *challenge_header;
 
 	char *nonce, *domain;
 	SoupAuth *auth;
+
+	NTLMHelper *sso_data;
 } SoupNTLMConnection;
 
 typedef struct {
@@ -75,6 +93,7 @@ static char     *soup_ntlm_response        (const char  *nonce,
 					    const char  *password,
 					    const char  *host, 
 					    const char  *domain);
+static void sso_ntlm_close (NTLMHelper *sso_data);
 
 static void
 soup_auth_manager_ntlm_init (SoupAuthManagerNTLM *ntlm)
@@ -90,10 +109,15 @@ static void
 free_ntlm_connection (SoupNTLMConnection *conn)
 {
 	g_free (conn->response_header);
+	g_free (conn->challenge_header);
 	g_free (conn->nonce);
 	g_free (conn->domain);
 	if (conn->auth)
 		g_object_unref (conn->auth);
+	if (conn->sso_data) {
+		sso_ntlm_close (conn->sso_data);
+		g_slice_free (NTLMHelper, conn->sso_data);
+	}
 	g_slice_free (SoupNTLMConnection, conn);
 }
 
@@ -180,6 +204,10 @@ get_connection (SoupAuthManagerNTLMPrivate *priv, SoupSocket *socket)
 	conn = g_slice_new0 (SoupNTLMConnection);
 	conn->socket = socket;
 	conn->state = SOUP_NTLM_NEW;
+	conn->sso_data = g_slice_new0 (NTLMHelper);
+	conn->sso_data->fd_in = -1;
+	conn->sso_data->fd_out = -1;
+	conn->sso_data->pid = 0;
 	g_hash_table_insert (priv->connections_by_id, socket, conn);
 
 	g_signal_connect (socket, "disconnected",
@@ -218,6 +246,154 @@ get_connection_for_msg (SoupAuthManagerNTLMPrivate *priv, SoupMessage *msg)
 }
 
 static void
+sso_ntlm_close (NTLMHelper *sso_data)
+{
+	if (sso_data->fd_in != -1) {
+		close (sso_data->fd_in);
+		sso_data->fd_in = -1;
+	}
+
+	if (sso_data->fd_out != -1) {
+		close (sso_data->fd_out);
+		sso_data->fd_out = -1;
+	}
+
+	if (sso_data->pid) {
+		gint ret, i;
+		for (i = 0; i < 4; i++) {
+			ret = waitpid (sso_data->pid, NULL, WNOHANG);
+			if (ret == sso_data->pid || errno == ECHILD)
+				break;
+			switch (i) {
+			case 0:
+				kill (sso_data->pid, SIGTERM);
+				break;
+			case 2:
+				kill (sso_data->pid, SIGKILL);
+				break;
+			case 1:
+			case 3:
+				sleep (1);
+				break;
+			}
+		}
+		sso_data->pid = 0;
+	}
+}
+
+static void
+sso_child_watch (GPid pid, gint status, gpointer data)
+{
+	NTLMHelper *sso_data = data;
+
+	if (sso_data->fd_in != -1) {
+		close (sso_data->fd_in);
+		sso_data->fd_in = -1;
+	}
+
+	if (sso_data->fd_out != -1) {
+		close (sso_data->fd_out);
+		sso_data->fd_out = -1;
+	}
+
+	g_spawn_close_pid (sso_data->pid);
+	sso_data->pid = 0;
+}
+
+static gboolean
+sso_ntlm_initiate (NTLMHelper *sso_data)
+{
+	char *username = NULL, *slash, *domain = NULL;
+	char *argv[9];
+	gboolean ret;
+
+	/* Return if ntlm_auth execution process exist already */
+	if (sso_data->fd_in != -1 && sso_data->fd_out != -1 && sso_data->pid)
+		return TRUE;
+	else
+		/* Clean all sso data before re-initiate */
+		sso_ntlm_close (sso_data);
+
+	username = getenv ("NTLMUSER");
+	if (!username)
+		username = getenv ("USER");
+	if (!username)
+		goto done;
+
+	slash = strpbrk (username, "\\/");
+	if (slash) {
+		domain = g_strdup (username);
+		slash = domain + (slash - username);
+		*slash = '\0';
+		username = slash + 1;
+	}
+
+	if (access (NTLM_AUTH, X_OK))
+		goto done;
+
+	argv[0] = NTLM_AUTH;
+	argv[1] = "--helper-protocol";
+	argv[2] = "ntlmssp-client-1";
+	argv[3] = "--use-cached-creds";
+	argv[4] = "--username";
+	argv[5] = username;
+	argv[6] = domain ? "--domain" : NULL;
+	argv[7] = domain;
+	argv[8] = NULL;
+	/* Spawn child process */
+	ret = g_spawn_async_with_pipes (NULL, argv, NULL,
+					G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_FILE_AND_ARGV_ZERO,
+					NULL, NULL,
+					&sso_data->pid, &sso_data->fd_in, &sso_data->fd_out,
+					NULL, NULL);
+	if (!ret)
+		goto done;
+	/* Add watch function to catch termination of the process */
+	g_child_watch_add (sso_data->pid, (GChildWatchFunc) sso_child_watch, sso_data);
+
+	if (domain)
+		g_free (domain);
+	return TRUE;
+done:
+	if (domain)
+		g_free (domain);
+
+	return FALSE;
+}
+
+static char *
+sso_ntlm_response (NTLMHelper *sso_data, const char* input, SoupNTLMState conn_state)
+{
+	ssize_t size;
+	char buf[1024], *response = NULL;
+
+	if (write (sso_data->fd_in, input, strlen (input)) < 0 ||
+	    (size = read (sso_data->fd_out, buf, 1024)) < 5 ) {
+		goto done;
+	}
+	/* Samba/winbind installed but not configured */
+	if (conn_state == SOUP_NTLM_NEW &&
+	    buf[0] == 'P' && buf[1] == 'W' && buf[size-1] == '\n') {
+		response = g_strdup ("PW");
+		goto done;
+	}
+	/* invalid response */
+	if (conn_state == SOUP_NTLM_NEW &&
+	    (buf[0] != 'Y' || buf[1] != 'R' || buf[2] != ' ' || buf[size-1] != '\n'))
+		goto done;
+	if (conn_state == SOUP_NTLM_RECEIVED_SSO_CHALLENGE &&
+	    (buf[0] != 'K' || buf[1] != 'K' || buf[2] != ' ' || buf[size-1] != '\n'))
+		goto done;
+
+	response = g_strndup (buf + 3, size - 4);
+	*(response + size - 4) = '\0';
+	response = g_strconcat ("NTLM ", response, NULL);
+	goto done;
+done:
+	return response;
+}
+
+static void
 ntlm_authorize_pre (SoupMessage *msg, gpointer ntlm)
 {
 	SoupAuthManagerNTLMPrivate *priv =
@@ -250,11 +426,16 @@ ntlm_authorize_pre (SoupMessage *msg, gpointer ntlm)
 		goto done;
 	}
 
-	conn->state = SOUP_NTLM_RECEIVED_CHALLENGE;
+	conn->challenge_header = g_strdup (val + 5);
 	conn->auth = soup_auth_ntlm_new (conn->domain,
 					 soup_message_get_uri (msg)->host);
-	soup_auth_manager_emit_authenticate (SOUP_AUTH_MANAGER (ntlm), msg,
-					     conn->auth, FALSE);
+	if (conn->state == SOUP_NTLM_SENT_SSO_REQUEST)
+		conn->state = SOUP_NTLM_RECEIVED_SSO_CHALLENGE;
+	else {
+		conn->state = SOUP_NTLM_RECEIVED_CHALLENGE;
+		soup_auth_manager_emit_authenticate (SOUP_AUTH_MANAGER (ntlm), msg,
+						     conn->auth, FALSE);
+	}
 
  done:
 	/* Remove the WWW-Authenticate headers so the session won't try
@@ -276,25 +457,49 @@ ntlm_authorize_post (SoupMessage *msg, gpointer ntlm)
 	if (!conn || !conn->auth)
 		return;
 
-	username = soup_auth_ntlm_get_username (conn->auth);
-	password = soup_auth_ntlm_get_password (conn->auth);
-	if (!username || !password)
+	if (conn->state == SOUP_NTLM_RECEIVED_SSO_CHALLENGE) {
+		char *input;
+		input = g_strdup_printf ("TT %s\n", conn->challenge_header);
+		/* Re-Initiate ntlm_auth process in case it was closed/killed abnormally */
+		if (sso_ntlm_initiate (conn->sso_data)) {
+			conn->response_header = sso_ntlm_response (conn->sso_data,
+								   input,
+								   conn->state);
+			/* Close ntlm_auth as it is no longer needed for current connection */
+			sso_ntlm_close (conn->sso_data);
+			if (!conn->response_header) {
+				g_free (input);
+				goto ssofailure;
+			}
+			soup_session_requeue_message (priv->session, msg);
+			g_free (input);
+			goto done;
+		}
+ssofailure:
+		conn->state = SOUP_NTLM_SSO_FAILED;
+		soup_session_requeue_message (priv->session, msg);
 		goto done;
-
-	slash = strpbrk (username, "\\/");
-	if (slash) {
-		domain = g_strdup (username);
-		slash = domain + (slash - username);
-		*slash = '\0';
-		username = slash + 1;
-	} else
-		domain = conn->domain;
-
-	conn->response_header = soup_ntlm_response (conn->nonce,
-						    username, password,
-						    NULL, domain);
-	soup_session_requeue_message (priv->session, msg);
-
+	} else {
+		username = soup_auth_ntlm_get_username (conn->auth);
+		password = soup_auth_ntlm_get_password (conn->auth);
+
+		if (!username || !password)
+			goto done;
+
+		slash = strpbrk (username, "\\/");
+		if (slash) {
+			domain = g_strdup (username);
+			slash = domain + (slash - username);
+			*slash = '\0';
+			username = slash + 1;
+		} else
+			domain = conn->domain;
+
+		conn->response_header = soup_ntlm_response (conn->nonce,
+							    username, password,
+							    NULL, domain);
+		soup_session_requeue_message (priv->session, msg);
+	}
 done:
 	if (domain != conn->domain)
 		g_free (domain);
@@ -341,6 +546,44 @@ request_started (SoupSessionFeature *ntlm, SoupSession *session,
 
 	switch (conn->state) {
 	case SOUP_NTLM_NEW:
+		/* Use Samba's 'winbind' daemon to support NTLM single-sign-on,
+		 * by delegating the NTLM challenge/response protocal to a helper
+		 * in ntlm_auth.
+		 * http://www.samba.org/samba/docs/man/manpages-3/winbindd.8.html
+		 * http://www.samba.org/samba/docs/man/manpages-3/ntlm_auth.1.html
+		 * The preprocessor variable 'HAVE_NTLM_AUTH' indicates whether
+		 * it has been installed. Another one 'NTLM_AUTH' contains absolute
+		 * path of it.
+		 * If NTLM single-sign-on fails, go back to original request handling process.
+		 */
+		if (HAVE_NTLM_AUTH && sso_ntlm_initiate (conn->sso_data)) {
+			header = sso_ntlm_response (conn->sso_data, "YR\n", conn->state);
+			if (header) {
+				if (g_ascii_strcasecmp (header, "PW")) {
+					conn->state = SOUP_NTLM_SENT_SSO_REQUEST;
+					break;
+				} else {
+					g_free (header);
+					header = NULL;
+					goto ssofailure;
+				}
+			} else {
+				g_warning ("NTLM single-sign-on by using %s failed", NTLM_AUTH);
+				goto ssofailure;
+			}
+		}
+ssofailure:
+		header = soup_ntlm_request ();
+		conn->state = SOUP_NTLM_SENT_REQUEST;
+		break;
+	case SOUP_NTLM_RECEIVED_SSO_CHALLENGE:
+		header = conn->response_header;
+		conn->response_header = NULL;
+		conn->state = SOUP_NTLM_SENT_SSO_RESPONSE;
+		break;
+	case SOUP_NTLM_SSO_FAILED:
+		/* Restart request without SSO */
+		g_warning ("NTLM single-sign-on by using %s failed", NTLM_AUTH);
 		header = soup_ntlm_request ();
 		conn->state = SOUP_NTLM_SENT_REQUEST;
 		break;
