1 // Copyright (c) 2011 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, "HTTP/intranet.google.com", 86 &auth_token)); 87 88 std::string second_challenge_text = "Negotiate Zm9vYmFy"; 89 HttpAuth::ChallengeTokenizer second_challenge(second_challenge_text.begin(), 90 second_challenge_text.end()); 91 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT, 92 auth_sspi.ParseChallenge(&second_challenge)); 93 } 94 95 TEST(HttpAuthSSPITest, ParseChallenge_UnexpectedTokenFirstRound) { 96 // If the first round challenge has an additional authentication token, it 97 // should be treated as an invalid challenge from the server. 98 MockSSPILibrary mock_library; 99 HttpAuthSSPI auth_sspi(&mock_library, "Negotiate", 100 NEGOSSP_NAME, kMaxTokenLength); 101 std::string challenge_text = "Negotiate Zm9vYmFy"; 102 HttpAuth::ChallengeTokenizer challenge(challenge_text.begin(), 103 challenge_text.end()); 104 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_INVALID, 105 auth_sspi.ParseChallenge(&challenge)); 106 } 107 108 TEST(HttpAuthSSPITest, ParseChallenge_MissingTokenSecondRound) { 109 // If a later-round challenge is simply "Negotiate", it should be treated as 110 // an authentication challenge rejection from the server or proxy. 111 MockSSPILibrary mock_library; 112 HttpAuthSSPI auth_sspi(&mock_library, "Negotiate", 113 NEGOSSP_NAME, kMaxTokenLength); 114 std::string first_challenge_text = "Negotiate"; 115 HttpAuth::ChallengeTokenizer first_challenge(first_challenge_text.begin(), 116 first_challenge_text.end()); 117 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT, 118 auth_sspi.ParseChallenge(&first_challenge)); 119 120 std::string auth_token; 121 EXPECT_EQ(OK, auth_sspi.GenerateAuthToken(NULL, "HTTP/intranet.google.com", 122 &auth_token)); 123 std::string second_challenge_text = "Negotiate"; 124 HttpAuth::ChallengeTokenizer second_challenge(second_challenge_text.begin(), 125 second_challenge_text.end()); 126 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_REJECT, 127 auth_sspi.ParseChallenge(&second_challenge)); 128 } 129 130 TEST(HttpAuthSSPITest, ParseChallenge_NonBase64EncodedToken) { 131 // If a later-round challenge has an invalid base64 encoded token, it should 132 // be treated as an invalid challenge. 133 MockSSPILibrary mock_library; 134 HttpAuthSSPI auth_sspi(&mock_library, "Negotiate", 135 NEGOSSP_NAME, kMaxTokenLength); 136 std::string first_challenge_text = "Negotiate"; 137 HttpAuth::ChallengeTokenizer first_challenge(first_challenge_text.begin(), 138 first_challenge_text.end()); 139 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT, 140 auth_sspi.ParseChallenge(&first_challenge)); 141 142 std::string auth_token; 143 EXPECT_EQ(OK, auth_sspi.GenerateAuthToken(NULL, "HTTP/intranet.google.com", 144 &auth_token)); 145 std::string second_challenge_text = "Negotiate =happyjoy="; 146 HttpAuth::ChallengeTokenizer second_challenge(second_challenge_text.begin(), 147 second_challenge_text.end()); 148 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_INVALID, 149 auth_sspi.ParseChallenge(&second_challenge)); 150 } 151 152 } // namespace net 153