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 <stddef.h> | 9 #include <stddef.h> |
10 | 10 |
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
279 CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE; | 279 CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE; |
280 break; | 280 break; |
281 case blink::WebReferrerPolicyNoReferrerWhenDowngradeOriginWhenCrossOrigin: | 281 case blink::WebReferrerPolicyNoReferrerWhenDowngradeOriginWhenCrossOrigin: |
282 net_referrer_policy = net::URLRequest:: | 282 net_referrer_policy = net::URLRequest:: |
283 REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN; | 283 REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN; |
284 break; | 284 break; |
285 } | 285 } |
286 request->set_referrer_policy(net_referrer_policy); | 286 request->set_referrer_policy(net_referrer_policy); |
287 } | 287 } |
288 | 288 |
289 // Consults the RendererSecurity policy to determine whether the | |
290 // ResourceDispatcherHostImpl should service this request. A request might be | |
291 // disallowed if the renderer is not authorized to retrieve the request URL or | |
292 // if the renderer is attempting to upload an unauthorized file. | |
293 bool ShouldServiceRequest(int process_type, | |
294 int child_id, | |
295 const ResourceRequest& request_data, | |
296 const net::HttpRequestHeaders& headers, | |
297 ResourceMessageFilter* filter, | |
298 ResourceContext* resource_context) { | |
299 ChildProcessSecurityPolicyImpl* policy = | |
300 ChildProcessSecurityPolicyImpl::GetInstance(); | |
301 | |
302 // Check if the renderer is permitted to request the requested URL. | |
303 if (!policy->CanRequestURL(child_id, request_data.url)) { | |
304 VLOG(1) << "Denied unauthorized request for " | |
305 << request_data.url.possibly_invalid_spec(); | |
306 return false; | |
307 } | |
308 | |
309 // Check if the renderer is using an illegal Origin header. If so, kill it. | |
310 std::string origin_string; | |
311 bool has_origin = headers.GetHeader("Origin", &origin_string) && | |
312 origin_string != "null"; | |
313 if (has_origin) { | |
314 GURL origin(origin_string); | |
315 if (!policy->CanCommitURL(child_id, origin) || | |
316 GetContentClient()->browser()->IsIllegalOrigin(resource_context, | |
317 child_id, origin)) { | |
318 VLOG(1) << "Killed renderer for illegal origin: " << origin_string; | |
319 bad_message::ReceivedBadMessage(filter, bad_message::RDH_ILLEGAL_ORIGIN); | |
320 return false; | |
321 } | |
322 } | |
323 | |
324 // Check if the renderer is permitted to upload the requested files. | |
325 if (request_data.request_body.get()) { | |
326 const std::vector<ResourceRequestBodyImpl::Element>* uploads = | |
327 request_data.request_body->elements(); | |
328 std::vector<ResourceRequestBodyImpl::Element>::const_iterator iter; | |
329 for (iter = uploads->begin(); iter != uploads->end(); ++iter) { | |
330 if (iter->type() == ResourceRequestBodyImpl::Element::TYPE_FILE && | |
331 !policy->CanReadFile(child_id, iter->path())) { | |
332 NOTREACHED() << "Denied unauthorized upload of " | |
333 << iter->path().value(); | |
334 return false; | |
335 } | |
336 if (iter->type() == | |
337 ResourceRequestBodyImpl::Element::TYPE_FILE_FILESYSTEM) { | |
338 storage::FileSystemURL url = | |
339 filter->file_system_context()->CrackURL(iter->filesystem_url()); | |
340 if (!policy->CanReadFileSystemFile(child_id, url)) { | |
341 NOTREACHED() << "Denied unauthorized upload of " | |
342 << iter->filesystem_url().spec(); | |
343 return false; | |
344 } | |
345 } | |
346 } | |
347 } | |
348 | |
349 return true; | |
350 } | |
351 | |
352 void RemoveDownloadFileFromChildSecurityPolicy(int child_id, | 289 void RemoveDownloadFileFromChildSecurityPolicy(int child_id, |
353 const base::FilePath& path) { | 290 const base::FilePath& path) { |
354 ChildProcessSecurityPolicyImpl::GetInstance()->RevokeAllPermissionsForFile( | 291 ChildProcessSecurityPolicyImpl::GetInstance()->RevokeAllPermissionsForFile( |
355 child_id, path); | 292 child_id, path); |
356 } | 293 } |
357 | 294 |
358 int GetCertID(CertStore* cert_store, net::URLRequest* request, int child_id) { | 295 int GetCertID(CertStore* cert_store, net::URLRequest* request, int child_id) { |
359 if (request->ssl_info().cert.get()) | 296 if (request->ssl_info().cert.get()) |
360 return cert_store->StoreCert(request->ssl_info().cert.get(), child_id); | 297 return cert_store->StoreCert(request->ssl_info().cert.get(), child_id); |
361 return 0; | 298 return 0; |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
486 if (pending_frame_host) | 423 if (pending_frame_host) |
487 routing_ids->insert(pending_frame_host->GetGlobalFrameRoutingId()); | 424 routing_ids->insert(pending_frame_host->GetGlobalFrameRoutingId()); |
488 } | 425 } |
489 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | 426 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
490 base::Bind(&NotifyForRouteSetOnIO, frame_callback, | 427 base::Bind(&NotifyForRouteSetOnIO, frame_callback, |
491 base::Passed(std::move(routing_ids)))); | 428 base::Passed(std::move(routing_ids)))); |
492 } | 429 } |
493 | 430 |
494 } // namespace | 431 } // namespace |
495 | 432 |
433 ResourceDispatcherHostImpl::HeaderInterceptorInfo::HeaderInterceptorInfo() {} | |
434 | |
435 ResourceDispatcherHostImpl::HeaderInterceptorInfo::~HeaderInterceptorInfo() {} | |
436 | |
437 ResourceDispatcherHostImpl::HeaderInterceptorInfo::HeaderInterceptorInfo( | |
438 const HeaderInterceptorInfo& other) {} | |
439 | |
496 // static | 440 // static |
497 ResourceDispatcherHost* ResourceDispatcherHost::Get() { | 441 ResourceDispatcherHost* ResourceDispatcherHost::Get() { |
498 return g_resource_dispatcher_host; | 442 return g_resource_dispatcher_host; |
499 } | 443 } |
500 | 444 |
501 ResourceDispatcherHostImpl::ResourceDispatcherHostImpl() | 445 ResourceDispatcherHostImpl::ResourceDispatcherHostImpl() |
502 : save_file_manager_(new SaveFileManager()), | 446 : save_file_manager_(new SaveFileManager()), |
503 request_id_(-1), | 447 request_id_(-1), |
504 is_shutdown_(false), | 448 is_shutdown_(false), |
505 num_in_flight_requests_(0), | 449 num_in_flight_requests_(0), |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
742 void ResourceDispatcherHostImpl::ClearLoginDelegateForRequest( | 686 void ResourceDispatcherHostImpl::ClearLoginDelegateForRequest( |
743 net::URLRequest* request) { | 687 net::URLRequest* request) { |
744 ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request); | 688 ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request); |
745 if (info) { | 689 if (info) { |
746 ResourceLoader* loader = GetLoader(info->GetGlobalRequestID()); | 690 ResourceLoader* loader = GetLoader(info->GetGlobalRequestID()); |
747 if (loader) | 691 if (loader) |
748 loader->ClearLoginDelegate(); | 692 loader->ClearLoginDelegate(); |
749 } | 693 } |
750 } | 694 } |
751 | 695 |
696 void ResourceDispatcherHostImpl::RegisterInterceptor( | |
697 const std::string& http_header, | |
698 const std::string& starts_with, | |
699 const InterceptorCallback& interceptor) { | |
700 DCHECK(!http_header.empty()); | |
701 DCHECK(interceptor); | |
702 // Only one interceptor per header is supported. | |
703 DCHECK(http_header_interceptor_map_.find(http_header) == | |
704 http_header_interceptor_map_.end()); | |
705 | |
706 HeaderInterceptorInfo interceptor_info; | |
707 interceptor_info.starts_with = starts_with; | |
708 interceptor_info.interceptor = interceptor; | |
709 | |
710 http_header_interceptor_map_[http_header] = interceptor_info; | |
711 } | |
712 | |
752 void ResourceDispatcherHostImpl::Shutdown() { | 713 void ResourceDispatcherHostImpl::Shutdown() { |
753 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 714 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
754 BrowserThread::PostTask(BrowserThread::IO, | 715 BrowserThread::PostTask(BrowserThread::IO, |
755 FROM_HERE, | 716 FROM_HERE, |
756 base::Bind(&ResourceDispatcherHostImpl::OnShutdown, | 717 base::Bind(&ResourceDispatcherHostImpl::OnShutdown, |
757 base::Unretained(this))); | 718 base::Unretained(this))); |
758 } | 719 } |
759 | 720 |
760 std::unique_ptr<ResourceHandler> | 721 std::unique_ptr<ResourceHandler> |
761 ResourceDispatcherHostImpl::CreateResourceHandlerForDownload( | 722 ResourceDispatcherHostImpl::CreateResourceHandlerForDownload( |
(...skipping 588 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1350 ResourceContext* resource_context = NULL; | 1311 ResourceContext* resource_context = NULL; |
1351 net::URLRequestContext* request_context = NULL; | 1312 net::URLRequestContext* request_context = NULL; |
1352 filter_->GetContexts(request_data.resource_type, &resource_context, | 1313 filter_->GetContexts(request_data.resource_type, &resource_context, |
1353 &request_context); | 1314 &request_context); |
1354 | 1315 |
1355 // Parse the headers before calling ShouldServiceRequest, so that they are | 1316 // Parse the headers before calling ShouldServiceRequest, so that they are |
1356 // available to be validated. | 1317 // available to be validated. |
1357 net::HttpRequestHeaders headers; | 1318 net::HttpRequestHeaders headers; |
1358 headers.AddHeadersFromString(request_data.headers); | 1319 headers.AddHeadersFromString(request_data.headers); |
1359 | 1320 |
1360 if (is_shutdown_ || | 1321 BeginRequestStatus begin_request_status = CONTINUE; |
1361 !ShouldServiceRequest(process_type, child_id, request_data, headers, | 1322 OnHeaderProcessedCallback callback; |
1362 filter_, resource_context)) { | 1323 if (!is_shutdown_) { |
1324 callback = | |
1325 base::Bind(&ResourceDispatcherHostImpl::ContinuePendingBeginRequest, | |
1326 base::Unretained(this), request_id, request_data, | |
1327 sync_result, route_id, headers); | |
1328 begin_request_status = | |
1329 ShouldServiceRequest(process_type, child_id, request_data, headers, | |
1330 filter_, resource_context, callback); | |
1331 } else { | |
1332 begin_request_status = ABORT; | |
1333 } | |
1334 if (begin_request_status == ABORT) { | |
1335 AbortRequestBeforeItStarts(filter_, sync_result, request_id); | |
1336 return; | |
1337 } else if (begin_request_status == CONTINUE) { | |
1338 callback.Run(true, 0); | |
1339 } | |
1340 } | |
1341 | |
1342 void ResourceDispatcherHostImpl::ContinuePendingBeginRequest( | |
1343 int request_id, | |
1344 const ResourceRequest& request_data, | |
1345 IPC::Message* sync_result, // only valid for sync | |
1346 int route_id, | |
1347 const net::HttpRequestHeaders& headers, | |
1348 bool continue_request, | |
1349 int error_code) { | |
1350 if (!continue_request) { | |
1351 bad_message::ReceivedBadMessage( | |
1352 filter_, static_cast<bad_message::BadMessageReason>(error_code)); | |
Charlie Reis
2016/08/10 20:44:02
This is not a safe cast. The INVALID_ORIGIN code
| |
1363 AbortRequestBeforeItStarts(filter_, sync_result, request_id); | 1353 AbortRequestBeforeItStarts(filter_, sync_result, request_id); |
1364 return; | 1354 return; |
1365 } | 1355 } |
1366 | 1356 |
1357 int process_type = filter_->process_type(); | |
1358 int child_id = filter_->child_id(); | |
1359 | |
1360 bool is_navigation_stream_request = | |
1361 IsBrowserSideNavigationEnabled() && | |
1362 IsResourceTypeFrame(request_data.resource_type); | |
1363 | |
1364 ResourceContext* resource_context = NULL; | |
1365 net::URLRequestContext* request_context = NULL; | |
1366 filter_->GetContexts(request_data.resource_type, &resource_context, | |
1367 &request_context); | |
1368 | |
1367 // Allow the observer to block/handle the request. | 1369 // Allow the observer to block/handle the request. |
1368 if (delegate_ && !delegate_->ShouldBeginRequest(request_data.method, | 1370 if (delegate_ && !delegate_->ShouldBeginRequest(request_data.method, |
1369 request_data.url, | 1371 request_data.url, |
1370 request_data.resource_type, | 1372 request_data.resource_type, |
1371 resource_context)) { | 1373 resource_context)) { |
1372 AbortRequestBeforeItStarts(filter_, sync_result, request_id); | 1374 AbortRequestBeforeItStarts(filter_, sync_result, request_id); |
1373 return; | 1375 return; |
1374 } | 1376 } |
1375 | 1377 |
1376 // Construct the request. | 1378 // Construct the request. |
(...skipping 1221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2598 DCHECK(deserialized); | 2600 DCHECK(deserialized); |
2599 ssl.cert_id = GetCertStore()->StoreCert(ssl_info.cert.get(), child_id); | 2601 ssl.cert_id = GetCertStore()->StoreCert(ssl_info.cert.get(), child_id); |
2600 response->head.security_info = SerializeSecurityInfo(ssl); | 2602 response->head.security_info = SerializeSecurityInfo(ssl); |
2601 } | 2603 } |
2602 | 2604 |
2603 CertStore* ResourceDispatcherHostImpl::GetCertStore() { | 2605 CertStore* ResourceDispatcherHostImpl::GetCertStore() { |
2604 return cert_store_for_testing_ ? cert_store_for_testing_ | 2606 return cert_store_for_testing_ ? cert_store_for_testing_ |
2605 : CertStore::GetInstance(); | 2607 : CertStore::GetInstance(); |
2606 } | 2608 } |
2607 | 2609 |
2610 ResourceDispatcherHostImpl::BeginRequestStatus | |
2611 ResourceDispatcherHostImpl::ShouldServiceRequest( | |
2612 int process_type, | |
2613 int child_id, | |
2614 const ResourceRequest& request_data, | |
2615 const net::HttpRequestHeaders& headers, | |
2616 ResourceMessageFilter* filter, | |
2617 ResourceContext* resource_context, | |
2618 OnHeaderProcessedCallback callback) { | |
2619 ChildProcessSecurityPolicyImpl* policy = | |
2620 ChildProcessSecurityPolicyImpl::GetInstance(); | |
2621 | |
2622 // Check if the renderer is permitted to request the requested URL. | |
2623 if (!policy->CanRequestURL(child_id, request_data.url)) { | |
2624 VLOG(1) << "Denied unauthorized request for " | |
2625 << request_data.url.possibly_invalid_spec(); | |
2626 return ABORT; | |
2627 } | |
2628 | |
2629 // Check if the renderer is using an illegal Origin header. If so, kill it. | |
2630 std::string origin_string; | |
2631 bool has_origin = | |
2632 headers.GetHeader("Origin", &origin_string) && origin_string != "null"; | |
2633 if (has_origin) { | |
2634 GURL origin(origin_string); | |
2635 if (!policy->CanCommitURL(child_id, origin)) { | |
2636 VLOG(1) << "Killed renderer for illegal origin: " << origin_string; | |
2637 bad_message::ReceivedBadMessage(filter, bad_message::RDH_ILLEGAL_ORIGIN); | |
2638 return ABORT; | |
2639 } | |
2640 } | |
2641 | |
2642 // Check if the renderer is permitted to upload the requested files. | |
2643 if (request_data.request_body.get()) { | |
2644 const std::vector<ResourceRequestBodyImpl::Element>* uploads = | |
2645 request_data.request_body->elements(); | |
2646 std::vector<ResourceRequestBodyImpl::Element>::const_iterator iter; | |
2647 for (iter = uploads->begin(); iter != uploads->end(); ++iter) { | |
2648 if (iter->type() == ResourceRequestBodyImpl::Element::TYPE_FILE && | |
2649 !policy->CanReadFile(child_id, iter->path())) { | |
2650 NOTREACHED() << "Denied unauthorized upload of " | |
2651 << iter->path().value(); | |
2652 return ABORT; | |
2653 } | |
2654 if (iter->type() == | |
2655 ResourceRequestBodyImpl::Element::TYPE_FILE_FILESYSTEM) { | |
2656 storage::FileSystemURL url = | |
2657 filter->file_system_context()->CrackURL(iter->filesystem_url()); | |
2658 if (!policy->CanReadFileSystemFile(child_id, url)) { | |
2659 NOTREACHED() << "Denied unauthorized upload of " | |
2660 << iter->filesystem_url().spec(); | |
2661 return ABORT; | |
2662 } | |
2663 } | |
2664 } | |
2665 } | |
2666 | |
2667 // Check if we have a registered interceptor for the headers passed in. If | |
2668 // yes then we need to mark the current request as pending and wait for the | |
2669 // interceptor to invoke the |callback| with a status code indicating whether | |
2670 // the request needs to be aborted or continued. | |
2671 for (net::HttpRequestHeaders::Iterator it(headers); it.GetNext();) { | |
2672 HeaderInterceptorMap::iterator index = | |
2673 http_header_interceptor_map_.find(it.name()); | |
2674 if (index != http_header_interceptor_map_.end()) { | |
2675 HeaderInterceptorInfo& interceptor_info = index->second; | |
2676 | |
2677 bool call_interceptor = true; | |
2678 if (!interceptor_info.starts_with.empty()) { | |
2679 call_interceptor = | |
2680 base::StartsWith(it.value(), interceptor_info.starts_with, | |
2681 base::CompareCase::INSENSITIVE_ASCII); | |
2682 } | |
2683 if (call_interceptor) { | |
2684 interceptor_info.interceptor.Run(it.name(), it.value(), child_id, | |
2685 resource_context, callback); | |
2686 return PENDING; | |
2687 } | |
2688 } | |
2689 } | |
2690 return CONTINUE; | |
2691 } | |
2692 | |
2608 } // namespace content | 2693 } // namespace content |
OLD | NEW |