OLD | NEW |
| (Empty) |
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 "net/http/http_auth_handler_basic.h" | |
6 | |
7 #include <string> | |
8 | |
9 #include "base/base64.h" | |
10 #include "base/strings/string_util.h" | |
11 #include "base/strings/utf_string_conversions.h" | |
12 #include "net/base/net_errors.h" | |
13 #include "net/base/net_string_util.h" | |
14 #include "net/http/http_auth.h" | |
15 #include "net/http/http_auth_challenge_tokenizer.h" | |
16 | |
17 namespace net { | |
18 | |
19 namespace { | |
20 | |
21 // Parses a realm from an auth challenge, and converts to UTF8-encoding. | |
22 // Returns whether the realm is invalid or the parameters are invalid. | |
23 // | |
24 // Note that if a realm was not specified, we will default it to ""; | |
25 // so specifying 'Basic realm=""' is equivalent to 'Basic'. | |
26 // | |
27 // This is more generous than RFC 2617, which is pretty clear in the | |
28 // production of challenge that realm is required. | |
29 // | |
30 // We allow it to be compatibility with certain embedded webservers that don't | |
31 // include a realm (see http://crbug.com/20984.) | |
32 // | |
33 // The over-the-wire realm is encoded as ISO-8859-1 (aka Latin-1). | |
34 // | |
35 // TODO(cbentzel): Realm may need to be decoded using RFC 2047 rules as | |
36 // well, see http://crbug.com/25790. | |
37 bool ParseRealm(const HttpAuthChallengeTokenizer& tokenizer, | |
38 std::string* realm) { | |
39 CHECK(realm); | |
40 realm->clear(); | |
41 HttpUtil::NameValuePairsIterator parameters = tokenizer.param_pairs(); | |
42 while (parameters.GetNext()) { | |
43 if (!LowerCaseEqualsASCII(parameters.name(), "realm")) | |
44 continue; | |
45 | |
46 if (!net::ConvertToUtf8AndNormalize(parameters.value(), kCharsetLatin1, | |
47 realm)) { | |
48 return false; | |
49 } | |
50 } | |
51 return parameters.valid(); | |
52 } | |
53 | |
54 } // namespace | |
55 | |
56 bool HttpAuthHandlerBasic::Init(HttpAuthChallengeTokenizer* challenge) { | |
57 auth_scheme_ = HttpAuth::AUTH_SCHEME_BASIC; | |
58 score_ = 1; | |
59 properties_ = 0; | |
60 return ParseChallenge(challenge); | |
61 } | |
62 | |
63 bool HttpAuthHandlerBasic::ParseChallenge( | |
64 HttpAuthChallengeTokenizer* challenge) { | |
65 // Verify the challenge's auth-scheme. | |
66 if (!LowerCaseEqualsASCII(challenge->scheme(), "basic")) | |
67 return false; | |
68 | |
69 std::string realm; | |
70 if (!ParseRealm(*challenge, &realm)) | |
71 return false; | |
72 | |
73 realm_ = realm; | |
74 return true; | |
75 } | |
76 | |
77 HttpAuth::AuthorizationResult HttpAuthHandlerBasic::HandleAnotherChallenge( | |
78 HttpAuthChallengeTokenizer* challenge) { | |
79 // Basic authentication is always a single round, so any responses | |
80 // should be treated as a rejection. However, if the new challenge | |
81 // is for a different realm, then indicate the realm change. | |
82 std::string realm; | |
83 if (!ParseRealm(*challenge, &realm)) | |
84 return HttpAuth::AUTHORIZATION_RESULT_INVALID; | |
85 return (realm_ != realm)? | |
86 HttpAuth::AUTHORIZATION_RESULT_DIFFERENT_REALM: | |
87 HttpAuth::AUTHORIZATION_RESULT_REJECT; | |
88 } | |
89 | |
90 int HttpAuthHandlerBasic::GenerateAuthTokenImpl( | |
91 const AuthCredentials* credentials, const HttpRequestInfo*, | |
92 const CompletionCallback&, std::string* auth_token) { | |
93 DCHECK(credentials); | |
94 // TODO(eroman): is this the right encoding of username/password? | |
95 std::string base64_username_password; | |
96 base::Base64Encode(base::UTF16ToUTF8(credentials->username()) + ":" + | |
97 base::UTF16ToUTF8(credentials->password()), | |
98 &base64_username_password); | |
99 *auth_token = "Basic " + base64_username_password; | |
100 return OK; | |
101 } | |
102 | |
103 HttpAuthHandlerBasic::Factory::Factory() { | |
104 } | |
105 | |
106 HttpAuthHandlerBasic::Factory::~Factory() { | |
107 } | |
108 | |
109 int HttpAuthHandlerBasic::Factory::CreateAuthHandler( | |
110 HttpAuthChallengeTokenizer* challenge, | |
111 HttpAuth::Target target, | |
112 const GURL& origin, | |
113 CreateReason reason, | |
114 int digest_nonce_count, | |
115 const BoundNetLog& net_log, | |
116 scoped_ptr<HttpAuthHandler>* handler) { | |
117 // TODO(cbentzel): Move towards model of parsing in the factory | |
118 // method and only constructing when valid. | |
119 scoped_ptr<HttpAuthHandler> tmp_handler(new HttpAuthHandlerBasic()); | |
120 if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log)) | |
121 return ERR_INVALID_RESPONSE; | |
122 handler->swap(tmp_handler); | |
123 return OK; | |
124 } | |
125 | |
126 } // namespace net | |
OLD | NEW |