| 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 // See http://dev.chromium.org/developers/design-documents/multi-process-resourc
e-loading | 5 // See http://dev.chromium.org/developers/design-documents/multi-process-resourc
e-loading |
| 6 | 6 |
| 7 #include "content/browser/loader/resource_dispatcher_host_impl.h" | 7 #include "content/browser/loader/resource_dispatcher_host_impl.h" |
| 8 | 8 |
| 9 #include <set> | 9 #include <set> |
| 10 #include <vector> | 10 #include <vector> |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 237 net::Error net_error) { | 237 net::Error net_error) { |
| 238 if (started_cb.is_null()) | 238 if (started_cb.is_null()) |
| 239 return net_error; | 239 return net_error; |
| 240 BrowserThread::PostTask( | 240 BrowserThread::PostTask( |
| 241 BrowserThread::UI, FROM_HERE, | 241 BrowserThread::UI, FROM_HERE, |
| 242 base::Bind(started_cb, static_cast<DownloadItem*>(NULL), net_error)); | 242 base::Bind(started_cb, static_cast<DownloadItem*>(NULL), net_error)); |
| 243 | 243 |
| 244 return net_error; | 244 return net_error; |
| 245 } | 245 } |
| 246 | 246 |
| 247 int BuildLoadFlagsForRequest( | |
| 248 const ResourceHostMsg_Request& request_data, | |
| 249 int child_id, | |
| 250 bool is_sync_load) { | |
| 251 int load_flags = request_data.load_flags; | |
| 252 | |
| 253 // Although EV status is irrelevant to sub-frames and sub-resources, we have | |
| 254 // to perform EV certificate verification on all resources because an HTTP | |
| 255 // keep-alive connection created to load a sub-frame or a sub-resource could | |
| 256 // be reused to load a main frame. | |
| 257 load_flags |= net::LOAD_VERIFY_EV_CERT; | |
| 258 if (request_data.resource_type == ResourceType::MAIN_FRAME) { | |
| 259 load_flags |= net::LOAD_MAIN_FRAME; | |
| 260 } else if (request_data.resource_type == ResourceType::SUB_FRAME) { | |
| 261 load_flags |= net::LOAD_SUB_FRAME; | |
| 262 } else if (request_data.resource_type == ResourceType::PREFETCH) { | |
| 263 load_flags |= (net::LOAD_PREFETCH | net::LOAD_DO_NOT_PROMPT_FOR_LOGIN); | |
| 264 } else if (request_data.resource_type == ResourceType::FAVICON) { | |
| 265 load_flags |= net::LOAD_DO_NOT_PROMPT_FOR_LOGIN; | |
| 266 } | |
| 267 | |
| 268 if (is_sync_load) | |
| 269 load_flags |= net::LOAD_IGNORE_LIMITS; | |
| 270 | |
| 271 ChildProcessSecurityPolicyImpl* policy = | |
| 272 ChildProcessSecurityPolicyImpl::GetInstance(); | |
| 273 if (!policy->CanSendCookiesForOrigin(child_id, request_data.url)) { | |
| 274 load_flags |= (net::LOAD_DO_NOT_SEND_COOKIES | | |
| 275 net::LOAD_DO_NOT_SEND_AUTH_DATA | | |
| 276 net::LOAD_DO_NOT_SAVE_COOKIES); | |
| 277 } | |
| 278 | |
| 279 // Raw headers are sensitive, as they include Cookie/Set-Cookie, so only | |
| 280 // allow requesting them if requester has ReadRawCookies permission. | |
| 281 if ((load_flags & net::LOAD_REPORT_RAW_HEADERS) | |
| 282 && !policy->CanReadRawCookies(child_id)) { | |
| 283 VLOG(1) << "Denied unauthorized request for raw headers"; | |
| 284 load_flags &= ~net::LOAD_REPORT_RAW_HEADERS; | |
| 285 } | |
| 286 | |
| 287 return load_flags; | |
| 288 } | |
| 289 | |
| 290 int GetCertID(net::URLRequest* request, int child_id) { | 247 int GetCertID(net::URLRequest* request, int child_id) { |
| 291 if (request->ssl_info().cert.get()) { | 248 if (request->ssl_info().cert.get()) { |
| 292 return CertStore::GetInstance()->StoreCert(request->ssl_info().cert.get(), | 249 return CertStore::GetInstance()->StoreCert(request->ssl_info().cert.get(), |
| 293 child_id); | 250 child_id); |
| 294 } | 251 } |
| 295 return 0; | 252 return 0; |
| 296 } | 253 } |
| 297 | 254 |
| 298 template <class T> | 255 template <class T> |
| 299 void NotifyOnUI(int type, int render_process_id, int render_view_id, | 256 void NotifyOnUI(int type, int render_process_id, int render_view_id, |
| (...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 646 | 603 |
| 647 return delegate_->CreateLoginDelegate(auth_info, loader->request()); | 604 return delegate_->CreateLoginDelegate(auth_info, loader->request()); |
| 648 } | 605 } |
| 649 | 606 |
| 650 bool ResourceDispatcherHostImpl::AcceptAuthRequest( | 607 bool ResourceDispatcherHostImpl::AcceptAuthRequest( |
| 651 ResourceLoader* loader, | 608 ResourceLoader* loader, |
| 652 net::AuthChallengeInfo* auth_info) { | 609 net::AuthChallengeInfo* auth_info) { |
| 653 if (delegate_ && !delegate_->AcceptAuthRequest(loader->request(), auth_info)) | 610 if (delegate_ && !delegate_->AcceptAuthRequest(loader->request(), auth_info)) |
| 654 return false; | 611 return false; |
| 655 | 612 |
| 656 // Prevent third-party content from prompting for login, unless it is | |
| 657 // a proxy that is trying to authenticate. This is often the foundation | |
| 658 // of a scam to extract credentials for another domain from the user. | |
| 659 if (!auth_info->is_proxy) { | |
| 660 HttpAuthResourceType resource_type = | |
| 661 HttpAuthResourceTypeOf(loader->request()); | |
| 662 UMA_HISTOGRAM_ENUMERATION("Net.HttpAuthResource", | |
| 663 resource_type, | |
| 664 HTTP_AUTH_RESOURCE_LAST); | |
| 665 | |
| 666 // TODO(tsepez): Return false on HTTP_AUTH_RESOURCE_BLOCKED_CROSS. | |
| 667 // The code once did this, but was changed due to http://crbug.com/174129. | |
| 668 // http://crbug.com/174179 has been filed to track this issue. | |
| 669 } | |
| 670 | |
| 671 return true; | 613 return true; |
| 672 } | 614 } |
| 673 | 615 |
| 674 bool ResourceDispatcherHostImpl::AcceptSSLClientCertificateRequest( | 616 bool ResourceDispatcherHostImpl::AcceptSSLClientCertificateRequest( |
| 675 ResourceLoader* loader, | 617 ResourceLoader* loader, |
| 676 net::SSLCertRequestInfo* cert_info) { | 618 net::SSLCertRequestInfo* cert_info) { |
| 677 if (delegate_ && !delegate_->AcceptSSLClientCertificateRequest( | 619 if (delegate_ && !delegate_->AcceptSSLClientCertificateRequest( |
| 678 loader->request(), cert_info)) { | 620 loader->request(), cert_info)) { |
| 679 return false; | 621 return false; |
| 680 } | 622 } |
| (...skipping 1109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1790 if (cancel_requests) { | 1732 if (cancel_requests) { |
| 1791 IncrementOutstandingRequestsMemory(-1, *info); | 1733 IncrementOutstandingRequestsMemory(-1, *info); |
| 1792 } else { | 1734 } else { |
| 1793 StartLoading(info, loader); | 1735 StartLoading(info, loader); |
| 1794 } | 1736 } |
| 1795 } | 1737 } |
| 1796 | 1738 |
| 1797 delete loaders; | 1739 delete loaders; |
| 1798 } | 1740 } |
| 1799 | 1741 |
| 1800 ResourceDispatcherHostImpl::HttpAuthResourceType | 1742 ResourceDispatcherHostImpl::HttpAuthRelationType |
| 1801 ResourceDispatcherHostImpl::HttpAuthResourceTypeOf(net::URLRequest* request) { | 1743 ResourceDispatcherHostImpl::HttpAuthRelationTypeOf( |
| 1802 // Use the same critera as for cookies to determine the sub-resource type | 1744 const GURL& request_url, |
| 1803 // that is requesting to be authenticated. | 1745 const GURL& first_party) { |
| 1804 if (!request->first_party_for_cookies().is_valid()) | 1746 if (!first_party.is_valid()) |
| 1805 return HTTP_AUTH_RESOURCE_TOP; | 1747 return HTTP_AUTH_RELATION_TOP; |
| 1806 | 1748 |
| 1807 if (net::registry_controlled_domains::SameDomainOrHost( | 1749 if (net::registry_controlled_domains::SameDomainOrHost( |
| 1808 request->first_party_for_cookies(), request->url(), | 1750 first_party, request_url, |
| 1809 net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES)) | 1751 net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES)) |
| 1810 return HTTP_AUTH_RESOURCE_SAME_DOMAIN; | 1752 return HTTP_AUTH_RELATION_SAME_DOMAIN; |
| 1811 | 1753 |
| 1812 if (allow_cross_origin_auth_prompt()) | 1754 if (allow_cross_origin_auth_prompt()) |
| 1813 return HTTP_AUTH_RESOURCE_ALLOWED_CROSS; | 1755 return HTTP_AUTH_RELATION_ALLOWED_CROSS; |
| 1814 | 1756 |
| 1815 return HTTP_AUTH_RESOURCE_BLOCKED_CROSS; | 1757 return HTTP_AUTH_RELATION_BLOCKED_CROSS; |
| 1816 } | 1758 } |
| 1817 | 1759 |
| 1818 bool ResourceDispatcherHostImpl::allow_cross_origin_auth_prompt() { | 1760 bool ResourceDispatcherHostImpl::allow_cross_origin_auth_prompt() { |
| 1819 return allow_cross_origin_auth_prompt_; | 1761 return allow_cross_origin_auth_prompt_; |
| 1820 } | 1762 } |
| 1821 | 1763 |
| 1822 bool ResourceDispatcherHostImpl::IsTransferredNavigation( | 1764 bool ResourceDispatcherHostImpl::IsTransferredNavigation( |
| 1823 const GlobalRequestID& id) const { | 1765 const GlobalRequestID& id) const { |
| 1824 ResourceLoader* loader = GetLoader(id); | 1766 ResourceLoader* loader = GetLoader(id); |
| 1825 return loader ? loader->is_transferring() : false; | 1767 return loader ? loader->is_transferring() : false; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1856 DCHECK(ContainsKey(delegate_map_, id)); | 1798 DCHECK(ContainsKey(delegate_map_, id)); |
| 1857 DelegateMap::iterator it = delegate_map_.find(id); | 1799 DelegateMap::iterator it = delegate_map_.find(id); |
| 1858 DCHECK(it->second->HasObserver(delegate)); | 1800 DCHECK(it->second->HasObserver(delegate)); |
| 1859 it->second->RemoveObserver(delegate); | 1801 it->second->RemoveObserver(delegate); |
| 1860 if (it->second->size() == 0) { | 1802 if (it->second->size() == 0) { |
| 1861 delete it->second; | 1803 delete it->second; |
| 1862 delegate_map_.erase(it); | 1804 delegate_map_.erase(it); |
| 1863 } | 1805 } |
| 1864 } | 1806 } |
| 1865 | 1807 |
| 1808 int ResourceDispatcherHostImpl::BuildLoadFlagsForRequest( |
| 1809 const ResourceHostMsg_Request& request_data, |
| 1810 int child_id, |
| 1811 bool is_sync_load) { |
| 1812 int load_flags = request_data.load_flags; |
| 1813 |
| 1814 // Although EV status is irrelevant to sub-frames and sub-resources, we have |
| 1815 // to perform EV certificate verification on all resources because an HTTP |
| 1816 // keep-alive connection created to load a sub-frame or a sub-resource could |
| 1817 // be reused to load a main frame. |
| 1818 load_flags |= net::LOAD_VERIFY_EV_CERT; |
| 1819 if (request_data.resource_type == ResourceType::MAIN_FRAME) { |
| 1820 load_flags |= net::LOAD_MAIN_FRAME; |
| 1821 } else if (request_data.resource_type == ResourceType::SUB_FRAME) { |
| 1822 load_flags |= net::LOAD_SUB_FRAME; |
| 1823 } else if (request_data.resource_type == ResourceType::PREFETCH) { |
| 1824 load_flags |= (net::LOAD_PREFETCH | net::LOAD_DO_NOT_PROMPT_FOR_LOGIN); |
| 1825 } else if (request_data.resource_type == ResourceType::FAVICON) { |
| 1826 load_flags |= net::LOAD_DO_NOT_PROMPT_FOR_LOGIN; |
| 1827 } else if (request_data.resource_type == ResourceType::IMAGE) { |
| 1828 // Prevent third-party image content from prompting for login, as this |
| 1829 // is often a scam to extract credentials for another domain from the user. |
| 1830 // Only block image loads, as the attack applies largely to the "src" |
| 1831 // property of the <img> tag. It is common for web properties to allow |
| 1832 // untrusted values for <img src>; this is considered a fair thing for an |
| 1833 // HTML sanitizer to do. Conversely, any HTML sanitizer that didn't |
| 1834 // filter sources for <script>, <link>, <embed>, <object>, <iframe> tags |
| 1835 // would be considered vulnerable in and of itself. |
| 1836 HttpAuthRelationType relation_type = HttpAuthRelationTypeOf( |
| 1837 request_data.url, request_data.first_party_for_cookies); |
| 1838 if (relation_type == HTTP_AUTH_RELATION_BLOCKED_CROSS) { |
| 1839 load_flags |= (net::LOAD_DO_NOT_SEND_AUTH_DATA | |
| 1840 net::LOAD_DO_NOT_PROMPT_FOR_LOGIN); |
| 1841 } |
| 1842 } |
| 1843 |
| 1844 if (is_sync_load) |
| 1845 load_flags |= net::LOAD_IGNORE_LIMITS; |
| 1846 |
| 1847 ChildProcessSecurityPolicyImpl* policy = |
| 1848 ChildProcessSecurityPolicyImpl::GetInstance(); |
| 1849 if (!policy->CanSendCookiesForOrigin(child_id, request_data.url)) { |
| 1850 load_flags |= (net::LOAD_DO_NOT_SEND_COOKIES | |
| 1851 net::LOAD_DO_NOT_SEND_AUTH_DATA | |
| 1852 net::LOAD_DO_NOT_SAVE_COOKIES); |
| 1853 } |
| 1854 |
| 1855 // Raw headers are sensitive, as they include Cookie/Set-Cookie, so only |
| 1856 // allow requesting them if requester has ReadRawCookies permission. |
| 1857 if ((load_flags & net::LOAD_REPORT_RAW_HEADERS) |
| 1858 && !policy->CanReadRawCookies(child_id)) { |
| 1859 VLOG(1) << "Denied unauthorized request for raw headers"; |
| 1860 load_flags &= ~net::LOAD_REPORT_RAW_HEADERS; |
| 1861 } |
| 1862 |
| 1863 return load_flags; |
| 1864 } |
| 1865 |
| 1866 } // namespace content | 1866 } // namespace content |
| OLD | NEW |