1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/basictypes.h" 6 #include "net/base/net_errors.h" 7 #include "net/http/http_auth_sspi_win.h" 8 #include "net/http/mock_sspi_library_win.h" 9 #include "testing/gtest/include/gtest/gtest.h" 10 11 namespace net { 12 13 namespace { 14 15 void MatchDomainUserAfterSplit(const std::wstring& combined, 16 const std::wstring& expected_domain, 17 const std::wstring& expected_user) { 18 std::wstring actual_domain; 19 std::wstring actual_user; 20 SplitDomainAndUser(combined, &actual_domain, &actual_user); 21 EXPECT_EQ(expected_domain, actual_domain); 22 EXPECT_EQ(expected_user, actual_user); 23 } 24 25 const ULONG kMaxTokenLength = 100; 26 27 } // namespace 28 29 TEST(HttpAuthSSPITest, SplitUserAndDomain) { 30 MatchDomainUserAfterSplit(L"foobar", L"", L"foobar"); 31 MatchDomainUserAfterSplit(L"FOO\\bar", L"FOO", L"bar"); 32 } 33 34 TEST(HttpAuthSSPITest, DetermineMaxTokenLength_Normal) { 35 SecPkgInfoW package_info; 36 memset(&package_info, 0x0, sizeof(package_info)); 37 package_info.cbMaxToken = 1337; 38 39 MockSSPILibrary mock_library; 40 mock_library.ExpectQuerySecurityPackageInfo(L"NTLM", SEC_E_OK, &package_info); 41 ULONG max_token_length = kMaxTokenLength; 42 int rv = DetermineMaxTokenLength(&mock_library, L"NTLM", &max_token_length); 43 EXPECT_EQ(OK, rv); 44 EXPECT_EQ(1337, max_token_length); 45 } 46 47 TEST(HttpAuthSSPITest, DetermineMaxTokenLength_InvalidPackage) { 48 MockSSPILibrary mock_library; 49 mock_library.ExpectQuerySecurityPackageInfo(L"Foo", SEC_E_SECPKG_NOT_FOUND, 50 NULL); 51 ULONG max_token_length = kMaxTokenLength; 52 int rv = DetermineMaxTokenLength(&mock_library, L"Foo", &max_token_length); 53 EXPECT_EQ(ERR_UNSUPPORTED_AUTH_SCHEME, rv); 54 // |DetermineMaxTokenLength()| interface states that |max_token_length| should 55 // not change on failure. 56 EXPECT_EQ(100, max_token_length); 57 } 58 59 TEST(HttpAuthSSPITest, ParseChallenge_FirstRound) { 60 // The first round should just consist of an unadorned "Negotiate" header. 61 MockSSPILibrary mock_library; 62 HttpAuthSSPI auth_sspi(&mock_library, "Negotiate", 63 NEGOSSP_NAME, kMaxTokenLength); 64 std::string challenge_text = "Negotiate"; 65 HttpAuth::ChallengeTokenizer challenge(challenge_text.begin(), 66 challenge_text.end()); 67 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT, 68 auth_sspi.ParseChallenge(&challenge)); 69 } 70 71 TEST(HttpAuthSSPITest, ParseChallenge_TwoRounds) { 72 // The first round should just have "Negotiate", and the second round should 73 // have a valid base64 token associated with it. 74 MockSSPILibrary mock_library; 75 HttpAuthSSPI auth_sspi(&mock_library, "Negotiate", 76 NEGOSSP_NAME, kMaxTokenLength); 77 std::string first_challenge_text = "Negotiate"; 78 HttpAuth::ChallengeTokenizer first_challenge(first_challenge_text.begin(), 79 first_challenge_text.end()); 80 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT, 81 auth_sspi.ParseChallenge(&first_challenge)); 82 83 // Generate an auth token and create another thing. 84 std::string auth_token; 85 EXPECT_EQ(OK, auth_sspi.GenerateAuthToken(NULL, NULL, 86 L"HTTP/intranet.google.com", 87 &auth_token)); 88 89 std::string second_challenge_text = "Negotiate Zm9vYmFy"; 90 HttpAuth::ChallengeTokenizer second_challenge(second_challenge_text.begin(), 91 second_challenge_text.end()); 92 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT, 93 auth_sspi.ParseChallenge(&second_challenge)); 94 } 95 96 TEST(HttpAuthSSPITest, ParseChallenge_UnexpectedTokenFirstRound) { 97 // If the first round challenge has an additional authentication token, it 98 // should be treated as an invalid challenge from the server. 99 MockSSPILibrary mock_library; 100 HttpAuthSSPI auth_sspi(&mock_library, "Negotiate", 101 NEGOSSP_NAME, kMaxTokenLength); 102 std::string challenge_text = "Negotiate Zm9vYmFy"; 103 HttpAuth::ChallengeTokenizer challenge(challenge_text.begin(), 104 challenge_text.end()); 105 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_INVALID, 106 auth_sspi.ParseChallenge(&challenge)); 107 } 108 109 TEST(HttpAuthSSPITest, ParseChallenge_MissingTokenSecondRound) { 110 // If a later-round challenge is simply "Negotiate", it should be treated as 111 // an authentication challenge rejection from the server or proxy. 112 MockSSPILibrary mock_library; 113 HttpAuthSSPI auth_sspi(&mock_library, "Negotiate", 114 NEGOSSP_NAME, kMaxTokenLength); 115 std::string first_challenge_text = "Negotiate"; 116 HttpAuth::ChallengeTokenizer first_challenge(first_challenge_text.begin(), 117 first_challenge_text.end()); 118 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT, 119 auth_sspi.ParseChallenge(&first_challenge)); 120 121 std::string auth_token; 122 EXPECT_EQ(OK, auth_sspi.GenerateAuthToken(NULL, NULL, 123 L"HTTP/intranet.google.com", 124 &auth_token)); 125 std::string second_challenge_text = "Negotiate"; 126 HttpAuth::ChallengeTokenizer second_challenge(second_challenge_text.begin(), 127 second_challenge_text.end()); 128 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_REJECT, 129 auth_sspi.ParseChallenge(&second_challenge)); 130 } 131 132 TEST(HttpAuthSSPITest, ParseChallenge_NonBase64EncodedToken) { 133 // If a later-round challenge has an invalid base64 encoded token, it should 134 // be treated as an invalid challenge. 135 MockSSPILibrary mock_library; 136 HttpAuthSSPI auth_sspi(&mock_library, "Negotiate", 137 NEGOSSP_NAME, kMaxTokenLength); 138 std::string first_challenge_text = "Negotiate"; 139 HttpAuth::ChallengeTokenizer first_challenge(first_challenge_text.begin(), 140 first_challenge_text.end()); 141 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT, 142 auth_sspi.ParseChallenge(&first_challenge)); 143 144 std::string auth_token; 145 EXPECT_EQ(OK, auth_sspi.GenerateAuthToken(NULL, NULL, 146 L"HTTP/intranet.google.com", 147 &auth_token)); 148 std::string second_challenge_text = "Negotiate =happyjoy="; 149 HttpAuth::ChallengeTokenizer second_challenge(second_challenge_text.begin(), 150 second_challenge_text.end()); 151 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_INVALID, 152 auth_sspi.ParseChallenge(&second_challenge)); 153 } 154 155 } // namespace net 156