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.
5 #include "base/basictypes.h"
6 #include "net/base/net_errors.h"
7 #include "net/http/http_auth_challenge_tokenizer.h"
8 #include "net/http/http_auth_sspi_win.h"
9 #include "net/http/mock_sspi_library_win.h"
10 #include "testing/gtest/include/gtest/gtest.h"
16 void MatchDomainUserAfterSplit(const std::wstring
& combined
,
17 const std::wstring
& expected_domain
,
18 const std::wstring
& expected_user
) {
19 std::wstring actual_domain
;
20 std::wstring actual_user
;
21 SplitDomainAndUser(combined
, &actual_domain
, &actual_user
);
22 EXPECT_EQ(expected_domain
, actual_domain
);
23 EXPECT_EQ(expected_user
, actual_user
);
26 const ULONG kMaxTokenLength
= 100;
28 void UnexpectedCallback(int result
) {
29 // At present getting tokens from gssapi is fully synchronous, so the callback
30 // should never be called.
36 TEST(HttpAuthSSPITest
, SplitUserAndDomain
) {
37 MatchDomainUserAfterSplit(L
"foobar", L
"", L
"foobar");
38 MatchDomainUserAfterSplit(L
"FOO\\bar", L
"FOO", L
"bar");
41 TEST(HttpAuthSSPITest
, DetermineMaxTokenLength_Normal
) {
42 SecPkgInfoW package_info
;
43 memset(&package_info
, 0x0, sizeof(package_info
));
44 package_info
.cbMaxToken
= 1337;
46 MockSSPILibrary mock_library
;
47 mock_library
.ExpectQuerySecurityPackageInfo(L
"NTLM", SEC_E_OK
, &package_info
);
48 ULONG max_token_length
= kMaxTokenLength
;
49 int rv
= DetermineMaxTokenLength(&mock_library
, L
"NTLM", &max_token_length
);
51 EXPECT_EQ(1337, max_token_length
);
54 TEST(HttpAuthSSPITest
, DetermineMaxTokenLength_InvalidPackage
) {
55 MockSSPILibrary mock_library
;
56 mock_library
.ExpectQuerySecurityPackageInfo(L
"Foo", SEC_E_SECPKG_NOT_FOUND
,
58 ULONG max_token_length
= kMaxTokenLength
;
59 int rv
= DetermineMaxTokenLength(&mock_library
, L
"Foo", &max_token_length
);
60 EXPECT_EQ(ERR_UNSUPPORTED_AUTH_SCHEME
, rv
);
61 // |DetermineMaxTokenLength()| interface states that |max_token_length| should
62 // not change on failure.
63 EXPECT_EQ(100, max_token_length
);
66 TEST(HttpAuthSSPITest
, ParseChallenge_FirstRound
) {
67 // The first round should just consist of an unadorned "Negotiate" header.
68 MockSSPILibrary mock_library
;
69 HttpAuthSSPI
auth_sspi(&mock_library
, "Negotiate",
70 NEGOSSP_NAME
, kMaxTokenLength
);
71 std::string challenge_text
= "Negotiate";
72 HttpAuthChallengeTokenizer
challenge(challenge_text
.begin(),
73 challenge_text
.end());
74 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT
,
75 auth_sspi
.ParseChallenge(&challenge
));
78 TEST(HttpAuthSSPITest
, ParseChallenge_TwoRounds
) {
79 // The first round should just have "Negotiate", and the second round should
80 // have a valid base64 token associated with it.
81 MockSSPILibrary mock_library
;
82 HttpAuthSSPI
auth_sspi(&mock_library
, "Negotiate",
83 NEGOSSP_NAME
, kMaxTokenLength
);
84 std::string first_challenge_text
= "Negotiate";
85 HttpAuthChallengeTokenizer
first_challenge(first_challenge_text
.begin(),
86 first_challenge_text
.end());
87 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT
,
88 auth_sspi
.ParseChallenge(&first_challenge
));
90 // Generate an auth token and create another thing.
91 std::string auth_token
;
92 EXPECT_EQ(OK
, auth_sspi
.GenerateAuthToken(NULL
, "HTTP/intranet.google.com",
94 base::Bind(&UnexpectedCallback
)));
96 std::string second_challenge_text
= "Negotiate Zm9vYmFy";
97 HttpAuthChallengeTokenizer
second_challenge(second_challenge_text
.begin(),
98 second_challenge_text
.end());
99 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT
,
100 auth_sspi
.ParseChallenge(&second_challenge
));
103 TEST(HttpAuthSSPITest
, ParseChallenge_UnexpectedTokenFirstRound
) {
104 // If the first round challenge has an additional authentication token, it
105 // should be treated as an invalid challenge from the server.
106 MockSSPILibrary mock_library
;
107 HttpAuthSSPI
auth_sspi(&mock_library
, "Negotiate",
108 NEGOSSP_NAME
, kMaxTokenLength
);
109 std::string challenge_text
= "Negotiate Zm9vYmFy";
110 HttpAuthChallengeTokenizer
challenge(challenge_text
.begin(),
111 challenge_text
.end());
112 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_INVALID
,
113 auth_sspi
.ParseChallenge(&challenge
));
116 TEST(HttpAuthSSPITest
, ParseChallenge_MissingTokenSecondRound
) {
117 // If a later-round challenge is simply "Negotiate", it should be treated as
118 // an authentication challenge rejection from the server or proxy.
119 MockSSPILibrary mock_library
;
120 HttpAuthSSPI
auth_sspi(&mock_library
, "Negotiate",
121 NEGOSSP_NAME
, kMaxTokenLength
);
122 std::string first_challenge_text
= "Negotiate";
123 HttpAuthChallengeTokenizer
first_challenge(first_challenge_text
.begin(),
124 first_challenge_text
.end());
125 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT
,
126 auth_sspi
.ParseChallenge(&first_challenge
));
128 std::string auth_token
;
129 EXPECT_EQ(OK
, auth_sspi
.GenerateAuthToken(NULL
, "HTTP/intranet.google.com",
131 base::Bind(&UnexpectedCallback
)));
132 std::string second_challenge_text
= "Negotiate";
133 HttpAuthChallengeTokenizer
second_challenge(second_challenge_text
.begin(),
134 second_challenge_text
.end());
135 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_REJECT
,
136 auth_sspi
.ParseChallenge(&second_challenge
));
139 TEST(HttpAuthSSPITest
, ParseChallenge_NonBase64EncodedToken
) {
140 // If a later-round challenge has an invalid base64 encoded token, it should
141 // be treated as an invalid challenge.
142 MockSSPILibrary mock_library
;
143 HttpAuthSSPI
auth_sspi(&mock_library
, "Negotiate",
144 NEGOSSP_NAME
, kMaxTokenLength
);
145 std::string first_challenge_text
= "Negotiate";
146 HttpAuthChallengeTokenizer
first_challenge(first_challenge_text
.begin(),
147 first_challenge_text
.end());
148 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT
,
149 auth_sspi
.ParseChallenge(&first_challenge
));
151 std::string auth_token
;
152 EXPECT_EQ(OK
, auth_sspi
.GenerateAuthToken(NULL
, "HTTP/intranet.google.com",
154 base::Bind(&UnexpectedCallback
)));
155 std::string second_challenge_text
= "Negotiate =happyjoy=";
156 HttpAuthChallengeTokenizer
second_challenge(second_challenge_text
.begin(),
157 second_challenge_text
.end());
158 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_INVALID
,
159 auth_sspi
.ParseChallenge(&second_challenge
));