[libsoup] SoupAuthManagerNTLM: allow non-ASCII usernames/passwords



commit 67824e6224409f77fa397a0d6bb2eab5e6cc8081
Author: Dan Winship <danw gnome org>
Date:   Thu Oct 20 17:27:34 2011 -0400

    SoupAuthManagerNTLM: allow non-ASCII usernames/passwords
    
    Switch to using the Unicode-encoded form of NTLM, so that non-ASCII
    usernames/passwords will work.
    
    Also, add a "-n" option to tests/get to make it use NTLM, and make
    SoupAuthManagerNTLM allow passwords-in-URLs.
    
    Based on a patch from Joachim Breitner, sponsored by ITOMIG GmbH and
    the City of BÃblingen.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=576838

 libsoup/soup-auth-manager-ntlm.c |   46 ++++++++++++++++++++++++++-----------
 tests/get.c                      |   10 ++++++-
 tests/ntlm-test.c                |    2 +-
 3 files changed, 41 insertions(+), 17 deletions(-)
---
diff --git a/libsoup/soup-auth-manager-ntlm.c b/libsoup/soup-auth-manager-ntlm.c
index 7c3f239..a1b76c7 100644
--- a/libsoup/soup-auth-manager-ntlm.c
+++ b/libsoup/soup-auth-manager-ntlm.c
@@ -12,6 +12,7 @@
 
 #include <ctype.h>
 #include <string.h>
+#include <glib.h>
 
 #ifdef USE_NTLM_AUTH
 #include <stdlib.h>
@@ -387,6 +388,7 @@ ntlm_authorize_pre (SoupMessage *msg, gpointer ntlm)
 		SOUP_AUTH_MANAGER_NTLM_GET_PRIVATE (ntlm);
 	SoupNTLMConnection *conn;
 	const char *val;
+	SoupURI *uri;
 
 	conn = get_connection_for_msg (priv, msg);
 	if (!conn)
@@ -423,8 +425,14 @@ ntlm_authorize_pre (SoupMessage *msg, gpointer ntlm)
 	}
 #endif
 	conn->state = SOUP_NTLM_RECEIVED_CHALLENGE;
