Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(38)

Side by Side Diff: net/http/http_network_transaction.cc

Issue 173528: Use SSPI for NTLM authentication on Windows.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Upload before checkin Created 11 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/http/http_auth_handler_ntlm_win.cc ('k') | net/http/http_network_transaction_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2009 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_network_transaction.h" 5 #include "net/http/http_network_transaction.h"
6 6
7 #include "base/scoped_ptr.h" 7 #include "base/scoped_ptr.h"
8 #include "base/compiler_specific.h" 8 #include "base/compiler_specific.h"
9 #include "base/field_trial.h" 9 #include "base/field_trial.h"
10 #include "base/histogram.h" 10 #include "base/histogram.h"
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 DCHECK(auth_identity_[target].source != HttpAuth::IDENT_SRC_PATH_LOOKUP); 246 DCHECK(auth_identity_[target].source != HttpAuth::IDENT_SRC_PATH_LOOKUP);
247 247
248 // Add the auth entry to the cache before restarting. We don't know whether 248 // Add the auth entry to the cache before restarting. We don't know whether
249 // the identity is valid yet, but if it is valid we want other transactions 249 // the identity is valid yet, but if it is valid we want other transactions
250 // to know about it. If an entry for (origin, handler->realm()) already 250 // to know about it. If an entry for (origin, handler->realm()) already
251 // exists, we update it. 251 // exists, we update it.
252 // 252 //
253 // If auth_identity_[target].source is HttpAuth::IDENT_SRC_NONE, 253 // If auth_identity_[target].source is HttpAuth::IDENT_SRC_NONE,
254 // auth_identity_[target] contains no identity because identity is not 254 // auth_identity_[target] contains no identity because identity is not
255 // required yet. 255 // required yet.
256 //
257 // TODO(wtc): For NTLM_SSPI, we add the same auth entry to the cache in
258 // round 1 and round 2, which is redundant but correct. It would be nice
259 // to add an auth entry to the cache only once, preferrably in round 1.
260 // See http://crbug.com/21015.
256 bool has_auth_identity = 261 bool has_auth_identity =
257 auth_identity_[target].source != HttpAuth::IDENT_SRC_NONE; 262 auth_identity_[target].source != HttpAuth::IDENT_SRC_NONE;
258 if (has_auth_identity) { 263 if (has_auth_identity) {
259 session_->auth_cache()->Add(AuthOrigin(target), auth_handler_[target], 264 session_->auth_cache()->Add(AuthOrigin(target), auth_handler_[target],
260 auth_identity_[target].username, auth_identity_[target].password, 265 auth_identity_[target].username, auth_identity_[target].password,
261 AuthPath(target)); 266 AuthPath(target));
262 } 267 }
263 268
264 bool keep_alive = false; 269 bool keep_alive = false;
265 if (response_.headers->IsKeepAlive()) { 270 if (response_.headers->IsKeepAlive()) {
266 // If there is a response body of known length, we need to drain it first. 271 // If there is a response body of known length, we need to drain it first.
267 if (response_body_length_ > 0 || chunked_decoder_.get()) { 272 if (response_body_length_ > 0 || chunked_decoder_.get()) {
268 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART; 273 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART;
269 read_buf_ = new IOBuffer(kDrainBodyBufferSize); // A bit bucket 274 read_buf_ = new IOBuffer(kDrainBodyBufferSize); // A bit bucket
270 read_buf_len_ = kDrainBodyBufferSize; 275 read_buf_len_ = kDrainBodyBufferSize;
271 return; 276 return;
272 } 277 }
273 if (response_body_length_ == 0) // No response body to drain. 278 if (response_body_length_ == 0) // No response body to drain.
274 keep_alive = true; 279 keep_alive = true;
275 // response_body_length_ is -1 and we're not using chunked encoding. We 280 // response_body_length_ is -1 and we're not using chunked encoding. We
276 // don't know the length of the response body, so we can't reuse this 281 // don't know the length of the response body, so we can't reuse this
277 // connection even though the server says it's keep-alive. 282 // connection even though the server says it's keep-alive.
278 } 283 }
279 284
280 // If the auth scheme is connection-based but the proxy/server mistakenly 285 // If the auth scheme is connection-based but the proxy/server mistakenly
281 // marks the connection as non-keep-alive, the auth is going to fail, so log 286 // marks the connection as non-keep-alive, the auth is going to fail, so log
282 // an error message. 287 // an error message.
288 //
289 // TODO(wtc): has_auth_identity is not the right condition. We should
290 // be testing for "not round 1" here. See http://crbug.com/21015.
283 if (!keep_alive && auth_handler_[target]->is_connection_based() && 291 if (!keep_alive && auth_handler_[target]->is_connection_based() &&
284 has_auth_identity) { 292 has_auth_identity) {
285 LOG(ERROR) << "Can't perform " << auth_handler_[target]->scheme() 293 LOG(ERROR) << "Can't perform " << auth_handler_[target]->scheme()
286 << " auth to the " << AuthTargetString(target) << " " 294 << " auth to the " << AuthTargetString(target) << " "
287 << AuthOrigin(target) << " over a non-keep-alive connection"; 295 << AuthOrigin(target) << " over a non-keep-alive connection";
288 296
289 HttpVersion http_version = response_.headers->GetHttpVersion(); 297 HttpVersion http_version = response_.headers->GetHttpVersion();
290 LOG(ERROR) << " HTTP version is " << http_version.major_value() << "." 298 LOG(ERROR) << " HTTP version is " << http_version.major_value() << "."
291 << http_version.minor_value(); 299 << http_version.minor_value();
292 300
(...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after
735 ShouldApplyProxyAuth() && 743 ShouldApplyProxyAuth() &&
736 (HaveAuth(HttpAuth::AUTH_PROXY) || 744 (HaveAuth(HttpAuth::AUTH_PROXY) ||
737 SelectPreemptiveAuth(HttpAuth::AUTH_PROXY)); 745 SelectPreemptiveAuth(HttpAuth::AUTH_PROXY));
738 bool have_server_auth = 746 bool have_server_auth =
739 ShouldApplyServerAuth() && 747 ShouldApplyServerAuth() &&
740 (HaveAuth(HttpAuth::AUTH_SERVER) || 748 (HaveAuth(HttpAuth::AUTH_SERVER) ||
741 SelectPreemptiveAuth(HttpAuth::AUTH_SERVER)); 749 SelectPreemptiveAuth(HttpAuth::AUTH_SERVER));
742 750
743 std::string authorization_headers; 751 std::string authorization_headers;
744 752
753 // TODO(wtc): If BuildAuthorizationHeader fails (returns an authorization
754 // header with no credentials), we should return an error to prevent
755 // entering an infinite auth restart loop. See http://crbug.com/21050.
745 if (have_proxy_auth) 756 if (have_proxy_auth)
746 authorization_headers.append( 757 authorization_headers.append(
747 BuildAuthorizationHeader(HttpAuth::AUTH_PROXY)); 758 BuildAuthorizationHeader(HttpAuth::AUTH_PROXY));
748 if (have_server_auth) 759 if (have_server_auth)
749 authorization_headers.append( 760 authorization_headers.append(
750 BuildAuthorizationHeader(HttpAuth::AUTH_SERVER)); 761 BuildAuthorizationHeader(HttpAuth::AUTH_SERVER));
751 762
752 if (establishing_tunnel_) { 763 if (establishing_tunnel_) {
753 BuildTunnelRequest(request_, authorization_headers, 764 BuildTunnelRequest(request_, authorization_headers,
754 &request_headers_->headers_); 765 &request_headers_->headers_);
(...skipping 1119 matching lines...) Expand 10 before | Expand all | Expand 10 after
1874 HttpAuth::AUTH_PROXY : HttpAuth::AUTH_SERVER; 1885 HttpAuth::AUTH_PROXY : HttpAuth::AUTH_SERVER;
1875 1886
1876 LOG(INFO) << "The " << AuthTargetString(target) << " " 1887 LOG(INFO) << "The " << AuthTargetString(target) << " "
1877 << AuthOrigin(target) << " requested auth" 1888 << AuthOrigin(target) << " requested auth"
1878 << AuthChallengeLogMessage(); 1889 << AuthChallengeLogMessage();
1879 1890
1880 if (target == HttpAuth::AUTH_PROXY && proxy_info_.is_direct()) 1891 if (target == HttpAuth::AUTH_PROXY && proxy_info_.is_direct())
1881 return ERR_UNEXPECTED_PROXY_AUTH; 1892 return ERR_UNEXPECTED_PROXY_AUTH;
1882 1893
1883 // The auth we tried just failed, hence it can't be valid. Remove it from 1894 // The auth we tried just failed, hence it can't be valid. Remove it from
1884 // the cache so it won't be used again, unless it's a null identity. 1895 // the cache so it won't be used again.
1885 if (HaveAuth(target) && 1896 // TODO(wtc): IsFinalRound is not the right condition. In a multi-round
1886 auth_identity_[target].source != HttpAuth::IDENT_SRC_NONE) 1897 // auth sequence, the server may fail the auth in round 1 if our first
1898 // authorization header is broken. We should inspect response_.headers to
1899 // determine if the server already failed the auth or wants us to continue.
1900 // See http://crbug.com/21015.
1901 if (HaveAuth(target) && auth_handler_[target]->IsFinalRound()) {
1887 InvalidateRejectedAuthFromCache(target); 1902 InvalidateRejectedAuthFromCache(target);
1903 auth_handler_[target] = NULL;
1904 auth_identity_[target] = HttpAuth::Identity();
1905 }
1888 1906
1889 auth_identity_[target].invalid = true; 1907 auth_identity_[target].invalid = true;
1890 1908
1891 if (target != HttpAuth::AUTH_SERVER || 1909 if (target != HttpAuth::AUTH_SERVER ||
1892 !(request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA)) { 1910 !(request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA)) {
1893 // Find the best authentication challenge that we support. 1911 // Find the best authentication challenge that we support.
1894 HttpAuth::ChooseBestChallenge(response_.headers.get(), 1912 HttpAuth::ChooseBestChallenge(response_.headers.get(),
1895 target, 1913 target,
1896 &auth_handler_[target]); 1914 &auth_handler_[target]);
1897 } 1915 }
(...skipping 14 matching lines...) Expand all
1912 // We found no supported challenge -- let the transaction continue 1930 // We found no supported challenge -- let the transaction continue
1913 // so we end up displaying the error page. 1931 // so we end up displaying the error page.
1914 return OK; 1932 return OK;
1915 } 1933 }
1916 1934
1917 if (auth_handler_[target]->NeedsIdentity()) { 1935 if (auth_handler_[target]->NeedsIdentity()) {
1918 // Pick a new auth identity to try, by looking to the URL and auth cache. 1936 // Pick a new auth identity to try, by looking to the URL and auth cache.
1919 // If an identity to try is found, it is saved to auth_identity_[target]. 1937 // If an identity to try is found, it is saved to auth_identity_[target].
1920 SelectNextAuthIdentityToTry(target); 1938 SelectNextAuthIdentityToTry(target);
1921 } else { 1939 } else {
1922 // Proceed with a null identity. 1940 // Proceed with the existing identity or a null identity.
1923 // 1941 //
1924 // TODO(wtc): Add a safeguard against infinite transaction restarts, if 1942 // TODO(wtc): Add a safeguard against infinite transaction restarts, if
1925 // the server keeps returning "NTLM". 1943 // the server keeps returning "NTLM".
1926 auth_identity_[target].source = HttpAuth::IDENT_SRC_NONE;
1927 auth_identity_[target].invalid = false; 1944 auth_identity_[target].invalid = false;
1928 auth_identity_[target].username.clear();
1929 auth_identity_[target].password.clear();
1930 } 1945 }
1931 1946
1932 // Make a note that we are waiting for auth. This variable is inspected 1947 // Make a note that we are waiting for auth. This variable is inspected
1933 // when the client calls RestartWithAuth() to pick up where we left off. 1948 // when the client calls RestartWithAuth() to pick up where we left off.
1934 pending_auth_target_ = target; 1949 pending_auth_target_ = target;
1935 1950
1936 if (auth_identity_[target].invalid) { 1951 if (auth_identity_[target].invalid) {
1937 // We have exhausted all identity possibilities, all we can do now is 1952 // We have exhausted all identity possibilities, all we can do now is
1938 // pass the challenge information back to the client. 1953 // pass the challenge information back to the client.
1939 PopulateAuthChallenge(target); 1954 PopulateAuthChallenge(target);
(...skipping 16 matching lines...) Expand all
1956 host_and_port = proxy_info_.proxy_server().host_and_port(); 1971 host_and_port = proxy_info_.proxy_server().host_and_port();
1957 } else { 1972 } else {
1958 DCHECK(target == HttpAuth::AUTH_SERVER); 1973 DCHECK(target == HttpAuth::AUTH_SERVER);
1959 host_and_port = GetHostAndPort(request_->url); 1974 host_and_port = GetHostAndPort(request_->url);
1960 } 1975 }
1961 auth_info->host_and_port = ASCIIToWide(host_and_port); 1976 auth_info->host_and_port = ASCIIToWide(host_and_port);
1962 response_.auth_challenge = auth_info; 1977 response_.auth_challenge = auth_info;
1963 } 1978 }
1964 1979
1965 } // namespace net 1980 } // namespace net
OLDNEW
« no previous file with comments | « net/http/http_auth_handler_ntlm_win.cc ('k') | net/http/http_network_transaction_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698