| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/http/http_auth_gssapi_posix.h" | 5 #include "net/http/http_auth_gssapi_posix.h" |
| 6 | 6 |
| 7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/native_library.h" | 9 #include "base/native_library.h" |
| 10 #include "base/scoped_ptr.h" | 10 #include "base/scoped_ptr.h" |
| 11 #include "net/base/net_errors.h" |
| 11 #include "net/http/mock_gssapi_library_posix.h" | 12 #include "net/http/mock_gssapi_library_posix.h" |
| 12 #include "testing/gtest/include/gtest/gtest.h" | 13 #include "testing/gtest/include/gtest/gtest.h" |
| 13 | 14 |
| 14 namespace net { | 15 namespace net { |
| 15 | 16 |
| 16 namespace { | 17 namespace { |
| 17 | 18 |
| 18 // gss_buffer_t helpers. | 19 // gss_buffer_t helpers. |
| 19 void ClearBuffer(gss_buffer_t dest) { | 20 void ClearBuffer(gss_buffer_t dest) { |
| 20 if (!dest) | 21 if (!dest) |
| (...skipping 18 matching lines...) Expand all Loading... |
| 39 | 40 |
| 40 void CopyBuffer(gss_buffer_t dest, const gss_buffer_t src) { | 41 void CopyBuffer(gss_buffer_t dest, const gss_buffer_t src) { |
| 41 if (!dest) | 42 if (!dest) |
| 42 return; | 43 return; |
| 43 ClearBuffer(dest); | 44 ClearBuffer(dest); |
| 44 if (!src) | 45 if (!src) |
| 45 return; | 46 return; |
| 46 SetBuffer(dest, src->value, src->length); | 47 SetBuffer(dest, src->value, src->length); |
| 47 } | 48 } |
| 48 | 49 |
| 50 const char kInitialAuthResponse[] = "Mary had a little lamb"; |
| 51 |
| 52 void EstablishInitialContext(test::MockGSSAPILibrary* library) { |
| 53 test::GssContextMockImpl context_info( |
| 54 "localhost", // Source name |
| 55 "example.com", // Target name |
| 56 23, // Lifetime |
| 57 *GSS_C_NT_HOSTBASED_SERVICE, // Mechanism |
| 58 0, // Context flags |
| 59 1, // Locally initiated |
| 60 0); // Open |
| 61 gss_buffer_desc in_buffer = {0, NULL}; |
| 62 gss_buffer_desc out_buffer = {arraysize(kInitialAuthResponse), |
| 63 const_cast<char*>(kInitialAuthResponse)}; |
| 64 library->ExpectSecurityContext( |
| 65 "Negotiate", |
| 66 GSS_S_CONTINUE_NEEDED, |
| 67 0, |
| 68 context_info, |
| 69 in_buffer, |
| 70 out_buffer); |
| 71 } |
| 72 |
| 49 } // namespace | 73 } // namespace |
| 50 | 74 |
| 51 TEST(HttpAuthGSSAPIPOSIXTest, GSSAPIStartup) { | 75 TEST(HttpAuthGSSAPIPOSIXTest, GSSAPIStartup) { |
| 52 // TODO(ahendrickson): Manipulate the libraries and paths to test each of the | 76 // TODO(ahendrickson): Manipulate the libraries and paths to test each of the |
| 53 // libraries we expect, and also whether or not they have the interface | 77 // libraries we expect, and also whether or not they have the interface |
| 54 // functions we want. | 78 // functions we want. |
| 55 GSSAPILibrary* gssapi = GSSAPILibrary::GetDefault(); | 79 GSSAPILibrary* gssapi = GSSAPILibrary::GetDefault(); |
| 56 DCHECK(gssapi); | 80 DCHECK(gssapi); |
| 57 gssapi->Init(); | 81 gssapi->Init(); |
| 58 } | 82 } |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 137 &time_rec); | 161 &time_rec); |
| 138 CopyBuffer(&input_token, &output_token); | 162 CopyBuffer(&input_token, &output_token); |
| 139 ClearBuffer(&output_token); | 163 ClearBuffer(&output_token); |
| 140 } | 164 } |
| 141 ClearBuffer(&input_token); | 165 ClearBuffer(&input_token); |
| 142 major_status = mock_library->delete_sec_context(&minor_status, | 166 major_status = mock_library->delete_sec_context(&minor_status, |
| 143 &context_handle, | 167 &context_handle, |
| 144 GSS_C_NO_BUFFER); | 168 GSS_C_NO_BUFFER); |
| 145 } | 169 } |
| 146 | 170 |
| 171 TEST(HttpAuthGSSAPITest, ParseChallenge_FirstRound) { |
| 172 // The first round should just consist of an unadorned "Negotiate" header. |
| 173 test::MockGSSAPILibrary mock_library; |
| 174 HttpAuthGSSAPI auth_gssapi(&mock_library, "Negotiate", |
| 175 CHROME_GSS_KRB5_MECH_OID_DESC); |
| 176 std::string challenge_text = "Negotiate"; |
| 177 HttpAuth::ChallengeTokenizer challenge(challenge_text.begin(), |
| 178 challenge_text.end()); |
| 179 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT, |
| 180 auth_gssapi.ParseChallenge(&challenge)); |
| 181 } |
| 182 |
| 183 TEST(HttpAuthGSSAPITest, ParseChallenge_TwoRounds) { |
| 184 // The first round should just have "Negotiate", and the second round should |
| 185 // have a valid base64 token associated with it. |
| 186 test::MockGSSAPILibrary mock_library; |
| 187 HttpAuthGSSAPI auth_gssapi(&mock_library, "Negotiate", |
| 188 CHROME_GSS_KRB5_MECH_OID_DESC); |
| 189 std::string first_challenge_text = "Negotiate"; |
| 190 HttpAuth::ChallengeTokenizer first_challenge(first_challenge_text.begin(), |
| 191 first_challenge_text.end()); |
| 192 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT, |
| 193 auth_gssapi.ParseChallenge(&first_challenge)); |
| 194 |
| 195 // Generate an auth token and create another thing. |
| 196 EstablishInitialContext(&mock_library); |
| 197 std::string auth_token; |
| 198 EXPECT_EQ(OK, auth_gssapi.GenerateAuthToken(NULL, NULL, |
| 199 L"HTTP/intranet.google.com", |
| 200 &auth_token)); |
| 201 |
| 202 std::string second_challenge_text = "Negotiate Zm9vYmFy"; |
| 203 HttpAuth::ChallengeTokenizer second_challenge(second_challenge_text.begin(), |
| 204 second_challenge_text.end()); |
| 205 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT, |
| 206 auth_gssapi.ParseChallenge(&second_challenge)); |
| 207 } |
| 208 |
| 209 TEST(HttpAuthGSSAPITest, ParseChallenge_UnexpectedTokenFirstRound) { |
| 210 // If the first round challenge has an additional authentication token, it |
| 211 // should be treated as an invalid challenge from the server. |
| 212 test::MockGSSAPILibrary mock_library; |
| 213 HttpAuthGSSAPI auth_gssapi(&mock_library, "Negotiate", |
| 214 CHROME_GSS_KRB5_MECH_OID_DESC); |
| 215 std::string challenge_text = "Negotiate Zm9vYmFy"; |
| 216 HttpAuth::ChallengeTokenizer challenge(challenge_text.begin(), |
| 217 challenge_text.end()); |
| 218 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_INVALID, |
| 219 auth_gssapi.ParseChallenge(&challenge)); |
| 220 } |
| 221 |
| 222 TEST(HttpAuthGSSAPITest, ParseChallenge_MissingTokenSecondRound) { |
| 223 // If a later-round challenge is simply "Negotiate", it should be treated as |
| 224 // an authentication challenge rejection from the server or proxy. |
| 225 test::MockGSSAPILibrary mock_library; |
| 226 HttpAuthGSSAPI auth_gssapi(&mock_library, "Negotiate", |
| 227 CHROME_GSS_KRB5_MECH_OID_DESC); |
| 228 std::string first_challenge_text = "Negotiate"; |
| 229 HttpAuth::ChallengeTokenizer first_challenge(first_challenge_text.begin(), |
| 230 first_challenge_text.end()); |
| 231 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT, |
| 232 auth_gssapi.ParseChallenge(&first_challenge)); |
| 233 |
| 234 EstablishInitialContext(&mock_library); |
| 235 std::string auth_token; |
| 236 EXPECT_EQ(OK, auth_gssapi.GenerateAuthToken(NULL, NULL, |
| 237 L"HTTP/intranet.google.com", |
| 238 &auth_token)); |
| 239 std::string second_challenge_text = "Negotiate"; |
| 240 HttpAuth::ChallengeTokenizer second_challenge(second_challenge_text.begin(), |
| 241 second_challenge_text.end()); |
| 242 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_REJECT, |
| 243 auth_gssapi.ParseChallenge(&second_challenge)); |
| 244 } |
| 245 |
| 246 TEST(HttpAuthGSSAPITest, ParseChallenge_NonBase64EncodedToken) { |
| 247 // If a later-round challenge has an invalid base64 encoded token, it should |
| 248 // be treated as an invalid challenge. |
| 249 test::MockGSSAPILibrary mock_library; |
| 250 HttpAuthGSSAPI auth_gssapi(&mock_library, "Negotiate", |
| 251 CHROME_GSS_KRB5_MECH_OID_DESC); |
| 252 std::string first_challenge_text = "Negotiate"; |
| 253 HttpAuth::ChallengeTokenizer first_challenge(first_challenge_text.begin(), |
| 254 first_challenge_text.end()); |
| 255 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT, |
| 256 auth_gssapi.ParseChallenge(&first_challenge)); |
| 257 |
| 258 EstablishInitialContext(&mock_library); |
| 259 std::string auth_token; |
| 260 EXPECT_EQ(OK, auth_gssapi.GenerateAuthToken(NULL, NULL, |
| 261 L"HTTP/intranet.google.com", |
| 262 &auth_token)); |
| 263 std::string second_challenge_text = "Negotiate =happyjoy="; |
| 264 HttpAuth::ChallengeTokenizer second_challenge(second_challenge_text.begin(), |
| 265 second_challenge_text.end()); |
| 266 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_INVALID, |
| 267 auth_gssapi.ParseChallenge(&second_challenge)); |
| 268 } |
| 269 |
| 147 } // namespace net | 270 } // namespace net |
| OLD | NEW |