-	soup_auth_manager_emit_authenticate (SOUP_AUTH_MANAGER (ntlm), msg,
-					     conn->auth, FALSE);
+
+	uri = soup_message_get_uri (msg);
+	if (uri->password)
+		soup_auth_authenticate (conn->auth, uri->user, uri->password);
+	else {
+		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
@@ -725,7 +733,7 @@ typedef struct {
 #define NTLM_CHALLENGE_DOMAIN_STRING_OFFSET 12
 
 #define NTLM_RESPONSE_HEADER "NTLMSSP\x00\x03\x00\x00\x00"
-#define NTLM_RESPONSE_FLAGS 0x8202
+#define NTLM_RESPONSE_FLAGS 0x8201
 
 typedef struct {
         guchar     header[12];
@@ -751,7 +759,7 @@ ntlm_set_string (NTLMString *string, int *offset, int len)
 static char *
 soup_ntlm_request (void)
 {
-	return g_strdup ("NTLM TlRMTVNTUAABAAAABoIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAwAAAA");
+	return g_strdup ("NTLM TlRMTVNTUAABAAAABYIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAwAAAA");
 }
 
 static gboolean
@@ -783,7 +791,9 @@ soup_ntlm_parse_challenge (const char *challenge,
 			return FALSE;
 		}
 
-		*default_domain = g_strndup ((char *)chall + domain.offset, domain.length);
+		*default_domain = g_convert ((char *)chall + domain.offset,
+					     domain.length, "UTF-8", "UCS-2LE",
+					     NULL, NULL, NULL);
 	}
 
 	if (nonce) {
@@ -802,8 +812,10 @@ soup_ntlm_response (const char *nonce,
 		    const char *host, 
 		    const char *domain)
 {
-	int hlen, dlen, ulen, offset;
+	int offset;
+	gsize hlen, dlen, ulen;
 	guchar hash[21], lm_resp[24], nt_resp[24];
+	char *user_conv, *host_conv, *domain_conv;
 	NTLMResponse resp;
 	char *out, *p;
 	int state, save;
@@ -819,13 +831,15 @@ soup_ntlm_response (const char *nonce,
 
 	offset = sizeof (resp);
 
-	dlen = strlen (domain);
-	ntlm_set_string (&resp.domain, &offset, dlen);
-	ulen = strlen (user);
-	ntlm_set_string (&resp.user, &offset, ulen);
 	if (!host)
 		host = "UNKNOWN";
-	hlen = strlen (host);
+
+	domain_conv = g_convert (domain, -1, "UCS-2LE", "UTF-8", NULL, &dlen, NULL);
+	user_conv = g_convert (user, -1, "UCS-2LE", "UTF-8", NULL, &ulen, NULL);
+	host_conv = g_convert (host, -1, "UCS-2LE", "UTF-8", NULL, &hlen, NULL);
+
+	ntlm_set_string (&resp.domain, &offset, dlen);
+	ntlm_set_string (&resp.user, &offset, ulen);
 	ntlm_set_string (&resp.host, &offset, hlen);
 	ntlm_set_string (&resp.lm_resp, &offset, sizeof (lm_resp));
 	ntlm_set_string (&resp.nt_resp, &offset, sizeof (nt_resp));
@@ -838,11 +852,11 @@ soup_ntlm_response (const char *nonce,
 
 	p += g_base64_encode_step ((const guchar *) &resp, sizeof (resp), 
 				   FALSE, p, &state, &save);
-	p += g_base64_encode_step ((const guchar *) domain, dlen, 
+	p += g_base64_encode_step ((const guchar *) domain_conv, dlen,
 				   FALSE, p, &state, &save);
-	p += g_base64_encode_step ((const guchar *) user, ulen, 
+	p += g_base64_encode_step ((const guchar *) user_conv, ulen,
 				   FALSE, p, &state, &save);
-	p += g_base64_encode_step ((const guchar *) host, hlen, 
+	p += g_base64_encode_step ((const guchar *) host_conv, hlen,
 				   FALSE, p, &state, &save);
 	p += g_base64_encode_step (lm_resp, sizeof (lm_resp), 
 				   FALSE, p, &state, &save);
@@ -851,6 +865,10 @@ soup_ntlm_response (const char *nonce,
 	p += g_base64_encode_close (FALSE, p, &state, &save);
 	*p = '\0';
 
+	g_free (domain_conv);
+	g_free (user_conv);
+	g_free (host_conv);
+
 	return out;
 }
 
diff --git a/tests/get.c b/tests/get.c
index a226e31..55dd735 100644
--- a/tests/get.c
+++ b/tests/get.c
@@ -105,14 +105,14 @@ main (int argc, char **argv)
 {
 	const char *cafile = NULL, *url;
 	SoupURI *proxy = NULL, *parsed;
-	gboolean synchronous = FALSE;
+	gboolean synchronous = FALSE, ntlm = FALSE;
 	int opt;
 
 	g_type_init ();
 
 	method = SOUP_METHOD_GET;
 
-	while ((opt = getopt (argc, argv, "c:dhp:qs")) != -1) {
+	while ((opt = getopt (argc, argv, "c:dhnp:qs")) != -1) {
 		switch (opt) {
 		case 'c':
 			cafile = optarg;
@@ -127,6 +127,10 @@ main (int argc, char **argv)
 			debug = TRUE;
 			break;
 
+		case 'n':
+			ntlm = TRUE;
+			break;
+
 		case 'p':
 			proxy = soup_uri_new (optarg);
 			if (!proxy) {
@@ -172,6 +176,7 @@ main (int argc, char **argv)
 			SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_COOKIE_JAR,
 			SOUP_SESSION_USER_AGENT, "get ",
 			SOUP_SESSION_ACCEPT_LANGUAGE_AUTO, TRUE,
+			SOUP_SESSION_USE_NTLM, ntlm,
 			NULL);
 	} else {
 		session = soup_session_async_new_with_options (
@@ -183,6 +188,7 @@ main (int argc, char **argv)
 			SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_COOKIE_JAR,
 			SOUP_SESSION_USER_AGENT, "get ",
 			SOUP_SESSION_ACCEPT_LANGUAGE_AUTO, TRUE,
+			SOUP_SESSION_USE_NTLM, ntlm,
 			NULL);
 	}
 
diff --git a/tests/ntlm-test.c b/tests/ntlm-test.c
index cd74b15..46ac46e 100644
--- a/tests/ntlm-test.c
+++ b/tests/ntlm-test.c
@@ -41,7 +41,7 @@ typedef enum {
 
 #define NTLM_CHALLENGE "TlRMTVNTUAACAAAADAAMADAAAAABAoEAASNFZ4mrze8AAAAAAAAAAGIAYgA8AAAARABPAE0AQQBJAE4AAgAMAEQATwBNAEEASQBOAAEADABTAEUAUgBWAEUAUgAEABQAZABvAG0AYQBpAG4ALgBjAG8AbQADACIAcwBlAHIAdgBlAHIALgBkAG8AbQBhAGkAbgAuAGMAbwBtAAAAAAA="
 
-#define NTLM_RESPONSE_USER(response) ((response)[87] == 'h' ? NTLM_AUTHENTICATED_ALICE : NTLM_AUTHENTICATED_BOB)
+#define NTLM_RESPONSE_USER(response) ((response)[102] == 'E' ? NTLM_AUTHENTICATED_ALICE : NTLM_AUTHENTICATED_BOB)
 
 static void
 clear_state (gpointer connections, GObject *ex_connection)



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]