http_auth_sspi_win_unittest.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h" 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_auth_sspi_win.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/mock_sspi_library_win.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MatchDomainUserAfterSplit(const std::wstring& combined, 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::wstring& expected_domain, 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::wstring& expected_user) { 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring actual_domain; 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring actual_user; 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SplitDomainAndUser(combined, &actual_domain, &actual_user); 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(expected_domain, actual_domain); 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(expected_user, actual_user); 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const ULONG kMaxTokenLength = 100; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(HttpAuthSSPITest, SplitUserAndDomain) { 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MatchDomainUserAfterSplit(L"foobar", L"", L"foobar"); 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MatchDomainUserAfterSplit(L"FOO\\bar", L"FOO", L"bar"); 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(HttpAuthSSPITest, DetermineMaxTokenLength_Normal) { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SecPkgInfoW package_info; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&package_info, 0x0, sizeof(package_info)); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) package_info.cbMaxToken = 1337; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockSSPILibrary mock_library; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mock_library.ExpectQuerySecurityPackageInfo(L"NTLM", SEC_E_OK, &package_info); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULONG max_token_length = kMaxTokenLength; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = DetermineMaxTokenLength(&mock_library, L"NTLM", &max_token_length); 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(OK, rv); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1337, max_token_length); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(HttpAuthSSPITest, DetermineMaxTokenLength_InvalidPackage) { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockSSPILibrary mock_library; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mock_library.ExpectQuerySecurityPackageInfo(L"Foo", SEC_E_SECPKG_NOT_FOUND, 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULONG max_token_length = kMaxTokenLength; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = DetermineMaxTokenLength(&mock_library, L"Foo", &max_token_length); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(ERR_UNSUPPORTED_AUTH_SCHEME, rv); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |DetermineMaxTokenLength()| interface states that |max_token_length| should 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // not change on failure. 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(100, max_token_length); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(HttpAuthSSPITest, ParseChallenge_FirstRound) { 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The first round should just consist of an unadorned "Negotiate" header. 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockSSPILibrary mock_library; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HttpAuthSSPI auth_sspi(&mock_library, "Negotiate", 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NEGOSSP_NAME, kMaxTokenLength); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string challenge_text = "Negotiate"; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HttpAuth::ChallengeTokenizer challenge(challenge_text.begin(), 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) challenge_text.end()); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT, 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) auth_sspi.ParseChallenge(&challenge)); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(HttpAuthSSPITest, ParseChallenge_TwoRounds) { 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The first round should just have "Negotiate", and the second round should 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // have a valid base64 token associated with it. 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockSSPILibrary mock_library; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HttpAuthSSPI auth_sspi(&mock_library, "Negotiate", 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NEGOSSP_NAME, kMaxTokenLength); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string first_challenge_text = "Negotiate"; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HttpAuth::ChallengeTokenizer first_challenge(first_challenge_text.begin(), 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first_challenge_text.end()); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT, 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) auth_sspi.ParseChallenge(&first_challenge)); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Generate an auth token and create another thing. 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string auth_token; 85a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(OK, auth_sspi.GenerateAuthToken(NULL, "HTTP/intranet.google.com", 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &auth_token)); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string second_challenge_text = "Negotiate Zm9vYmFy"; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HttpAuth::ChallengeTokenizer second_challenge(second_challenge_text.begin(), 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) second_challenge_text.end()); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT, 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) auth_sspi.ParseChallenge(&second_challenge)); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(HttpAuthSSPITest, ParseChallenge_UnexpectedTokenFirstRound) { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the first round challenge has an additional authentication token, it 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // should be treated as an invalid challenge from the server. 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockSSPILibrary mock_library; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HttpAuthSSPI auth_sspi(&mock_library, "Negotiate", 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NEGOSSP_NAME, kMaxTokenLength); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string challenge_text = "Negotiate Zm9vYmFy"; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HttpAuth::ChallengeTokenizer challenge(challenge_text.begin(), 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) challenge_text.end()); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_INVALID, 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) auth_sspi.ParseChallenge(&challenge)); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(HttpAuthSSPITest, ParseChallenge_MissingTokenSecondRound) { 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If a later-round challenge is simply "Negotiate", it should be treated as 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // an authentication challenge rejection from the server or proxy. 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockSSPILibrary mock_library; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HttpAuthSSPI auth_sspi(&mock_library, "Negotiate", 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NEGOSSP_NAME, kMaxTokenLength); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string first_challenge_text = "Negotiate"; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HttpAuth::ChallengeTokenizer first_challenge(first_challenge_text.begin(), 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first_challenge_text.end()); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT, 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) auth_sspi.ParseChallenge(&first_challenge)); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string auth_token; 121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(OK, auth_sspi.GenerateAuthToken(NULL, "HTTP/intranet.google.com", 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &auth_token)); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string second_challenge_text = "Negotiate"; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HttpAuth::ChallengeTokenizer second_challenge(second_challenge_text.begin(), 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) second_challenge_text.end()); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_REJECT, 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) auth_sspi.ParseChallenge(&second_challenge)); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(HttpAuthSSPITest, ParseChallenge_NonBase64EncodedToken) { 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If a later-round challenge has an invalid base64 encoded token, it should 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // be treated as an invalid challenge. 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockSSPILibrary mock_library; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HttpAuthSSPI auth_sspi(&mock_library, "Negotiate", 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NEGOSSP_NAME, kMaxTokenLength); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string first_challenge_text = "Negotiate"; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HttpAuth::ChallengeTokenizer first_challenge(first_challenge_text.begin(), 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first_challenge_text.end()); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT, 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) auth_sspi.ParseChallenge(&first_challenge)); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string auth_token; 143a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(OK, auth_sspi.GenerateAuthToken(NULL, "HTTP/intranet.google.com", 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &auth_token)); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string second_challenge_text = "Negotiate =happyjoy="; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HttpAuth::ChallengeTokenizer second_challenge(second_challenge_text.begin(), 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) second_challenge_text.end()); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_INVALID, 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) auth_sspi.ParseChallenge(&second_challenge)); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 153