diff --git a/netwerk/protocol/http/src/nsHttpChannel.cpp b/netwerk/protocol/http/src/nsHttpChannel.cpp index 4f993c62fe75..1e30e23a9227 100644 --- a/netwerk/protocol/http/src/nsHttpChannel.cpp +++ b/netwerk/protocol/http/src/nsHttpChannel.cpp @@ -2653,12 +2653,24 @@ nsHttpChannel::ParseRealm(const char *challenge, nsACString &realm) // const char *p = PL_strcasestr(challenge, "realm="); if (p) { + PRBool has_quote = PR_FALSE; p += 6; - if (*p == '"') + if (*p == '"') { + has_quote = PR_TRUE; p++; - const char *end = PL_strchr(p, '"'); - if (!end) - end = PL_strchr(p, ' '); + } + + const char *end = p; + while (*end && has_quote) { + // Loop through all the string characters to find the closing + // quote, ignoring escaped quotes. + if (*end == '"' && end[-1] != '\\') + break; + ++end; + } + + if (!has_quote) + end = strchr(p, ' '); if (end) realm.Assign(p, end - p); else diff --git a/netwerk/test/unit/test_authentication.js b/netwerk/test/unit/test_authentication.js index d893d6113075..0cf076860c16 100644 --- a/netwerk/test/unit/test_authentication.js +++ b/netwerk/test/unit/test_authentication.js @@ -130,7 +130,6 @@ AuthPrompt2.prototype = { } }; - function Requestor(flags, versions) { this.flags = flags; this.versions = versions; @@ -167,6 +166,35 @@ Requestor.prototype = { prompt2: null }; +function RealmTestRequestor() {} + +RealmTestRequestor.prototype = { + QueryInterface: function realmtest_qi(iid) { + if (iid.equals(Components.interfaces.nsISupports) || + iid.equals(Components.interfaces.nsIInterfaceRequestor) || + iid.equals(Components.interfaces.nsIAuthPrompt2)) + return this; + throw Components.results.NS_ERROR_NO_INTERFACE; + }, + + getInterface: function realmtest_interface(iid) { + if (iid.equals(Components.interfaces.nsIAuthPrompt2)) + return this; + + throw Components.results.NS_ERROR_NO_INTERFACE; + }, + + promptAuth: function realmtest_checkAuth(channel, level, authInfo) { + do_check_eq(authInfo.realm, '\\"foo_bar'); + + return false; + }, + + asyncPromptAuth: function realmtest_async(chan, cb, ctx, lvl, info) { + do_throw("not implemented yet"); + } +}; + var listener = { expectedCode: 401, // Unauthorized @@ -222,7 +250,8 @@ function makeChan(url) { } var tests = [test_noauth, test_returnfalse1, test_wrongpw1, test_prompt1, - test_returnfalse2, test_wrongpw2, test_prompt2, test_ntlm]; + test_returnfalse2, test_wrongpw2, test_prompt2, test_ntlm, + test_auth]; var current_test = 0; var httpserv = null; @@ -232,6 +261,7 @@ function run_test() { httpserv.registerPathHandler("/auth", authHandler); httpserv.registerPathHandler("/auth/ntlm/simple", authNtlmSimple); + httpserv.registerPathHandler("/auth/realm", authRealm); httpserv.start(4444); @@ -317,6 +347,16 @@ function test_ntlm() { do_test_pending(); } +function test_auth() { + var chan = makeChan("http://localhost:4444/auth/realm"); + + chan.notificationCallbacks = new RealmTestRequestor(); + listener.expectedCode = 401; // Unauthorized + chan.asyncOpen(listener, null); + + do_test_pending(); +} + // PATH HANDLERS // /auth @@ -357,3 +397,12 @@ function authNtlmSimple(metadata, response) { response.bodyOutputStream.write(body, body.length); } + +// /auth/realm +function authRealm(metadata, response) { + response.setStatusLine(metadata.httpVersion, 401, "Unauthorized"); + response.setHeader("WWW-Authenticate", 'Basic realm="\\"foo_bar"', false); + var body = "success"; + + response.bodyOutputStream.write(body, body.length); +}