From 67824e6224409f77fa397a0d6bb2eab5e6cc8081 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Thu, 20 Oct 2011 17:27:34 -0400 Subject: [PATCH] SoupAuthManagerNTLM: allow non-ASCII usernames/passwords MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 #include +#include #ifdef USE_NTLM_AUTH #include @@ -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) -- 2.7.4