| 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 "net/http/http_auth_handler_digest.h" | 5 #include "net/http/http_auth_handler_digest.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/md5.h" | 10 #include "base/md5.h" |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 85 | 85 |
| 86 HttpAuthHandlerDigest::Factory::~Factory() { | 86 HttpAuthHandlerDigest::Factory::~Factory() { |
| 87 } | 87 } |
| 88 | 88 |
| 89 void HttpAuthHandlerDigest::Factory::set_nonce_generator( | 89 void HttpAuthHandlerDigest::Factory::set_nonce_generator( |
| 90 const NonceGenerator* nonce_generator) { | 90 const NonceGenerator* nonce_generator) { |
| 91 nonce_generator_.reset(nonce_generator); | 91 nonce_generator_.reset(nonce_generator); |
| 92 } | 92 } |
| 93 | 93 |
| 94 int HttpAuthHandlerDigest::Factory::CreateAuthHandler( | 94 int HttpAuthHandlerDigest::Factory::CreateAuthHandler( |
| 95 HttpAuthChallengeTokenizer* challenge, | 95 const HttpAuthChallengeTokenizer& challenge, |
| 96 HttpAuth::Target target, | 96 HttpAuth::Target target, |
| 97 const GURL& origin, | 97 const GURL& origin, |
| 98 CreateReason reason, | 98 CreateReason reason, |
| 99 int digest_nonce_count, | 99 int digest_nonce_count, |
| 100 const BoundNetLog& net_log, | 100 const BoundNetLog& net_log, |
| 101 scoped_ptr<HttpAuthHandler>* handler) { | 101 scoped_ptr<HttpAuthHandler>* handler) { |
| 102 // TODO(cbentzel): Move towards model of parsing in the factory | 102 // TODO(cbentzel): Move towards model of parsing in the factory |
| 103 // method and only constructing when valid. | 103 // method and only constructing when valid. |
| 104 scoped_ptr<HttpAuthHandler> tmp_handler( | 104 scoped_ptr<HttpAuthHandler> tmp_handler( |
| 105 new HttpAuthHandlerDigest(digest_nonce_count, nonce_generator_.get())); | 105 new HttpAuthHandlerDigest(digest_nonce_count, nonce_generator_.get())); |
| 106 if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log)) | 106 int result = |
| 107 return ERR_INVALID_RESPONSE; | 107 tmp_handler->HandleInitialChallenge(challenge, target, origin, net_log); |
| 108 handler->swap(tmp_handler); | 108 if (result == OK) |
| 109 return OK; | 109 handler->swap(tmp_handler); |
| 110 return result; |
| 110 } | 111 } |
| 111 | 112 |
| 112 HttpAuth::AuthorizationResult HttpAuthHandlerDigest::HandleAnotherChallenge( | 113 HttpAuth::AuthorizationResult HttpAuthHandlerDigest::HandleAnotherChallenge( |
| 113 HttpAuthChallengeTokenizer* challenge) { | 114 const HttpAuthChallengeTokenizer& challenge) { |
| 114 // Even though Digest is not connection based, a "second round" is parsed | 115 // Even though Digest is not connection based, a "second round" is parsed |
| 115 // to differentiate between stale and rejected responses. | 116 // to differentiate between stale and rejected responses. |
| 116 // Note that the state of the current handler is not mutated - this way if | 117 // Note that the state of the current handler is not mutated - this way if |
| 117 // there is a rejection the realm hasn't changed. | 118 // there is a rejection the realm hasn't changed. |
| 118 if (!challenge->SchemeIs(kDigestSchemeName)) | 119 if (!challenge.SchemeIs(kDigestSchemeName)) |
| 119 return HttpAuth::AUTHORIZATION_RESULT_INVALID; | 120 return HttpAuth::AUTHORIZATION_RESULT_INVALID; |
| 120 | 121 |
| 121 HttpUtil::NameValuePairsIterator parameters = challenge->param_pairs(); | 122 HttpUtil::NameValuePairsIterator parameters = challenge.param_pairs(); |
| 122 | 123 |
| 123 // Try to find the "stale" value, and also keep track of the realm | 124 // Try to find the "stale" value, and also keep track of the realm |
| 124 // for the new challenge. | 125 // for the new challenge. |
| 125 std::string original_realm; | 126 std::string original_realm; |
| 126 while (parameters.GetNext()) { | 127 while (parameters.GetNext()) { |
| 127 if (base::LowerCaseEqualsASCII(parameters.name(), "stale")) { | 128 if (base::LowerCaseEqualsASCII(parameters.name(), "stale")) { |
| 128 if (base::LowerCaseEqualsASCII(parameters.value(), "true")) | 129 if (base::LowerCaseEqualsASCII(parameters.value(), "true")) |
| 129 return HttpAuth::AUTHORIZATION_RESULT_STALE; | 130 return HttpAuth::AUTHORIZATION_RESULT_STALE; |
| 130 } else if (base::LowerCaseEqualsASCII(parameters.name(), "realm")) { | 131 } else if (base::LowerCaseEqualsASCII(parameters.name(), "realm")) { |
| 131 original_realm = parameters.value(); | 132 original_realm = parameters.value(); |
| 132 } | 133 } |
| 133 } | 134 } |
| 134 return (original_realm_ != original_realm) ? | 135 return (original_realm_ != original_realm) ? |
| 135 HttpAuth::AUTHORIZATION_RESULT_DIFFERENT_REALM : | 136 HttpAuth::AUTHORIZATION_RESULT_DIFFERENT_REALM : |
| 136 HttpAuth::AUTHORIZATION_RESULT_REJECT; | 137 HttpAuth::AUTHORIZATION_RESULT_REJECT; |
| 137 } | 138 } |
| 138 | 139 |
| 139 bool HttpAuthHandlerDigest::Init(HttpAuthChallengeTokenizer* challenge) { | 140 int HttpAuthHandlerDigest::Init(const HttpAuthChallengeTokenizer& challenge) { |
| 140 return ParseChallenge(challenge); | 141 return ParseChallenge(challenge) ? OK : ERR_INVALID_RESPONSE; |
| 141 } | 142 } |
| 142 | 143 |
| 143 int HttpAuthHandlerDigest::GenerateAuthTokenImpl( | 144 int HttpAuthHandlerDigest::GenerateAuthTokenImpl( |
| 144 const AuthCredentials* credentials, const HttpRequestInfo* request, | 145 const AuthCredentials* credentials, |
| 145 const CompletionCallback& callback, std::string* auth_token) { | 146 const HttpRequestInfo& request, |
| 147 const CompletionCallback& callback, |
| 148 std::string* auth_token) { |
| 146 // Generate a random client nonce. | 149 // Generate a random client nonce. |
| 147 std::string cnonce = nonce_generator_->GenerateNonce(); | 150 std::string cnonce = nonce_generator_->GenerateNonce(); |
| 148 | 151 |
| 149 // Extract the request method and path -- the meaning of 'path' is overloaded | 152 // Extract the request method and path -- the meaning of 'path' is overloaded |
| 150 // in certain cases, to be a hostname. | 153 // in certain cases, to be a hostname. |
| 151 std::string method; | 154 std::string method; |
| 152 std::string path; | 155 std::string path; |
| 153 GetRequestMethodAndPath(request, &method, &path); | 156 GetRequestMethodAndPath(request, &method, &path); |
| 154 | 157 |
| 155 *auth_token = AssembleCredentials(method, path, *credentials, | 158 *auth_token = AssembleCredentials(method, path, *credentials, |
| (...skipping 26 matching lines...) Expand all Loading... |
| 182 // [<extension-directive>] | 185 // [<extension-directive>] |
| 183 // | 186 // |
| 184 // Note that according to RFC 2617 (section 1.2) the realm is required. | 187 // Note that according to RFC 2617 (section 1.2) the realm is required. |
| 185 // However we allow it to be omitted, in which case it will default to the | 188 // However we allow it to be omitted, in which case it will default to the |
| 186 // empty string. | 189 // empty string. |
| 187 // | 190 // |
| 188 // This allowance is for better compatibility with webservers that fail to | 191 // This allowance is for better compatibility with webservers that fail to |
| 189 // send the realm (See http://crbug.com/20984 for an instance where a | 192 // send the realm (See http://crbug.com/20984 for an instance where a |
| 190 // webserver was not sending the realm with a BASIC challenge). | 193 // webserver was not sending the realm with a BASIC challenge). |
| 191 bool HttpAuthHandlerDigest::ParseChallenge( | 194 bool HttpAuthHandlerDigest::ParseChallenge( |
| 192 HttpAuthChallengeTokenizer* challenge) { | 195 const HttpAuthChallengeTokenizer& challenge) { |
| 193 auth_scheme_ = kDigestSchemeName; | 196 auth_scheme_ = kDigestSchemeName; |
| 194 | 197 |
| 195 // Initialize to defaults. | 198 // Initialize to defaults. |
| 196 stale_ = false; | 199 stale_ = false; |
| 197 algorithm_ = ALGORITHM_UNSPECIFIED; | 200 algorithm_ = ALGORITHM_UNSPECIFIED; |
| 198 qop_ = QOP_UNSPECIFIED; | 201 qop_ = QOP_UNSPECIFIED; |
| 199 realm_ = original_realm_ = nonce_ = domain_ = opaque_ = std::string(); | 202 realm_ = original_realm_ = nonce_ = domain_ = opaque_ = std::string(); |
| 200 | 203 |
| 201 // FAIL -- Couldn't match auth-scheme. | 204 // FAIL -- Couldn't match auth-scheme. |
| 202 if (!challenge->SchemeIs(kDigestSchemeName)) | 205 if (!challenge.SchemeIs(kDigestSchemeName)) |
| 203 return false; | 206 return false; |
| 204 | 207 |
| 205 HttpUtil::NameValuePairsIterator parameters = challenge->param_pairs(); | 208 HttpUtil::NameValuePairsIterator parameters = challenge.param_pairs(); |
| 206 | 209 |
| 207 // Loop through all the properties. | 210 // Loop through all the properties. |
| 208 while (parameters.GetNext()) { | 211 while (parameters.GetNext()) { |
| 209 // FAIL -- couldn't parse a property. | 212 // FAIL -- couldn't parse a property. |
| 210 if (!ParseChallengeProperty(parameters.name(), | 213 if (!ParseChallengeProperty(parameters.name(), |
| 211 parameters.value())) | 214 parameters.value())) |
| 212 return false; | 215 return false; |
| 213 } | 216 } |
| 214 | 217 |
| 215 // Check if tokenizer failed. | 218 // Check if tokenizer failed. |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 291 return "MD5"; | 294 return "MD5"; |
| 292 case ALGORITHM_MD5_SESS: | 295 case ALGORITHM_MD5_SESS: |
| 293 return "MD5-sess"; | 296 return "MD5-sess"; |
| 294 default: | 297 default: |
| 295 NOTREACHED(); | 298 NOTREACHED(); |
| 296 return std::string(); | 299 return std::string(); |
| 297 } | 300 } |
| 298 } | 301 } |
| 299 | 302 |
| 300 void HttpAuthHandlerDigest::GetRequestMethodAndPath( | 303 void HttpAuthHandlerDigest::GetRequestMethodAndPath( |
| 301 const HttpRequestInfo* request, | 304 const HttpRequestInfo& request, |
| 302 std::string* method, | 305 std::string* method, |
| 303 std::string* path) const { | 306 std::string* path) const { |
| 304 DCHECK(request); | 307 const GURL& url = request.url; |
| 305 | |
| 306 const GURL& url = request->url; | |
| 307 | 308 |
| 308 if (target_ == HttpAuth::AUTH_PROXY && | 309 if (target_ == HttpAuth::AUTH_PROXY && |
| 309 (url.SchemeIs("https") || url.SchemeIsWSOrWSS())) { | 310 (url.SchemeIs("https") || url.SchemeIsWSOrWSS())) { |
| 310 *method = "CONNECT"; | 311 *method = "CONNECT"; |
| 311 *path = GetHostAndPort(url); | 312 *path = GetHostAndPort(url); |
| 312 } else { | 313 } else { |
| 313 *method = request->method; | 314 *method = request.method; |
| 314 *path = url.PathForRequest(); | 315 *path = url.PathForRequest(); |
| 315 } | 316 } |
| 316 } | 317 } |
| 317 | 318 |
| 318 std::string HttpAuthHandlerDigest::AssembleResponseDigest( | 319 std::string HttpAuthHandlerDigest::AssembleResponseDigest( |
| 319 const std::string& method, | 320 const std::string& method, |
| 320 const std::string& path, | 321 const std::string& path, |
| 321 const AuthCredentials& credentials, | 322 const AuthCredentials& credentials, |
| 322 const std::string& cnonce, | 323 const std::string& cnonce, |
| 323 const std::string& nc) const { | 324 const std::string& nc) const { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 374 // TODO(eroman): Supposedly IIS server requires quotes surrounding qop. | 375 // TODO(eroman): Supposedly IIS server requires quotes surrounding qop. |
| 375 authorization += ", qop=" + QopToString(qop_); | 376 authorization += ", qop=" + QopToString(qop_); |
| 376 authorization += ", nc=" + nc; | 377 authorization += ", nc=" + nc; |
| 377 authorization += ", cnonce=" + HttpUtil::Quote(cnonce); | 378 authorization += ", cnonce=" + HttpUtil::Quote(cnonce); |
| 378 } | 379 } |
| 379 | 380 |
| 380 return authorization; | 381 return authorization; |
| 381 } | 382 } |
| 382 | 383 |
| 383 } // namespace net | 384 } // namespace net |
| OLD | NEW |