Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / net / http / http_auth_unittest.cc
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.
4
5 #include <set>
6 #include <string>
7
8 #include "base/memory/ref_counted.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/strings/string_util.h"
11 #include "net/base/net_errors.h"
12 #include "net/dns/mock_host_resolver.h"
13 #include "net/http/http_auth.h"
14 #include "net/http/http_auth_challenge_tokenizer.h"
15 #include "net/http/http_auth_filter.h"
16 #include "net/http/http_auth_handler.h"
17 #include "net/http/http_auth_handler_factory.h"
18 #include "net/http/http_auth_handler_mock.h"
19 #include "net/http/http_response_headers.h"
20 #include "net/http/http_util.h"
21 #include "net/http/mock_allow_url_security_manager.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23
24 namespace net {
25
26 namespace {
27
28 HttpAuthHandlerMock* CreateMockHandler(bool connection_based) {
29   HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock();
30   auth_handler->set_connection_based(connection_based);
31   std::string challenge_text = "Basic";
32   HttpAuthChallengeTokenizer challenge(challenge_text.begin(),
33                                          challenge_text.end());
34   GURL origin("www.example.com");
35   EXPECT_TRUE(auth_handler->InitFromChallenge(&challenge,
36                                               HttpAuth::AUTH_SERVER,
37                                               origin,
38                                               BoundNetLog()));
39   return auth_handler;
40 }
41
42 HttpResponseHeaders* HeadersFromResponseText(const std::string& response) {
43   return new HttpResponseHeaders(
44       HttpUtil::AssembleRawHeaders(response.c_str(), response.length()));
45 }
46
47 HttpAuth::AuthorizationResult HandleChallengeResponse(
48     bool connection_based,
49     const std::string& headers_text,
50     std::string* challenge_used) {
51   scoped_ptr<HttpAuthHandlerMock> mock_handler(
52       CreateMockHandler(connection_based));
53   std::set<HttpAuth::Scheme> disabled_schemes;
54   scoped_refptr<HttpResponseHeaders> headers(
55       HeadersFromResponseText(headers_text));
56   return HttpAuth::HandleChallengeResponse(
57       mock_handler.get(),
58       headers.get(),
59       HttpAuth::AUTH_SERVER,
60       disabled_schemes,
61       challenge_used);
62 }
63
64 }  // namespace
65
66 TEST(HttpAuthTest, ChooseBestChallenge) {
67   static const struct {
68     const char* headers;
69     HttpAuth::Scheme challenge_scheme;
70     const char* challenge_realm;
71   } tests[] = {
72     {
73       // Basic is the only challenge type, pick it.
74       "Y: Digest realm=\"X\", nonce=\"aaaaaaaaaa\"\n"
75       "www-authenticate: Basic realm=\"BasicRealm\"\n",
76
77       HttpAuth::AUTH_SCHEME_BASIC,
78       "BasicRealm",
79     },
80     {
81       // Fake is the only challenge type, but it is unsupported.
82       "Y: Digest realm=\"FooBar\", nonce=\"aaaaaaaaaa\"\n"
83       "www-authenticate: Fake realm=\"FooBar\"\n",
84
85       HttpAuth::AUTH_SCHEME_MAX,
86       "",
87     },
88     {
89       // Pick Digest over Basic.
90       "www-authenticate: Basic realm=\"FooBar\"\n"
91       "www-authenticate: Fake realm=\"FooBar\"\n"
92       "www-authenticate: nonce=\"aaaaaaaaaa\"\n"
93       "www-authenticate: Digest realm=\"DigestRealm\", nonce=\"aaaaaaaaaa\"\n",
94
95       HttpAuth::AUTH_SCHEME_DIGEST,
96       "DigestRealm",
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
110 #if defined(USE_KERBEROS)
111       // Choose Negotiate over NTLM on all platforms.
112       // 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
114       // for gssapi.
115       HttpAuth::AUTH_SCHEME_NEGOTIATE,
116 #else
117       // On systems that don't use Kerberos fall back to NTLM.
118       HttpAuth::AUTH_SCHEME_NTLM,
119 #endif  // defined(USE_KERBEROS)
120       "",
121     }
122   };
123   GURL origin("http://www.example.com");
124   std::set<HttpAuth::Scheme> disabled_schemes;
125   MockAllowURLSecurityManager url_security_manager;
126   scoped_ptr<HostResolver> host_resolver(new MockHostResolver());
127   scoped_ptr<HttpAuthHandlerRegistryFactory> http_auth_handler_factory(
128       HttpAuthHandlerFactory::CreateDefault(host_resolver.get()));
129   http_auth_handler_factory->SetURLSecurityManager(
130       "negotiate", &url_security_manager);
131
132   for (size_t i = 0; i < arraysize(tests); ++i) {
133     // Make a HttpResponseHeaders object.
134     std::string headers_with_status_line("HTTP/1.1 401 Unauthorized\n");
135     headers_with_status_line += tests[i].headers;
136     scoped_refptr<HttpResponseHeaders> headers(
137         HeadersFromResponseText(headers_with_status_line));
138
139     scoped_ptr<HttpAuthHandler> handler;
140     HttpAuth::ChooseBestChallenge(http_auth_handler_factory.get(),
141                                   headers.get(),
142                                   HttpAuth::AUTH_SERVER,
143                                   origin,
144                                   disabled_schemes,
145                                   BoundNetLog(),
146                                   &handler);
147
148     if (handler.get()) {
149       EXPECT_EQ(tests[i].challenge_scheme, handler->auth_scheme());
150       EXPECT_STREQ(tests[i].challenge_realm, handler->realm().c_str());
151     } else {
152       EXPECT_EQ(HttpAuth::AUTH_SCHEME_MAX, tests[i].challenge_scheme);
153       EXPECT_STREQ("", tests[i].challenge_realm);
154     }
155   }
156 }
157
158 TEST(HttpAuthTest, HandleChallengeResponse) {
159   std::string challenge_used;
160   const char* const kMockChallenge =
161       "HTTP/1.1 401 Unauthorized\n"
162       "WWW-Authenticate: Mock token_here\n";
163   const char* const kBasicChallenge =
164       "HTTP/1.1 401 Unauthorized\n"
165       "WWW-Authenticate: Basic realm=\"happy\"\n";
166   const char* const kMissingChallenge =
167       "HTTP/1.1 401 Unauthorized\n";
168   const char* const kEmptyChallenge =
169       "HTTP/1.1 401 Unauthorized\n"
170       "WWW-Authenticate: \n";
171   const char* const kBasicAndMockChallenges =
172       "HTTP/1.1 401 Unauthorized\n"
173       "WWW-Authenticate: Basic realm=\"happy\"\n"
174       "WWW-Authenticate: Mock token_here\n";
175   const char* const kTwoMockChallenges =
176       "HTTP/1.1 401 Unauthorized\n"
177       "WWW-Authenticate: Mock token_a\n"
178       "WWW-Authenticate: Mock token_b\n";
179
180   // Request based schemes should treat any new challenges as rejections of the
181   // previous authentication attempt. (There is a slight exception for digest
182   // authentication and the stale parameter, but that is covered in the
183   // http_auth_handler_digest_unittests).
184   EXPECT_EQ(
185       HttpAuth::AUTHORIZATION_RESULT_REJECT,
186       HandleChallengeResponse(false, kMockChallenge, &challenge_used));
187   EXPECT_EQ("Mock token_here", challenge_used);
188
189   EXPECT_EQ(
190       HttpAuth::AUTHORIZATION_RESULT_REJECT,
191       HandleChallengeResponse(false, kBasicChallenge, &challenge_used));
192   EXPECT_EQ("", challenge_used);
193
194   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,
206       HandleChallengeResponse(false, kBasicAndMockChallenges, &challenge_used));
207   EXPECT_EQ("Mock token_here", challenge_used);
208
209   EXPECT_EQ(
210       HttpAuth::AUTHORIZATION_RESULT_REJECT,
211       HandleChallengeResponse(false, kTwoMockChallenges, &challenge_used));
212   EXPECT_EQ("Mock token_a", challenge_used);
213
214   // Connection based schemes will treat new auth challenges for the same scheme
215   // 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
217   // a rejection.
218   EXPECT_EQ(
219       HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
220       HandleChallengeResponse(true, kMockChallenge, &challenge_used));
221   EXPECT_EQ("Mock token_here", challenge_used);
222
223   EXPECT_EQ(
224       HttpAuth::AUTHORIZATION_RESULT_REJECT,
225       HandleChallengeResponse(true, kBasicChallenge, &challenge_used));
226   EXPECT_EQ("", challenge_used);
227
228   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,
240       HandleChallengeResponse(true, kBasicAndMockChallenges, &challenge_used));
241   EXPECT_EQ("Mock token_here", challenge_used);
242
243   EXPECT_EQ(
244       HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
245       HandleChallengeResponse(true, kTwoMockChallenges, &challenge_used));
246   EXPECT_EQ("Mock token_a", challenge_used);
247 }
248
249 TEST(HttpAuthTest, GetChallengeHeaderName) {
250   std::string name;
251
252   name = HttpAuth::GetChallengeHeaderName(HttpAuth::AUTH_SERVER);
253   EXPECT_STREQ("WWW-Authenticate", name.c_str());
254
255   name = HttpAuth::GetChallengeHeaderName(HttpAuth::AUTH_PROXY);
256   EXPECT_STREQ("Proxy-Authenticate", name.c_str());
257 }
258
259 TEST(HttpAuthTest, GetAuthorizationHeaderName) {
260   std::string name;
261
262   name = HttpAuth::GetAuthorizationHeaderName(HttpAuth::AUTH_SERVER);
263   EXPECT_STREQ("Authorization", name.c_str());
264
265   name = HttpAuth::GetAuthorizationHeaderName(HttpAuth::AUTH_PROXY);
266   EXPECT_STREQ("Proxy-Authorization", name.c_str());
267 }
268
269 }  // namespace net