OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 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 <set> | 5 #include <set> |
6 #include <string> | 6 #include <string> |
7 | 7 |
8 #include "base/memory/ref_counted.h" | 8 #include "base/memory/ref_counted.h" |
9 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
(...skipping 12 matching lines...) Expand all Loading... |
23 | 23 |
24 namespace net { | 24 namespace net { |
25 | 25 |
26 namespace { | 26 namespace { |
27 | 27 |
28 HttpAuthHandlerMock* CreateMockHandler(bool connection_based) { | 28 HttpAuthHandlerMock* CreateMockHandler(bool connection_based) { |
29 HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock(); | 29 HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock(); |
30 auth_handler->set_connection_based(connection_based); | 30 auth_handler->set_connection_based(connection_based); |
31 std::string challenge_text = "Basic"; | 31 std::string challenge_text = "Basic"; |
32 HttpAuthChallengeTokenizer challenge(challenge_text.begin(), | 32 HttpAuthChallengeTokenizer challenge(challenge_text.begin(), |
33 challenge_text.end()); | 33 challenge_text.end()); |
34 GURL origin("www.example.com"); | 34 GURL origin("www.example.com"); |
35 EXPECT_TRUE(auth_handler->InitFromChallenge(&challenge, | 35 EXPECT_TRUE(auth_handler->InitFromChallenge( |
36 HttpAuth::AUTH_SERVER, | 36 &challenge, HttpAuth::AUTH_SERVER, origin, BoundNetLog())); |
37 origin, | |
38 BoundNetLog())); | |
39 return auth_handler; | 37 return auth_handler; |
40 } | 38 } |
41 | 39 |
42 HttpResponseHeaders* HeadersFromResponseText(const std::string& response) { | 40 HttpResponseHeaders* HeadersFromResponseText(const std::string& response) { |
43 return new HttpResponseHeaders( | 41 return new HttpResponseHeaders( |
44 HttpUtil::AssembleRawHeaders(response.c_str(), response.length())); | 42 HttpUtil::AssembleRawHeaders(response.c_str(), response.length())); |
45 } | 43 } |
46 | 44 |
47 HttpAuth::AuthorizationResult HandleChallengeResponse( | 45 HttpAuth::AuthorizationResult HandleChallengeResponse( |
48 bool connection_based, | 46 bool connection_based, |
49 const std::string& headers_text, | 47 const std::string& headers_text, |
50 std::string* challenge_used) { | 48 std::string* challenge_used) { |
51 scoped_ptr<HttpAuthHandlerMock> mock_handler( | 49 scoped_ptr<HttpAuthHandlerMock> mock_handler( |
52 CreateMockHandler(connection_based)); | 50 CreateMockHandler(connection_based)); |
53 std::set<HttpAuth::Scheme> disabled_schemes; | 51 std::set<HttpAuth::Scheme> disabled_schemes; |
54 scoped_refptr<HttpResponseHeaders> headers( | 52 scoped_refptr<HttpResponseHeaders> headers( |
55 HeadersFromResponseText(headers_text)); | 53 HeadersFromResponseText(headers_text)); |
56 return HttpAuth::HandleChallengeResponse( | 54 return HttpAuth::HandleChallengeResponse(mock_handler.get(), |
57 mock_handler.get(), | 55 headers.get(), |
58 headers.get(), | 56 HttpAuth::AUTH_SERVER, |
59 HttpAuth::AUTH_SERVER, | 57 disabled_schemes, |
60 disabled_schemes, | 58 challenge_used); |
61 challenge_used); | |
62 } | 59 } |
63 | 60 |
64 } // namespace | 61 } // namespace |
65 | 62 |
66 TEST(HttpAuthTest, ChooseBestChallenge) { | 63 TEST(HttpAuthTest, ChooseBestChallenge) { |
67 static const struct { | 64 static const struct { |
68 const char* headers; | 65 const char* headers; |
69 HttpAuth::Scheme challenge_scheme; | 66 HttpAuth::Scheme challenge_scheme; |
70 const char* challenge_realm; | 67 const char* challenge_realm; |
71 } tests[] = { | 68 } tests[] = {{// Basic is the only challenge type, pick it. |
72 { | 69 "Y: Digest realm=\"X\", nonce=\"aaaaaaaaaa\"\n" |
73 // Basic is the only challenge type, pick it. | 70 "www-authenticate: Basic realm=\"BasicRealm\"\n", |
74 "Y: Digest realm=\"X\", nonce=\"aaaaaaaaaa\"\n" | 71 HttpAuth::AUTH_SCHEME_BASIC, "BasicRealm", |
75 "www-authenticate: Basic realm=\"BasicRealm\"\n", | 72 }, |
76 | 73 {// Fake is the only challenge type, but it is unsupported. |
77 HttpAuth::AUTH_SCHEME_BASIC, | 74 "Y: Digest realm=\"FooBar\", nonce=\"aaaaaaaaaa\"\n" |
78 "BasicRealm", | 75 "www-authenticate: Fake realm=\"FooBar\"\n", |
79 }, | 76 HttpAuth::AUTH_SCHEME_MAX, "", |
80 { | 77 }, |
81 // Fake is the only challenge type, but it is unsupported. | 78 {// Pick Digest over Basic. |
82 "Y: Digest realm=\"FooBar\", nonce=\"aaaaaaaaaa\"\n" | 79 "www-authenticate: Basic realm=\"FooBar\"\n" |
83 "www-authenticate: Fake realm=\"FooBar\"\n", | 80 "www-authenticate: Fake realm=\"FooBar\"\n" |
84 | 81 "www-authenticate: nonce=\"aaaaaaaaaa\"\n" |
85 HttpAuth::AUTH_SCHEME_MAX, | 82 "www-authenticate: Digest realm=\"DigestRealm\", " |
86 "", | 83 "nonce=\"aaaaaaaaaa\"\n", |
87 }, | 84 HttpAuth::AUTH_SCHEME_DIGEST, "DigestRealm", |
88 { | 85 }, |
89 // Pick Digest over Basic. | 86 {// Handle an empty header correctly. |
90 "www-authenticate: Basic realm=\"FooBar\"\n" | 87 "Y: Digest realm=\"X\", nonce=\"aaaaaaaaaa\"\n" |
91 "www-authenticate: Fake realm=\"FooBar\"\n" | 88 "www-authenticate:\n", |
92 "www-authenticate: nonce=\"aaaaaaaaaa\"\n" | 89 HttpAuth::AUTH_SCHEME_MAX, "", |
93 "www-authenticate: Digest realm=\"DigestRealm\", nonce=\"aaaaaaaaaa\"\n", | 90 }, |
94 | 91 { |
95 HttpAuth::AUTH_SCHEME_DIGEST, | 92 "WWW-Authenticate: Negotiate\n" |
96 "DigestRealm", | 93 "WWW-Authenticate: NTLM\n", |
97 }, | |
98 { | |
99 // Handle an empty header correctly. | |
100 "Y: Digest realm=\"X\", nonce=\"aaaaaaaaaa\"\n" | |
101 "www-authenticate:\n", | |
102 | |
103 HttpAuth::AUTH_SCHEME_MAX, | |
104 "", | |
105 }, | |
106 { | |
107 "WWW-Authenticate: Negotiate\n" | |
108 "WWW-Authenticate: NTLM\n", | |
109 | 94 |
110 #if defined(USE_KERBEROS) | 95 #if defined(USE_KERBEROS) |
111 // Choose Negotiate over NTLM on all platforms. | 96 // Choose Negotiate over NTLM on all platforms. |
112 // TODO(ahendrickson): This may be flaky on Linux and OSX as it | 97 // TODO(ahendrickson): This may be flaky on Linux and OSX as it |
113 // relies on being able to load one of the known .so files | 98 // relies on being able to load one of the known .so files |
114 // for gssapi. | 99 // for gssapi. |
115 HttpAuth::AUTH_SCHEME_NEGOTIATE, | 100 HttpAuth::AUTH_SCHEME_NEGOTIATE, |
116 #else | 101 #else |
117 // On systems that don't use Kerberos fall back to NTLM. | 102 // On systems that don't use Kerberos fall back to NTLM. |
118 HttpAuth::AUTH_SCHEME_NTLM, | 103 HttpAuth::AUTH_SCHEME_NTLM, |
119 #endif // defined(USE_KERBEROS) | 104 #endif // defined(USE_KERBEROS) |
120 "", | 105 "", |
121 } | 106 }}; |
122 }; | |
123 GURL origin("http://www.example.com"); | 107 GURL origin("http://www.example.com"); |
124 std::set<HttpAuth::Scheme> disabled_schemes; | 108 std::set<HttpAuth::Scheme> disabled_schemes; |
125 MockAllowURLSecurityManager url_security_manager; | 109 MockAllowURLSecurityManager url_security_manager; |
126 scoped_ptr<HostResolver> host_resolver(new MockHostResolver()); | 110 scoped_ptr<HostResolver> host_resolver(new MockHostResolver()); |
127 scoped_ptr<HttpAuthHandlerRegistryFactory> http_auth_handler_factory( | 111 scoped_ptr<HttpAuthHandlerRegistryFactory> http_auth_handler_factory( |
128 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())); | 112 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())); |
129 http_auth_handler_factory->SetURLSecurityManager( | 113 http_auth_handler_factory->SetURLSecurityManager("negotiate", |
130 "negotiate", &url_security_manager); | 114 &url_security_manager); |
131 | 115 |
132 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { | 116 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { |
133 // Make a HttpResponseHeaders object. | 117 // Make a HttpResponseHeaders object. |
134 std::string headers_with_status_line("HTTP/1.1 401 Unauthorized\n"); | 118 std::string headers_with_status_line("HTTP/1.1 401 Unauthorized\n"); |
135 headers_with_status_line += tests[i].headers; | 119 headers_with_status_line += tests[i].headers; |
136 scoped_refptr<HttpResponseHeaders> headers( | 120 scoped_refptr<HttpResponseHeaders> headers( |
137 HeadersFromResponseText(headers_with_status_line)); | 121 HeadersFromResponseText(headers_with_status_line)); |
138 | 122 |
139 scoped_ptr<HttpAuthHandler> handler; | 123 scoped_ptr<HttpAuthHandler> handler; |
140 HttpAuth::ChooseBestChallenge(http_auth_handler_factory.get(), | 124 HttpAuth::ChooseBestChallenge(http_auth_handler_factory.get(), |
(...skipping 15 matching lines...) Expand all Loading... |
156 } | 140 } |
157 | 141 |
158 TEST(HttpAuthTest, HandleChallengeResponse) { | 142 TEST(HttpAuthTest, HandleChallengeResponse) { |
159 std::string challenge_used; | 143 std::string challenge_used; |
160 const char* const kMockChallenge = | 144 const char* const kMockChallenge = |
161 "HTTP/1.1 401 Unauthorized\n" | 145 "HTTP/1.1 401 Unauthorized\n" |
162 "WWW-Authenticate: Mock token_here\n"; | 146 "WWW-Authenticate: Mock token_here\n"; |
163 const char* const kBasicChallenge = | 147 const char* const kBasicChallenge = |
164 "HTTP/1.1 401 Unauthorized\n" | 148 "HTTP/1.1 401 Unauthorized\n" |
165 "WWW-Authenticate: Basic realm=\"happy\"\n"; | 149 "WWW-Authenticate: Basic realm=\"happy\"\n"; |
166 const char* const kMissingChallenge = | 150 const char* const kMissingChallenge = "HTTP/1.1 401 Unauthorized\n"; |
167 "HTTP/1.1 401 Unauthorized\n"; | |
168 const char* const kEmptyChallenge = | 151 const char* const kEmptyChallenge = |
169 "HTTP/1.1 401 Unauthorized\n" | 152 "HTTP/1.1 401 Unauthorized\n" |
170 "WWW-Authenticate: \n"; | 153 "WWW-Authenticate: \n"; |
171 const char* const kBasicAndMockChallenges = | 154 const char* const kBasicAndMockChallenges = |
172 "HTTP/1.1 401 Unauthorized\n" | 155 "HTTP/1.1 401 Unauthorized\n" |
173 "WWW-Authenticate: Basic realm=\"happy\"\n" | 156 "WWW-Authenticate: Basic realm=\"happy\"\n" |
174 "WWW-Authenticate: Mock token_here\n"; | 157 "WWW-Authenticate: Mock token_here\n"; |
175 const char* const kTwoMockChallenges = | 158 const char* const kTwoMockChallenges = |
176 "HTTP/1.1 401 Unauthorized\n" | 159 "HTTP/1.1 401 Unauthorized\n" |
177 "WWW-Authenticate: Mock token_a\n" | 160 "WWW-Authenticate: Mock token_a\n" |
178 "WWW-Authenticate: Mock token_b\n"; | 161 "WWW-Authenticate: Mock token_b\n"; |
179 | 162 |
180 // Request based schemes should treat any new challenges as rejections of the | 163 // Request based schemes should treat any new challenges as rejections of the |
181 // previous authentication attempt. (There is a slight exception for digest | 164 // previous authentication attempt. (There is a slight exception for digest |
182 // authentication and the stale parameter, but that is covered in the | 165 // authentication and the stale parameter, but that is covered in the |
183 // http_auth_handler_digest_unittests). | 166 // http_auth_handler_digest_unittests). |
184 EXPECT_EQ( | 167 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_REJECT, |
185 HttpAuth::AUTHORIZATION_RESULT_REJECT, | 168 HandleChallengeResponse(false, kMockChallenge, &challenge_used)); |
186 HandleChallengeResponse(false, kMockChallenge, &challenge_used)); | |
187 EXPECT_EQ("Mock token_here", challenge_used); | 169 EXPECT_EQ("Mock token_here", challenge_used); |
188 | 170 |
189 EXPECT_EQ( | 171 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_REJECT, |
190 HttpAuth::AUTHORIZATION_RESULT_REJECT, | 172 HandleChallengeResponse(false, kBasicChallenge, &challenge_used)); |
191 HandleChallengeResponse(false, kBasicChallenge, &challenge_used)); | 173 EXPECT_EQ("", challenge_used); |
| 174 |
| 175 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_REJECT, |
| 176 HandleChallengeResponse(false, kMissingChallenge, &challenge_used)); |
| 177 EXPECT_EQ("", challenge_used); |
| 178 |
| 179 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_REJECT, |
| 180 HandleChallengeResponse(false, kEmptyChallenge, &challenge_used)); |
192 EXPECT_EQ("", challenge_used); | 181 EXPECT_EQ("", challenge_used); |
193 | 182 |
194 EXPECT_EQ( | 183 EXPECT_EQ( |
195 HttpAuth::AUTHORIZATION_RESULT_REJECT, | |
196 HandleChallengeResponse(false, kMissingChallenge, &challenge_used)); | |
197 EXPECT_EQ("", challenge_used); | |
198 | |
199 EXPECT_EQ( | |
200 HttpAuth::AUTHORIZATION_RESULT_REJECT, | |
201 HandleChallengeResponse(false, kEmptyChallenge, &challenge_used)); | |
202 EXPECT_EQ("", challenge_used); | |
203 | |
204 EXPECT_EQ( | |
205 HttpAuth::AUTHORIZATION_RESULT_REJECT, | 184 HttpAuth::AUTHORIZATION_RESULT_REJECT, |
206 HandleChallengeResponse(false, kBasicAndMockChallenges, &challenge_used)); | 185 HandleChallengeResponse(false, kBasicAndMockChallenges, &challenge_used)); |
207 EXPECT_EQ("Mock token_here", challenge_used); | 186 EXPECT_EQ("Mock token_here", challenge_used); |
208 | 187 |
209 EXPECT_EQ( | 188 EXPECT_EQ( |
210 HttpAuth::AUTHORIZATION_RESULT_REJECT, | 189 HttpAuth::AUTHORIZATION_RESULT_REJECT, |
211 HandleChallengeResponse(false, kTwoMockChallenges, &challenge_used)); | 190 HandleChallengeResponse(false, kTwoMockChallenges, &challenge_used)); |
212 EXPECT_EQ("Mock token_a", challenge_used); | 191 EXPECT_EQ("Mock token_a", challenge_used); |
213 | 192 |
214 // Connection based schemes will treat new auth challenges for the same scheme | 193 // Connection based schemes will treat new auth challenges for the same scheme |
215 // as acceptance (and continuance) of the current approach. If there are | 194 // as acceptance (and continuance) of the current approach. If there are |
216 // no auth challenges for the same scheme, the response will be treated as | 195 // no auth challenges for the same scheme, the response will be treated as |
217 // a rejection. | 196 // a rejection. |
218 EXPECT_EQ( | 197 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT, |
219 HttpAuth::AUTHORIZATION_RESULT_ACCEPT, | 198 HandleChallengeResponse(true, kMockChallenge, &challenge_used)); |
220 HandleChallengeResponse(true, kMockChallenge, &challenge_used)); | |
221 EXPECT_EQ("Mock token_here", challenge_used); | 199 EXPECT_EQ("Mock token_here", challenge_used); |
222 | 200 |
223 EXPECT_EQ( | 201 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_REJECT, |
224 HttpAuth::AUTHORIZATION_RESULT_REJECT, | 202 HandleChallengeResponse(true, kBasicChallenge, &challenge_used)); |
225 HandleChallengeResponse(true, kBasicChallenge, &challenge_used)); | 203 EXPECT_EQ("", challenge_used); |
| 204 |
| 205 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_REJECT, |
| 206 HandleChallengeResponse(true, kMissingChallenge, &challenge_used)); |
| 207 EXPECT_EQ("", challenge_used); |
| 208 |
| 209 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_REJECT, |
| 210 HandleChallengeResponse(true, kEmptyChallenge, &challenge_used)); |
226 EXPECT_EQ("", challenge_used); | 211 EXPECT_EQ("", challenge_used); |
227 | 212 |
228 EXPECT_EQ( | 213 EXPECT_EQ( |
229 HttpAuth::AUTHORIZATION_RESULT_REJECT, | |
230 HandleChallengeResponse(true, kMissingChallenge, &challenge_used)); | |
231 EXPECT_EQ("", challenge_used); | |
232 | |
233 EXPECT_EQ( | |
234 HttpAuth::AUTHORIZATION_RESULT_REJECT, | |
235 HandleChallengeResponse(true, kEmptyChallenge, &challenge_used)); | |
236 EXPECT_EQ("", challenge_used); | |
237 | |
238 EXPECT_EQ( | |
239 HttpAuth::AUTHORIZATION_RESULT_ACCEPT, | 214 HttpAuth::AUTHORIZATION_RESULT_ACCEPT, |
240 HandleChallengeResponse(true, kBasicAndMockChallenges, &challenge_used)); | 215 HandleChallengeResponse(true, kBasicAndMockChallenges, &challenge_used)); |
241 EXPECT_EQ("Mock token_here", challenge_used); | 216 EXPECT_EQ("Mock token_here", challenge_used); |
242 | 217 |
243 EXPECT_EQ( | 218 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT, |
244 HttpAuth::AUTHORIZATION_RESULT_ACCEPT, | 219 HandleChallengeResponse(true, kTwoMockChallenges, &challenge_used)); |
245 HandleChallengeResponse(true, kTwoMockChallenges, &challenge_used)); | |
246 EXPECT_EQ("Mock token_a", challenge_used); | 220 EXPECT_EQ("Mock token_a", challenge_used); |
247 } | 221 } |
248 | 222 |
249 TEST(HttpAuthTest, GetChallengeHeaderName) { | 223 TEST(HttpAuthTest, GetChallengeHeaderName) { |
250 std::string name; | 224 std::string name; |
251 | 225 |
252 name = HttpAuth::GetChallengeHeaderName(HttpAuth::AUTH_SERVER); | 226 name = HttpAuth::GetChallengeHeaderName(HttpAuth::AUTH_SERVER); |
253 EXPECT_STREQ("WWW-Authenticate", name.c_str()); | 227 EXPECT_STREQ("WWW-Authenticate", name.c_str()); |
254 | 228 |
255 name = HttpAuth::GetChallengeHeaderName(HttpAuth::AUTH_PROXY); | 229 name = HttpAuth::GetChallengeHeaderName(HttpAuth::AUTH_PROXY); |
256 EXPECT_STREQ("Proxy-Authenticate", name.c_str()); | 230 EXPECT_STREQ("Proxy-Authenticate", name.c_str()); |
257 } | 231 } |
258 | 232 |
259 TEST(HttpAuthTest, GetAuthorizationHeaderName) { | 233 TEST(HttpAuthTest, GetAuthorizationHeaderName) { |
260 std::string name; | 234 std::string name; |
261 | 235 |
262 name = HttpAuth::GetAuthorizationHeaderName(HttpAuth::AUTH_SERVER); | 236 name = HttpAuth::GetAuthorizationHeaderName(HttpAuth::AUTH_SERVER); |
263 EXPECT_STREQ("Authorization", name.c_str()); | 237 EXPECT_STREQ("Authorization", name.c_str()); |
264 | 238 |
265 name = HttpAuth::GetAuthorizationHeaderName(HttpAuth::AUTH_PROXY); | 239 name = HttpAuth::GetAuthorizationHeaderName(HttpAuth::AUTH_PROXY); |
266 EXPECT_STREQ("Proxy-Authorization", name.c_str()); | 240 EXPECT_STREQ("Proxy-Authorization", name.c_str()); |
267 } | 241 } |
268 | 242 |
269 } // namespace net | 243 } // namespace net |
OLD | NEW |