blob: 3c427679103d713980aaf0e231bf62c0339d26ff [file] [log] [blame]
[email protected]f3cf9802011-10-28 18:44:581// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]7da0b332010-01-08 14:56:562// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Sebastien Marchand6d0558fd2019-01-25 16:49:375#include "net/http/http_auth_sspi_win.h"
6#include "base/bind.h"
[email protected]7c46fa572010-02-25 16:05:347#include "net/base/net_errors.h"
[email protected]df41d0d82014-03-13 00:43:248#include "net/http/http_auth_challenge_tokenizer.h"
[email protected]5c2471b2010-04-20 17:25:099#include "net/http/mock_sspi_library_win.h"
robpercival214763f2016-07-01 23:27:0110#include "net/test/gtest_util.h"
11#include "testing/gmock/include/gmock/gmock.h"
[email protected]7da0b332010-01-08 14:56:5612#include "testing/gtest/include/gtest/gtest.h"
13
robpercival214763f2016-07-01 23:27:0114using net::test::IsError;
15using net::test::IsOk;
16
[email protected]7da0b332010-01-08 14:56:5617namespace net {
18
[email protected]7c46fa572010-02-25 16:05:3419namespace {
20
jdoerrie6312bf62019-02-01 22:03:4221void MatchDomainUserAfterSplit(const base::string16& combined,
22 const base::string16& expected_domain,
23 const base::string16& expected_user) {
24 base::string16 actual_domain;
25 base::string16 actual_user;
[email protected]7da0b332010-01-08 14:56:5626 SplitDomainAndUser(combined, &actual_domain, &actual_user);
27 EXPECT_EQ(expected_domain, actual_domain);
28 EXPECT_EQ(expected_user, actual_user);
29}
30
[email protected]eca50e122010-09-11 14:03:3031const ULONG kMaxTokenLength = 100;
32
aberentec894a52015-07-09 14:45:5333void UnexpectedCallback(int result) {
34 // At present getting tokens from gssapi is fully synchronous, so the callback
35 // should never be called.
36 ADD_FAILURE();
37}
38
[email protected]7c46fa572010-02-25 16:05:3439} // namespace
40
41TEST(HttpAuthSSPITest, SplitUserAndDomain) {
jdoerrie6312bf62019-02-01 22:03:4242 MatchDomainUserAfterSplit(STRING16_LITERAL("foobar"), STRING16_LITERAL(""),
43 STRING16_LITERAL("foobar"));
44 MatchDomainUserAfterSplit(STRING16_LITERAL("FOO\\bar"),
45 STRING16_LITERAL("FOO"), STRING16_LITERAL("bar"));
[email protected]7da0b332010-01-08 14:56:5646}
47
[email protected]7c46fa572010-02-25 16:05:3448TEST(HttpAuthSSPITest, DetermineMaxTokenLength_Normal) {
49 SecPkgInfoW package_info;
50 memset(&package_info, 0x0, sizeof(package_info));
51 package_info.cbMaxToken = 1337;
52
[email protected]5c2471b2010-04-20 17:25:0953 MockSSPILibrary mock_library;
[email protected]7c46fa572010-02-25 16:05:3454 mock_library.ExpectQuerySecurityPackageInfo(L"NTLM", SEC_E_OK, &package_info);
[email protected]eca50e122010-09-11 14:03:3055 ULONG max_token_length = kMaxTokenLength;
[email protected]7c46fa572010-02-25 16:05:3456 int rv = DetermineMaxTokenLength(&mock_library, L"NTLM", &max_token_length);
robpercival214763f2016-07-01 23:27:0157 EXPECT_THAT(rv, IsOk());
thakis6ef917b2015-12-10 19:29:5758 EXPECT_EQ(1337u, max_token_length);
[email protected]7c46fa572010-02-25 16:05:3459}
60
61TEST(HttpAuthSSPITest, DetermineMaxTokenLength_InvalidPackage) {
[email protected]5c2471b2010-04-20 17:25:0962 MockSSPILibrary mock_library;
[email protected]7c46fa572010-02-25 16:05:3463 mock_library.ExpectQuerySecurityPackageInfo(L"Foo", SEC_E_SECPKG_NOT_FOUND,
Raul Tambre94493c652019-03-11 17:18:3564 nullptr);
[email protected]eca50e122010-09-11 14:03:3065 ULONG max_token_length = kMaxTokenLength;
[email protected]7c46fa572010-02-25 16:05:3466 int rv = DetermineMaxTokenLength(&mock_library, L"Foo", &max_token_length);
robpercival214763f2016-07-01 23:27:0167 EXPECT_THAT(rv, IsError(ERR_UNSUPPORTED_AUTH_SCHEME));
[email protected]7c46fa572010-02-25 16:05:3468 // |DetermineMaxTokenLength()| interface states that |max_token_length| should
69 // not change on failure.
thakis6ef917b2015-12-10 19:29:5770 EXPECT_EQ(100u, max_token_length);
[email protected]7c46fa572010-02-25 16:05:3471}
72
[email protected]eca50e122010-09-11 14:03:3073TEST(HttpAuthSSPITest, ParseChallenge_FirstRound) {
74 // The first round should just consist of an unadorned "Negotiate" header.
75 MockSSPILibrary mock_library;
76 HttpAuthSSPI auth_sspi(&mock_library, "Negotiate",
77 NEGOSSP_NAME, kMaxTokenLength);
78 std::string challenge_text = "Negotiate";
[email protected]df41d0d82014-03-13 00:43:2479 HttpAuthChallengeTokenizer challenge(challenge_text.begin(),
80 challenge_text.end());
[email protected]eca50e122010-09-11 14:03:3081 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
82 auth_sspi.ParseChallenge(&challenge));
83}
84
85TEST(HttpAuthSSPITest, ParseChallenge_TwoRounds) {
86 // The first round should just have "Negotiate", and the second round should
87 // have a valid base64 token associated with it.
88 MockSSPILibrary mock_library;
89 HttpAuthSSPI auth_sspi(&mock_library, "Negotiate",
90 NEGOSSP_NAME, kMaxTokenLength);
91 std::string first_challenge_text = "Negotiate";
[email protected]df41d0d82014-03-13 00:43:2492 HttpAuthChallengeTokenizer first_challenge(first_challenge_text.begin(),
93 first_challenge_text.end());
[email protected]eca50e122010-09-11 14:03:3094 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
95 auth_sspi.ParseChallenge(&first_challenge));
96
97 // Generate an auth token and create another thing.
98 std::string auth_token;
Bence Béky7236fb72018-08-01 14:35:0999 EXPECT_EQ(OK, auth_sspi.GenerateAuthToken(
Raul Tambre94493c652019-03-11 17:18:35100 nullptr, "HTTP/intranet.google.com", std::string(),
Bence Béky7236fb72018-08-01 14:35:09101 &auth_token, base::BindOnce(&UnexpectedCallback)));
[email protected]eca50e122010-09-11 14:03:30102
103 std::string second_challenge_text = "Negotiate Zm9vYmFy";
[email protected]df41d0d82014-03-13 00:43:24104 HttpAuthChallengeTokenizer second_challenge(second_challenge_text.begin(),
105 second_challenge_text.end());
[email protected]eca50e122010-09-11 14:03:30106 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
107 auth_sspi.ParseChallenge(&second_challenge));
108}
109
110TEST(HttpAuthSSPITest, ParseChallenge_UnexpectedTokenFirstRound) {
111 // If the first round challenge has an additional authentication token, it
112 // should be treated as an invalid challenge from the server.
113 MockSSPILibrary mock_library;
114 HttpAuthSSPI auth_sspi(&mock_library, "Negotiate",
115 NEGOSSP_NAME, kMaxTokenLength);
116 std::string challenge_text = "Negotiate Zm9vYmFy";
[email protected]df41d0d82014-03-13 00:43:24117 HttpAuthChallengeTokenizer challenge(challenge_text.begin(),
118 challenge_text.end());
[email protected]eca50e122010-09-11 14:03:30119 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_INVALID,
120 auth_sspi.ParseChallenge(&challenge));
121}
122
123TEST(HttpAuthSSPITest, ParseChallenge_MissingTokenSecondRound) {
124 // If a later-round challenge is simply "Negotiate", it should be treated as
125 // an authentication challenge rejection from the server or proxy.
126 MockSSPILibrary mock_library;
127 HttpAuthSSPI auth_sspi(&mock_library, "Negotiate",
128 NEGOSSP_NAME, kMaxTokenLength);
129 std::string first_challenge_text = "Negotiate";
[email protected]df41d0d82014-03-13 00:43:24130 HttpAuthChallengeTokenizer first_challenge(first_challenge_text.begin(),
131 first_challenge_text.end());
[email protected]eca50e122010-09-11 14:03:30132 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
133 auth_sspi.ParseChallenge(&first_challenge));
134
135 std::string auth_token;
Bence Béky7236fb72018-08-01 14:35:09136 EXPECT_EQ(OK, auth_sspi.GenerateAuthToken(
Raul Tambre94493c652019-03-11 17:18:35137 nullptr, "HTTP/intranet.google.com", std::string(),
Bence Béky7236fb72018-08-01 14:35:09138 &auth_token, base::BindOnce(&UnexpectedCallback)));
[email protected]eca50e122010-09-11 14:03:30139 std::string second_challenge_text = "Negotiate";
[email protected]df41d0d82014-03-13 00:43:24140 HttpAuthChallengeTokenizer second_challenge(second_challenge_text.begin(),
141 second_challenge_text.end());
[email protected]eca50e122010-09-11 14:03:30142 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_REJECT,
143 auth_sspi.ParseChallenge(&second_challenge));
144}
145
146TEST(HttpAuthSSPITest, ParseChallenge_NonBase64EncodedToken) {
147 // If a later-round challenge has an invalid base64 encoded token, it should
148 // be treated as an invalid challenge.
149 MockSSPILibrary mock_library;
150 HttpAuthSSPI auth_sspi(&mock_library, "Negotiate",
151 NEGOSSP_NAME, kMaxTokenLength);
152 std::string first_challenge_text = "Negotiate";
[email protected]df41d0d82014-03-13 00:43:24153 HttpAuthChallengeTokenizer first_challenge(first_challenge_text.begin(),
154 first_challenge_text.end());
[email protected]eca50e122010-09-11 14:03:30155 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
156 auth_sspi.ParseChallenge(&first_challenge));
157
158 std::string auth_token;
Bence Béky7236fb72018-08-01 14:35:09159 EXPECT_EQ(OK, auth_sspi.GenerateAuthToken(
Raul Tambre94493c652019-03-11 17:18:35160 nullptr, "HTTP/intranet.google.com", std::string(),
Bence Béky7236fb72018-08-01 14:35:09161 &auth_token, base::BindOnce(&UnexpectedCallback)));
[email protected]eca50e122010-09-11 14:03:30162 std::string second_challenge_text = "Negotiate =happyjoy=";
[email protected]df41d0d82014-03-13 00:43:24163 HttpAuthChallengeTokenizer second_challenge(second_challenge_text.begin(),
164 second_challenge_text.end());
[email protected]eca50e122010-09-11 14:03:30165 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_INVALID,
166 auth_sspi.ParseChallenge(&second_challenge));
167}
168
[email protected]7da0b332010-01-08 14:56:56169} // namespace net