summaryrefslogtreecommitdiffstats
path: root/net/http/http_auth_sspi_win_unittest.cc
diff options
context:
space:
mode:
authorcbentzel@chromium.org <cbentzel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-09-11 14:03:30 +0000
committercbentzel@chromium.org <cbentzel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-09-11 14:03:30 +0000
commiteca50e128ff1bc41bc0cc1d3fdf2e015ba459d4c (patch)
treeae0368388f38766781c5ddff86c9e0e2c0c9c362 /net/http/http_auth_sspi_win_unittest.cc
parent4630db4630bc415cc3b7be70bce87160559810df (diff)
downloadchromium_src-eca50e128ff1bc41bc0cc1d3fdf2e015ba459d4c.zip
chromium_src-eca50e128ff1bc41bc0cc1d3fdf2e015ba459d4c.tar.gz
chromium_src-eca50e128ff1bc41bc0cc1d3fdf2e015ba459d4c.tar.bz2
Fix multi-round authentication.
In the case of Negotiate, authentication can look like C: GET S: 401, WWW-Authenticate: Negotiate C: GET, WWW-Authorization: Negotiate <client_token_1> S: 401, WWW-Authenticate: Negotiate <server_token_1> C: GET, WWW-Authorization: Negotiate <client_token_2> S: 401, WWW-Authenticate: Negotiate <server_token_2> on that third challenge, the handler was reported as being in "the final round" and this was treated as a rejection of the authentication attempt. After that, the new challenge token was used by a new auth handler that hadn't established a security context, and an ERR_INVALID_HANDLE would be returned. This CL also does some prep work to correctly handle the "stale=true" value for Digest authentication, but I decided to defer the HttpAuthCache changes needed for that to a separate CL since this was large enough. BUG=53282 TEST=net_unittests. Unfortunately, I haven't been able to set up a proxy/server to do more than two auth challenges, but this does happen in the wild. Review URL: http://codereview.chromium.org/3360017 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@59188 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/http/http_auth_sspi_win_unittest.cc')
-rw-r--r--net/http/http_auth_sspi_win_unittest.cc102
1 files changed, 100 insertions, 2 deletions
diff --git a/net/http/http_auth_sspi_win_unittest.cc b/net/http/http_auth_sspi_win_unittest.cc
index fdef793..331dcd6 100644
--- a/net/http/http_auth_sspi_win_unittest.cc
+++ b/net/http/http_auth_sspi_win_unittest.cc
@@ -22,6 +22,8 @@ void MatchDomainUserAfterSplit(const std::wstring& combined,
EXPECT_EQ(expected_user, actual_user);
}
+const ULONG kMaxTokenLength = 100;
+
} // namespace
TEST(HttpAuthSSPITest, SplitUserAndDomain) {
@@ -36,7 +38,7 @@ TEST(HttpAuthSSPITest, DetermineMaxTokenLength_Normal) {
MockSSPILibrary mock_library;
mock_library.ExpectQuerySecurityPackageInfo(L"NTLM", SEC_E_OK, &package_info);
- ULONG max_token_length = 100;
+ ULONG max_token_length = kMaxTokenLength;
int rv = DetermineMaxTokenLength(&mock_library, L"NTLM", &max_token_length);
EXPECT_EQ(OK, rv);
EXPECT_EQ(1337, max_token_length);
@@ -46,7 +48,7 @@ TEST(HttpAuthSSPITest, DetermineMaxTokenLength_InvalidPackage) {
MockSSPILibrary mock_library;
mock_library.ExpectQuerySecurityPackageInfo(L"Foo", SEC_E_SECPKG_NOT_FOUND,
NULL);
- ULONG max_token_length = 100;
+ ULONG max_token_length = kMaxTokenLength;
int rv = DetermineMaxTokenLength(&mock_library, L"Foo", &max_token_length);
EXPECT_EQ(ERR_UNSUPPORTED_AUTH_SCHEME, rv);
// |DetermineMaxTokenLength()| interface states that |max_token_length| should
@@ -54,4 +56,100 @@ TEST(HttpAuthSSPITest, DetermineMaxTokenLength_InvalidPackage) {
EXPECT_EQ(100, max_token_length);
}
+TEST(HttpAuthSSPITest, ParseChallenge_FirstRound) {
+ // The first round should just consist of an unadorned "Negotiate" header.
+ MockSSPILibrary mock_library;
+ HttpAuthSSPI auth_sspi(&mock_library, "Negotiate",
+ NEGOSSP_NAME, kMaxTokenLength);
+ std::string challenge_text = "Negotiate";
+ HttpAuth::ChallengeTokenizer challenge(challenge_text.begin(),
+ challenge_text.end());
+ EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
+ auth_sspi.ParseChallenge(&challenge));
+}
+
+TEST(HttpAuthSSPITest, ParseChallenge_TwoRounds) {
+ // The first round should just have "Negotiate", and the second round should
+ // have a valid base64 token associated with it.
+ MockSSPILibrary mock_library;
+ HttpAuthSSPI auth_sspi(&mock_library, "Negotiate",
+ NEGOSSP_NAME, kMaxTokenLength);
+ std::string first_challenge_text = "Negotiate";
+ HttpAuth::ChallengeTokenizer first_challenge(first_challenge_text.begin(),
+ first_challenge_text.end());
+ EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
+ auth_sspi.ParseChallenge(&first_challenge));
+
+ // Generate an auth token and create another thing.
+ std::string auth_token;
+ EXPECT_EQ(OK, auth_sspi.GenerateAuthToken(NULL, NULL,
+ L"HTTP/intranet.google.com",
+ &auth_token));
+
+ std::string second_challenge_text = "Negotiate Zm9vYmFy";
+ HttpAuth::ChallengeTokenizer second_challenge(second_challenge_text.begin(),
+ second_challenge_text.end());
+ EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
+ auth_sspi.ParseChallenge(&second_challenge));
+}
+
+TEST(HttpAuthSSPITest, ParseChallenge_UnexpectedTokenFirstRound) {
+ // If the first round challenge has an additional authentication token, it
+ // should be treated as an invalid challenge from the server.
+ MockSSPILibrary mock_library;
+ HttpAuthSSPI auth_sspi(&mock_library, "Negotiate",
+ NEGOSSP_NAME, kMaxTokenLength);
+ std::string challenge_text = "Negotiate Zm9vYmFy";
+ HttpAuth::ChallengeTokenizer challenge(challenge_text.begin(),
+ challenge_text.end());
+ EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_INVALID,
+ auth_sspi.ParseChallenge(&challenge));
+}
+
+TEST(HttpAuthSSPITest, ParseChallenge_MissingTokenSecondRound) {
+ // If a later-round challenge is simply "Negotiate", it should be treated as
+ // an authentication challenge rejection from the server or proxy.
+ MockSSPILibrary mock_library;
+ HttpAuthSSPI auth_sspi(&mock_library, "Negotiate",
+ NEGOSSP_NAME, kMaxTokenLength);
+ std::string first_challenge_text = "Negotiate";
+ HttpAuth::ChallengeTokenizer first_challenge(first_challenge_text.begin(),
+ first_challenge_text.end());
+ EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
+ auth_sspi.ParseChallenge(&first_challenge));
+
+ std::string auth_token;
+ EXPECT_EQ(OK, auth_sspi.GenerateAuthToken(NULL, NULL,
+ L"HTTP/intranet.google.com",
+ &auth_token));
+ std::string second_challenge_text = "Negotiate";
+ HttpAuth::ChallengeTokenizer second_challenge(second_challenge_text.begin(),
+ second_challenge_text.end());
+ EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_REJECT,
+ auth_sspi.ParseChallenge(&second_challenge));
+}
+
+TEST(HttpAuthSSPITest, ParseChallenge_NonBase64EncodedToken) {
+ // If a later-round challenge has an invalid base64 encoded token, it should
+ // be treated as an invalid challenge.
+ MockSSPILibrary mock_library;
+ HttpAuthSSPI auth_sspi(&mock_library, "Negotiate",
+ NEGOSSP_NAME, kMaxTokenLength);
+ std::string first_challenge_text = "Negotiate";
+ HttpAuth::ChallengeTokenizer first_challenge(first_challenge_text.begin(),
+ first_challenge_text.end());
+ EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
+ auth_sspi.ParseChallenge(&first_challenge));
+
+ std::string auth_token;
+ EXPECT_EQ(OK, auth_sspi.GenerateAuthToken(NULL, NULL,
+ L"HTTP/intranet.google.com",
+ &auth_token));
+ std::string second_challenge_text = "Negotiate =happyjoy=";
+ HttpAuth::ChallengeTokenizer second_challenge(second_challenge_text.begin(),
+ second_challenge_text.end());
+ EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_INVALID,
+ auth_sspi.ParseChallenge(&second_challenge));
+}
+
} // namespace net