Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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_negotiate.h" | 5 #include "net/http/http_auth_handler_negotiate.h" |
| 6 | 6 |
| 7 #include "base/base64.h" | |
| 7 #include "base/bind.h" | 8 #include "base/bind.h" |
| 8 #include "base/bind_helpers.h" | 9 #include "base/bind_helpers.h" |
| 9 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "base/strings/string_util.h" | |
| 10 #include "base/strings/stringprintf.h" | 12 #include "base/strings/stringprintf.h" |
| 11 #include "net/base/address_family.h" | 13 #include "net/base/address_family.h" |
| 12 #include "net/base/net_errors.h" | 14 #include "net/base/net_errors.h" |
| 13 #include "net/dns/host_resolver.h" | 15 #include "net/dns/host_resolver.h" |
| 14 #include "net/dns/single_request_host_resolver.h" | 16 #include "net/dns/single_request_host_resolver.h" |
| 17 #include "net/http/http_auth_challenge_tokenizer.h" | |
| 15 #include "net/http/http_auth_filter.h" | 18 #include "net/http/http_auth_filter.h" |
| 16 #include "net/http/url_security_manager.h" | 19 #include "net/http/url_security_manager.h" |
| 17 | 20 |
| 18 namespace net { | 21 namespace net { |
| 19 | 22 |
| 20 HttpAuthHandlerNegotiate::Factory::Factory() | 23 HttpAuthHandlerNegotiate::Factory::Factory() |
| 21 : disable_cname_lookup_(false), | 24 : disable_cname_lookup_(false), |
| 22 use_port_(false), | 25 use_port_(false), |
| 23 resolver_(NULL), | 26 resolver_(NULL), |
| 24 #if defined(OS_WIN) | 27 #if defined(OS_WIN) |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 58 // TODO(cbentzel): Move towards model of parsing in the factory | 61 // TODO(cbentzel): Move towards model of parsing in the factory |
| 59 // method and only constructing when valid. | 62 // method and only constructing when valid. |
| 60 scoped_ptr<HttpAuthHandler> tmp_handler( | 63 scoped_ptr<HttpAuthHandler> tmp_handler( |
| 61 new HttpAuthHandlerNegotiate(auth_library_.get(), max_token_length_, | 64 new HttpAuthHandlerNegotiate(auth_library_.get(), max_token_length_, |
| 62 url_security_manager(), resolver_, | 65 url_security_manager(), resolver_, |
| 63 disable_cname_lookup_, use_port_)); | 66 disable_cname_lookup_, use_port_)); |
| 64 if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log)) | 67 if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log)) |
| 65 return ERR_INVALID_RESPONSE; | 68 return ERR_INVALID_RESPONSE; |
| 66 handler->swap(tmp_handler); | 69 handler->swap(tmp_handler); |
| 67 return OK; | 70 return OK; |
| 71 #elif defined(OS_ANDROID) | |
| 72 if (is_unsupported_ || account_type_.empty()) | |
| 73 return ERR_UNSUPPORTED_AUTH_SCHEME; | |
| 74 // TODO(ahendrickson): Move towards model of parsing in the factory | |
| 75 // method and only constructing when valid. | |
|
Ryan Sleevi
2015/06/16 01:07:47
This looks like you just copy-pasted the TODO from
aberent
2015/06/19 15:06:25
Actually copied it from 91/92, but happy to switch
| |
| 76 scoped_ptr<HttpAuthHandler> tmp_handler(new HttpAuthHandlerNegotiate( | |
| 77 account_type_, url_security_manager(), resolver_, disable_cname_lookup_, | |
| 78 use_port_)); | |
| 79 if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log)) | |
| 80 return ERR_INVALID_RESPONSE; | |
| 81 handler->swap(tmp_handler); | |
| 82 return OK; | |
| 83 | |
| 68 #elif defined(OS_POSIX) | 84 #elif defined(OS_POSIX) |
| 69 if (is_unsupported_) | 85 if (is_unsupported_) |
| 70 return ERR_UNSUPPORTED_AUTH_SCHEME; | 86 return ERR_UNSUPPORTED_AUTH_SCHEME; |
| 71 if (!auth_library_->Init()) { | 87 if (!auth_library_->Init()) { |
| 72 is_unsupported_ = true; | 88 is_unsupported_ = true; |
| 73 return ERR_UNSUPPORTED_AUTH_SCHEME; | 89 return ERR_UNSUPPORTED_AUTH_SCHEME; |
| 74 } | 90 } |
| 75 // TODO(ahendrickson): Move towards model of parsing in the factory | 91 // TODO(ahendrickHson): Move towards model of parsing in the factory |
|
Bernhard Bauer
2015/06/15 16:43:11
Nit: Capital H snuck in here somehow :)
aberent
2015/06/19 15:06:24
Done.
| |
| 76 // method and only constructing when valid. | 92 // method and only constructing when valid. |
| 77 scoped_ptr<HttpAuthHandler> tmp_handler( | 93 scoped_ptr<HttpAuthHandler> tmp_handler( |
| 78 new HttpAuthHandlerNegotiate(auth_library_.get(), url_security_manager(), | 94 new HttpAuthHandlerNegotiate(auth_library_.get(), url_security_manager(), |
| 79 resolver_, disable_cname_lookup_, | 95 resolver_, disable_cname_lookup_, |
| 80 use_port_)); | 96 use_port_)); |
| 81 if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log)) | 97 if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log)) |
| 82 return ERR_INVALID_RESPONSE; | 98 return ERR_INVALID_RESPONSE; |
| 83 handler->swap(tmp_handler); | 99 handler->swap(tmp_handler); |
| 84 return OK; | 100 return OK; |
| 85 #endif | 101 #endif |
| 86 } | 102 } |
| 87 | 103 |
| 88 HttpAuthHandlerNegotiate::HttpAuthHandlerNegotiate( | 104 HttpAuthHandlerNegotiate::HttpAuthHandlerNegotiate( |
| 105 #if defined(OS_ANDROID) | |
| 106 std::string account_type, | |
| 107 #endif | |
| 108 #if defined(OS_WIN) || (defined(OS_POSIX) && !defined(OS_ANDROID)) | |
| 89 AuthLibrary* auth_library, | 109 AuthLibrary* auth_library, |
| 110 #endif | |
| 90 #if defined(OS_WIN) | 111 #if defined(OS_WIN) |
| 91 ULONG max_token_length, | 112 ULONG max_token_length, |
| 92 #endif | 113 #endif |
| 93 URLSecurityManager* url_security_manager, | 114 URLSecurityManager* url_security_manager, |
| 94 HostResolver* resolver, | 115 HostResolver* resolver, |
| 95 bool disable_cname_lookup, | 116 bool disable_cname_lookup, |
| 96 bool use_port) | 117 bool use_port) |
| 97 #if defined(OS_WIN) | 118 #if defined(OS_ANDROID) |
| 119 : auth_system_(account_type), | |
| 120 #elif defined(OS_WIN) | |
| 98 : auth_system_(auth_library, "Negotiate", NEGOSSP_NAME, max_token_length), | 121 : auth_system_(auth_library, "Negotiate", NEGOSSP_NAME, max_token_length), |
| 99 #elif defined(OS_POSIX) | 122 #elif defined(OS_POSIX) |
| 100 : auth_system_(auth_library, "Negotiate", CHROME_GSS_SPNEGO_MECH_OID_DESC), | 123 : auth_system_(auth_library, "Negotiate", CHROME_GSS_SPNEGO_MECH_OID_DESC), |
| 101 #endif | 124 #endif |
| 102 disable_cname_lookup_(disable_cname_lookup), | 125 disable_cname_lookup_(disable_cname_lookup), |
| 103 use_port_(use_port), | 126 use_port_(use_port), |
| 104 resolver_(resolver), | 127 resolver_(resolver), |
| 105 already_called_(false), | 128 already_called_(false), |
| 106 has_credentials_(false), | 129 has_credentials_(false), |
| 107 auth_token_(NULL), | 130 auth_token_(NULL), |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 155 if (port != 80 && port != 443 && use_port_) { | 178 if (port != 80 && port != 443 && use_port_) { |
| 156 return base::StringPrintf("HTTP%c%s:%d", kSpnSeparator, server.c_str(), | 179 return base::StringPrintf("HTTP%c%s:%d", kSpnSeparator, server.c_str(), |
| 157 port); | 180 port); |
| 158 } else { | 181 } else { |
| 159 return base::StringPrintf("HTTP%c%s", kSpnSeparator, server.c_str()); | 182 return base::StringPrintf("HTTP%c%s", kSpnSeparator, server.c_str()); |
| 160 } | 183 } |
| 161 } | 184 } |
| 162 | 185 |
| 163 HttpAuth::AuthorizationResult HttpAuthHandlerNegotiate::HandleAnotherChallenge( | 186 HttpAuth::AuthorizationResult HttpAuthHandlerNegotiate::HandleAnotherChallenge( |
| 164 HttpAuthChallengeTokenizer* challenge) { | 187 HttpAuthChallengeTokenizer* challenge) { |
| 165 return auth_system_.ParseChallenge(challenge); | 188 // Verify the challenge's auth-scheme. |
| 189 if (!base::LowerCaseEqualsASCII(challenge->scheme(), "negotiate")) | |
|
Ryan Sleevi
2015/06/16 01:07:47
DANGER: It's worth noting here that there isn't a
aberent
2015/06/19 15:06:25
Note that there is substantial refactoring of this
| |
| 190 return HttpAuth::AUTHORIZATION_RESULT_INVALID; | |
| 191 | |
| 192 std::string encoded_auth_token = challenge->base64_param(); | |
| 193 if (encoded_auth_token.empty()) { | |
| 194 return HttpAuth::AUTHORIZATION_RESULT_REJECT; | |
| 195 } | |
|
Ryan Sleevi
2015/06/16 01:07:47
Consistent with lines 189/190 and 199/200 (and rea
aberent
2015/06/19 15:06:25
Done.
| |
| 196 // Make sure the additional token is base64 encoded. | |
| 197 std::string decoded_auth_token; | |
| 198 bool base64_rv = base::Base64Decode(encoded_auth_token, &decoded_auth_token); | |
| 199 if (!base64_rv) | |
|
Ryan Sleevi
2015/06/16 01:07:47
Does not seem like there's any reason to use a tem
aberent
2015/06/19 15:06:24
Done.
| |
| 200 return HttpAuth::AUTHORIZATION_RESULT_INVALID; | |
| 201 auth_system_.SetServerAuthToken(encoded_auth_token, decoded_auth_token); | |
| 202 return HttpAuth::AUTHORIZATION_RESULT_ACCEPT; | |
| 166 } | 203 } |
| 167 | 204 |
| 168 // Require identity on first pass instead of second. | 205 // Require identity on first pass instead of second. |
| 169 bool HttpAuthHandlerNegotiate::NeedsIdentity() { | 206 bool HttpAuthHandlerNegotiate::NeedsIdentity() { |
| 170 return auth_system_.NeedsIdentity(); | 207 return auth_system_.NeedsIdentity(); |
| 171 } | 208 } |
| 172 | 209 |
| 173 bool HttpAuthHandlerNegotiate::AllowsDefaultCredentials() { | 210 bool HttpAuthHandlerNegotiate::AllowsDefaultCredentials() { |
| 174 if (target_ == HttpAuth::AUTH_PROXY) | 211 if (target_ == HttpAuth::AUTH_PROXY) |
| 175 return true; | 212 return true; |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 195 // a particular site (based on whitelist), fall back to a | 232 // a particular site (based on whitelist), fall back to a |
| 196 // different scheme. | 233 // different scheme. |
| 197 if (!AllowsDefaultCredentials()) | 234 if (!AllowsDefaultCredentials()) |
| 198 return false; | 235 return false; |
| 199 #endif | 236 #endif |
| 200 if (CanDelegate()) | 237 if (CanDelegate()) |
| 201 auth_system_.Delegate(); | 238 auth_system_.Delegate(); |
| 202 auth_scheme_ = HttpAuth::AUTH_SCHEME_NEGOTIATE; | 239 auth_scheme_ = HttpAuth::AUTH_SCHEME_NEGOTIATE; |
| 203 score_ = 4; | 240 score_ = 4; |
| 204 properties_ = ENCRYPTS_IDENTITY | IS_CONNECTION_BASED; | 241 properties_ = ENCRYPTS_IDENTITY | IS_CONNECTION_BASED; |
| 205 HttpAuth::AuthorizationResult auth_result = | 242 if (!base::LowerCaseEqualsASCII(challenge->scheme(), "negotiate")) |
| 206 auth_system_.ParseChallenge(challenge); | 243 return false; |
| 207 return (auth_result == HttpAuth::AUTHORIZATION_RESULT_ACCEPT); | 244 return challenge->base64_param().empty(); |
| 208 } | 245 } |
| 209 | 246 |
| 210 int HttpAuthHandlerNegotiate::GenerateAuthTokenImpl( | 247 int HttpAuthHandlerNegotiate::GenerateAuthTokenImpl( |
| 211 const AuthCredentials* credentials, const HttpRequestInfo* request, | 248 const AuthCredentials* credentials, const HttpRequestInfo* request, |
| 212 const CompletionCallback& callback, std::string* auth_token) { | 249 const CompletionCallback& callback, std::string* auth_token) { |
| 213 DCHECK(callback_.is_null()); | 250 DCHECK(callback_.is_null()); |
| 214 DCHECK(auth_token_ == NULL); | 251 DCHECK(auth_token_ == NULL); |
| 215 auth_token_ = auth_token; | 252 auth_token_ = auth_token; |
| 216 if (already_called_) { | 253 if (already_called_) { |
| 217 DCHECK((!has_credentials_ && credentials == NULL) || | 254 DCHECK((!has_credentials_ && credentials == NULL) || |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 308 | 345 |
| 309 next_state_ = STATE_GENERATE_AUTH_TOKEN; | 346 next_state_ = STATE_GENERATE_AUTH_TOKEN; |
| 310 spn_ = CreateSPN(address_list_, origin_); | 347 spn_ = CreateSPN(address_list_, origin_); |
| 311 address_list_ = AddressList(); | 348 address_list_ = AddressList(); |
| 312 return rv; | 349 return rv; |
| 313 } | 350 } |
| 314 | 351 |
| 315 int HttpAuthHandlerNegotiate::DoGenerateAuthToken() { | 352 int HttpAuthHandlerNegotiate::DoGenerateAuthToken() { |
| 316 next_state_ = STATE_GENERATE_AUTH_TOKEN_COMPLETE; | 353 next_state_ = STATE_GENERATE_AUTH_TOKEN_COMPLETE; |
| 317 AuthCredentials* credentials = has_credentials_ ? &credentials_ : NULL; | 354 AuthCredentials* credentials = has_credentials_ ? &credentials_ : NULL; |
| 318 // TODO(cbentzel): This should possibly be done async. | 355 return auth_system_.GenerateAuthToken( |
| 319 return auth_system_.GenerateAuthToken(credentials, spn_, auth_token_); | 356 credentials, spn_, auth_token_, |
| 357 base::Bind(&HttpAuthHandlerNegotiate::OnIOComplete, | |
| 358 base::Unretained(this))); | |
| 320 } | 359 } |
| 321 | 360 |
| 322 int HttpAuthHandlerNegotiate::DoGenerateAuthTokenComplete(int rv) { | 361 int HttpAuthHandlerNegotiate::DoGenerateAuthTokenComplete(int rv) { |
| 323 DCHECK_NE(ERR_IO_PENDING, rv); | 362 DCHECK_NE(ERR_IO_PENDING, rv); |
| 324 auth_token_ = NULL; | 363 auth_token_ = NULL; |
| 325 return rv; | 364 return rv; |
| 326 } | 365 } |
| 327 | 366 |
| 328 bool HttpAuthHandlerNegotiate::CanDelegate() const { | 367 bool HttpAuthHandlerNegotiate::CanDelegate() const { |
| 329 // TODO(cbentzel): Should delegation be allowed on proxies? | 368 // TODO(cbentzel): Should delegation be allowed on proxies? |
| 330 if (target_ == HttpAuth::AUTH_PROXY) | 369 if (target_ == HttpAuth::AUTH_PROXY) |
| 331 return false; | 370 return false; |
| 332 if (!url_security_manager_) | 371 if (!url_security_manager_) |
| 333 return false; | 372 return false; |
| 334 return url_security_manager_->CanDelegate(origin_); | 373 return url_security_manager_->CanDelegate(origin_); |
| 335 } | 374 } |
| 336 | 375 |
| 337 } // namespace net | 376 } // namespace net |
| OLD | NEW |