OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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/string_util.h" | 9 #include "base/string_util.h" |
10 #include "base/trace_event.h" | 10 #include "base/trace_event.h" |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
116 } | 116 } |
117 | 117 |
118 void HttpNetworkTransaction::PrepareForAuthRestart(HttpAuth::Target target) { | 118 void HttpNetworkTransaction::PrepareForAuthRestart(HttpAuth::Target target) { |
119 DCHECK(HaveAuth(target)); | 119 DCHECK(HaveAuth(target)); |
120 DCHECK(auth_identity_[target].source != HttpAuth::IDENT_SRC_PATH_LOOKUP); | 120 DCHECK(auth_identity_[target].source != HttpAuth::IDENT_SRC_PATH_LOOKUP); |
121 | 121 |
122 // Add the auth entry to the cache before restarting. We don't know whether | 122 // Add the auth entry to the cache before restarting. We don't know whether |
123 // the identity is valid yet, but if it is valid we want other transactions | 123 // the identity is valid yet, but if it is valid we want other transactions |
124 // to know about it. If an entry for (origin, handler->realm()) already | 124 // to know about it. If an entry for (origin, handler->realm()) already |
125 // exists, we update it. | 125 // exists, we update it. |
126 session_->auth_cache()->Add(AuthOrigin(target), auth_handler_[target], | 126 // |
127 auth_identity_[target].username, auth_identity_[target].password, | 127 // If auth_identity_[target].source is HttpAuth::IDENT_SRC_NONE, |
128 AuthPath(target)); | 128 // auth_identity_[target] contains no identity because identity is not |
| 129 // required yet. |
| 130 if (auth_identity_[target].source != HttpAuth::IDENT_SRC_NONE) { |
| 131 session_->auth_cache()->Add(AuthOrigin(target), auth_handler_[target], |
| 132 auth_identity_[target].username, auth_identity_[target].password, |
| 133 AuthPath(target)); |
| 134 } |
129 | 135 |
130 bool keep_alive = false; | 136 bool keep_alive = false; |
131 if (response_.headers->IsKeepAlive()) { | 137 if (response_.headers->IsKeepAlive()) { |
132 // If there is a response body of known length, we need to drain it first. | 138 // If there is a response body of known length, we need to drain it first. |
133 if (content_length_ > 0 || chunked_decoder_.get()) { | 139 if (content_length_ > 0 || chunked_decoder_.get()) { |
134 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART; | 140 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART; |
135 read_buf_ = new IOBuffer(kDrainBodyBufferSize); // A bit bucket | 141 read_buf_ = new IOBuffer(kDrainBodyBufferSize); // A bit bucket |
136 read_buf_len_ = kDrainBodyBufferSize; | 142 read_buf_len_ = kDrainBodyBufferSize; |
137 return; | 143 return; |
138 } | 144 } |
(...skipping 1116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1255 return false; | 1261 return false; |
1256 | 1262 |
1257 // SelectPreemptiveAuth() is on the critical path for each request, so it | 1263 // SelectPreemptiveAuth() is on the critical path for each request, so it |
1258 // is expected to be fast. LookupByPath() is fast in the common case, since | 1264 // is expected to be fast. LookupByPath() is fast in the common case, since |
1259 // the number of http auth cache entries is expected to be very small. | 1265 // the number of http auth cache entries is expected to be very small. |
1260 // (For most users in fact, it will be 0.) | 1266 // (For most users in fact, it will be 0.) |
1261 | 1267 |
1262 HttpAuthCache::Entry* entry = session_->auth_cache()->LookupByPath( | 1268 HttpAuthCache::Entry* entry = session_->auth_cache()->LookupByPath( |
1263 AuthOrigin(target), AuthPath(target)); | 1269 AuthOrigin(target), AuthPath(target)); |
1264 | 1270 |
1265 if (entry) { | 1271 // We don't support preemptive authentication for connection-based |
| 1272 // authentication schemes because they can't reuse entry->handler(). |
| 1273 // Hopefully we can remove this limitation in the future. |
| 1274 if (entry && !entry->handler()->is_connection_based()) { |
1266 auth_identity_[target].source = HttpAuth::IDENT_SRC_PATH_LOOKUP; | 1275 auth_identity_[target].source = HttpAuth::IDENT_SRC_PATH_LOOKUP; |
1267 auth_identity_[target].invalid = false; | 1276 auth_identity_[target].invalid = false; |
1268 auth_identity_[target].username = entry->username(); | 1277 auth_identity_[target].username = entry->username(); |
1269 auth_identity_[target].password = entry->password(); | 1278 auth_identity_[target].password = entry->password(); |
1270 auth_handler_[target] = entry->handler(); | 1279 auth_handler_[target] = entry->handler(); |
1271 return true; | 1280 return true; |
1272 } | 1281 } |
1273 return false; | 1282 return false; |
1274 } | 1283 } |
1275 | 1284 |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1332 int status = response_.headers->response_code(); | 1341 int status = response_.headers->response_code(); |
1333 if (status != 401 && status != 407) | 1342 if (status != 401 && status != 407) |
1334 return OK; | 1343 return OK; |
1335 HttpAuth::Target target = status == 407 ? | 1344 HttpAuth::Target target = status == 407 ? |
1336 HttpAuth::AUTH_PROXY : HttpAuth::AUTH_SERVER; | 1345 HttpAuth::AUTH_PROXY : HttpAuth::AUTH_SERVER; |
1337 | 1346 |
1338 if (target == HttpAuth::AUTH_PROXY && proxy_info_.is_direct()) | 1347 if (target == HttpAuth::AUTH_PROXY && proxy_info_.is_direct()) |
1339 return ERR_UNEXPECTED_PROXY_AUTH; | 1348 return ERR_UNEXPECTED_PROXY_AUTH; |
1340 | 1349 |
1341 // The auth we tried just failed, hence it can't be valid. Remove it from | 1350 // The auth we tried just failed, hence it can't be valid. Remove it from |
1342 // the cache so it won't be used again. | 1351 // the cache so it won't be used again, unless it's a null identity. |
1343 if (HaveAuth(target)) | 1352 if (HaveAuth(target) && |
| 1353 auth_identity_[target].source != HttpAuth::IDENT_SRC_NONE) |
1344 InvalidateRejectedAuthFromCache(target); | 1354 InvalidateRejectedAuthFromCache(target); |
1345 | 1355 |
1346 auth_identity_[target].invalid = true; | 1356 auth_identity_[target].invalid = true; |
1347 | 1357 |
1348 // Find the best authentication challenge that we support. | 1358 // Find the best authentication challenge that we support. |
1349 HttpAuth::ChooseBestChallenge(response_.headers.get(), | 1359 HttpAuth::ChooseBestChallenge(response_.headers.get(), |
1350 target, | 1360 target, |
1351 &auth_handler_[target]); | 1361 &auth_handler_[target]); |
1352 | 1362 |
1353 if (!auth_handler_[target]) { | 1363 if (!auth_handler_[target]) { |
1354 if (establishing_tunnel_) { | 1364 if (establishing_tunnel_) { |
1355 // We are establishing a tunnel, we can't show the error page because an | 1365 // We are establishing a tunnel, we can't show the error page because an |
1356 // active network attacker could control its contents. Instead, we just | 1366 // active network attacker could control its contents. Instead, we just |
1357 // fail to establish the tunnel. | 1367 // fail to establish the tunnel. |
1358 return ERR_PROXY_AUTH_REQUESTED; | 1368 return ERR_PROXY_AUTH_REQUESTED; |
1359 } | 1369 } |
1360 // We found no supported challenge -- let the transaction continue | 1370 // We found no supported challenge -- let the transaction continue |
1361 // so we end up displaying the error page. | 1371 // so we end up displaying the error page. |
1362 return OK; | 1372 return OK; |
1363 } | 1373 } |
1364 | 1374 |
1365 // Pick a new auth identity to try, by looking to the URL and auth cache. | 1375 bool has_identity_to_try; |
1366 // If an identity to try is found, it is saved to auth_identity_[target]. | 1376 if (auth_handler_[target]->NeedsIdentity()) { |
1367 bool has_identity_to_try = SelectNextAuthIdentityToTry(target); | 1377 // Pick a new auth identity to try, by looking to the URL and auth cache. |
| 1378 // If an identity to try is found, it is saved to auth_identity_[target]. |
| 1379 has_identity_to_try = SelectNextAuthIdentityToTry(target); |
| 1380 } else { |
| 1381 // Proceed with a null identity. |
| 1382 // |
| 1383 // TODO(wtc): Add a safeguard against infinite transaction restarts, if |
| 1384 // the server keeps returning "NTLM". |
| 1385 auth_identity_[target].source = HttpAuth::IDENT_SRC_NONE; |
| 1386 auth_identity_[target].invalid = false; |
| 1387 auth_identity_[target].username.clear(); |
| 1388 auth_identity_[target].password.clear(); |
| 1389 has_identity_to_try = true; |
| 1390 } |
1368 DCHECK(has_identity_to_try == !auth_identity_[target].invalid); | 1391 DCHECK(has_identity_to_try == !auth_identity_[target].invalid); |
1369 | 1392 |
1370 if (has_identity_to_try) { | 1393 if (has_identity_to_try) { |
1371 DCHECK(user_callback_); | 1394 DCHECK(user_callback_); |
1372 PrepareForAuthRestart(target); | 1395 PrepareForAuthRestart(target); |
1373 return WILL_RESTART_TRANSACTION; | 1396 return WILL_RESTART_TRANSACTION; |
1374 } | 1397 } |
1375 | 1398 |
1376 // We have exhausted all identity possibilities, all we can do now is | 1399 // We have exhausted all identity possibilities, all we can do now is |
1377 // pass the challenge information back to the client. | 1400 // pass the challenge information back to the client. |
(...skipping 13 matching lines...) Expand all Loading... |
1391 if (target == HttpAuth::AUTH_PROXY) { | 1414 if (target == HttpAuth::AUTH_PROXY) { |
1392 auth_info->host = ASCIIToWide(proxy_info_.proxy_server().host_and_port()); | 1415 auth_info->host = ASCIIToWide(proxy_info_.proxy_server().host_and_port()); |
1393 } else { | 1416 } else { |
1394 DCHECK(target == HttpAuth::AUTH_SERVER); | 1417 DCHECK(target == HttpAuth::AUTH_SERVER); |
1395 auth_info->host = ASCIIToWide(request_->url.host()); | 1418 auth_info->host = ASCIIToWide(request_->url.host()); |
1396 } | 1419 } |
1397 response_.auth_challenge = auth_info; | 1420 response_.auth_challenge = auth_info; |
1398 } | 1421 } |
1399 | 1422 |
1400 } // namespace net | 1423 } // namespace net |
OLD | NEW |