| 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 "content/browser/child_process_security_policy_impl.h" | 5 #include "content/browser/child_process_security_policy_impl.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| (...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 436 | 436 |
| 437 return base::ContainsKey(pseudo_schemes_, scheme); | 437 return base::ContainsKey(pseudo_schemes_, scheme); |
| 438 } | 438 } |
| 439 | 439 |
| 440 void ChildProcessSecurityPolicyImpl::GrantRequestURL( | 440 void ChildProcessSecurityPolicyImpl::GrantRequestURL( |
| 441 int child_id, const GURL& url) { | 441 int child_id, const GURL& url) { |
| 442 | 442 |
| 443 if (!url.is_valid()) | 443 if (!url.is_valid()) |
| 444 return; // Can't grant the capability to request invalid URLs. | 444 return; // Can't grant the capability to request invalid URLs. |
| 445 | 445 |
| 446 if (IsWebSafeScheme(url.scheme())) | 446 const std::string& scheme = url.scheme(); |
| 447 |
| 448 if (IsWebSafeScheme(scheme)) |
| 447 return; // The scheme has already been whitelisted for every child process. | 449 return; // The scheme has already been whitelisted for every child process. |
| 448 | 450 |
| 449 if (IsPseudoScheme(url.scheme())) { | 451 if (IsPseudoScheme(scheme)) { |
| 450 return; // Can't grant the capability to request pseudo schemes. | 452 return; // Can't grant the capability to request pseudo schemes. |
| 451 } | 453 } |
| 452 | 454 |
| 453 if (url.SchemeIsBlob() || url.SchemeIsFileSystem()) { | 455 if (url.SchemeIsBlob() || url.SchemeIsFileSystem()) { |
| 454 return; // Don't grant blanket access to blob: or filesystem: schemes. | 456 return; // Don't grant blanket access to blob: or filesystem: schemes. |
| 455 } | 457 } |
| 456 | 458 |
| 457 { | 459 { |
| 458 base::AutoLock lock(lock_); | 460 base::AutoLock lock(lock_); |
| 459 SecurityStateMap::iterator state = security_state_.find(child_id); | 461 SecurityStateMap::iterator state = security_state_.find(child_id); |
| 460 if (state == security_state_.end()) | 462 if (state == security_state_.end()) |
| 461 return; | 463 return; |
| 462 | 464 |
| 463 // When the child process has been commanded to request this scheme, | 465 // When the child process has been commanded to request this scheme, |
| 464 // we grant it the capability to request all URLs of that scheme. | 466 // we grant it the capability to request all URLs of that scheme. |
| 465 state->second->GrantScheme(url.scheme()); | 467 state->second->GrantScheme(scheme); |
| 466 } | 468 } |
| 467 } | 469 } |
| 468 | 470 |
| 469 void ChildProcessSecurityPolicyImpl::GrantRequestSpecificFileURL( | 471 void ChildProcessSecurityPolicyImpl::GrantRequestSpecificFileURL( |
| 470 int child_id, | 472 int child_id, |
| 471 const GURL& url) { | 473 const GURL& url) { |
| 472 if (!url.SchemeIs(url::kFileScheme)) | 474 if (!url.SchemeIs(url::kFileScheme)) |
| 473 return; | 475 return; |
| 474 | 476 |
| 475 { | 477 { |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 625 return; | 627 return; |
| 626 | 628 |
| 627 state->second->RevokeReadRawCookies(); | 629 state->second->RevokeReadRawCookies(); |
| 628 } | 630 } |
| 629 | 631 |
| 630 bool ChildProcessSecurityPolicyImpl::CanRequestURL( | 632 bool ChildProcessSecurityPolicyImpl::CanRequestURL( |
| 631 int child_id, const GURL& url) { | 633 int child_id, const GURL& url) { |
| 632 if (!url.is_valid()) | 634 if (!url.is_valid()) |
| 633 return false; // Can't request invalid URLs. | 635 return false; // Can't request invalid URLs. |
| 634 | 636 |
| 635 if (IsPseudoScheme(url.scheme())) { | 637 const std::string& scheme = url.scheme(); |
| 638 |
| 639 if (IsPseudoScheme(scheme)) { |
| 636 // Every child process can request <about:blank>, <about:blank?foo>, | 640 // Every child process can request <about:blank>, <about:blank?foo>, |
| 637 // <about:blank/#foo> and <about:srcdoc>. | 641 // <about:blank/#foo> and <about:srcdoc>. |
| 638 if (url.IsAboutBlank() || url == kAboutSrcDocURL) | 642 if (url.IsAboutBlank() || url == kAboutSrcDocURL) |
| 639 return true; | 643 return true; |
| 640 // URLs like <about:version>, <about:crash>, <view-source:...> shouldn't be | 644 // URLs like <about:version>, <about:crash>, <view-source:...> shouldn't be |
| 641 // requestable by any child process. Also, this case covers | 645 // requestable by any child process. Also, this case covers |
| 642 // <javascript:...>, which should be handled internally by the process and | 646 // <javascript:...>, which should be handled internally by the process and |
| 643 // not kicked up to the browser. | 647 // not kicked up to the browser. |
| 644 return false; | 648 return false; |
| 645 } | 649 } |
| 646 | 650 |
| 647 // Blob and filesystem URLs require special treatment, since they embed an | 651 // Blob and filesystem URLs require special treatment, since they embed an |
| 648 // inner origin. | 652 // inner origin. |
| 649 if (url.SchemeIsBlob() || url.SchemeIsFileSystem()) { | 653 if (url.SchemeIsBlob() || url.SchemeIsFileSystem()) { |
| 650 if (IsMalformedBlobUrl(url)) | 654 if (IsMalformedBlobUrl(url)) |
| 651 return false; | 655 return false; |
| 652 | 656 |
| 653 url::Origin origin(url); | 657 url::Origin origin(url); |
| 654 return origin.unique() || IsWebSafeScheme(origin.scheme()) || | 658 return origin.unique() || IsWebSafeScheme(origin.scheme()) || |
| 655 CanCommitURL(child_id, GURL(origin.Serialize())); | 659 CanCommitURL(child_id, GURL(origin.Serialize())); |
| 656 } | 660 } |
| 657 | 661 |
| 658 if (IsWebSafeScheme(url.scheme())) | 662 if (IsWebSafeScheme(scheme)) |
| 659 return true; | 663 return true; |
| 660 | 664 |
| 661 // If the process can commit the URL, it can request it. | 665 // If the process can commit the URL, it can request it. |
| 662 if (CanCommitURL(child_id, url)) | 666 if (CanCommitURL(child_id, url)) |
| 663 return true; | 667 return true; |
| 664 | 668 |
| 665 // Also allow URLs destined for ShellExecute and not the browser itself. | 669 // Also allow URLs destined for ShellExecute and not the browser itself. |
| 666 return !GetContentClient()->browser()->IsHandledURL(url) && | 670 return !GetContentClient()->browser()->IsHandledURL(url) && |
| 667 !net::URLRequest::IsHandledURL(url); | 671 !net::URLRequest::IsHandledURL(url); |
| 668 } | 672 } |
| 669 | 673 |
| 670 bool ChildProcessSecurityPolicyImpl::CanCommitURL(int child_id, | 674 bool ChildProcessSecurityPolicyImpl::CanCommitURL(int child_id, |
| 671 const GURL& url) { | 675 const GURL& url) { |
| 672 if (!url.is_valid()) | 676 if (!url.is_valid()) |
| 673 return false; // Can't commit invalid URLs. | 677 return false; // Can't commit invalid URLs. |
| 674 | 678 |
| 679 const std::string& scheme = url.scheme(); |
| 680 |
| 675 // Of all the pseudo schemes, only about:blank and about:srcdoc are allowed to | 681 // Of all the pseudo schemes, only about:blank and about:srcdoc are allowed to |
| 676 // commit. | 682 // commit. |
| 677 if (IsPseudoScheme(url.scheme())) | 683 if (IsPseudoScheme(scheme)) |
| 678 return url == url::kAboutBlankURL || url == kAboutSrcDocURL; | 684 return url == url::kAboutBlankURL || url == kAboutSrcDocURL; |
| 679 | 685 |
| 680 // Blob and filesystem URLs require special treatment; validate the inner | 686 // Blob and filesystem URLs require special treatment; validate the inner |
| 681 // origin they embed. | 687 // origin they embed. |
| 682 if (url.SchemeIsBlob() || url.SchemeIsFileSystem()) { | 688 if (url.SchemeIsBlob() || url.SchemeIsFileSystem()) { |
| 683 if (IsMalformedBlobUrl(url)) | 689 if (IsMalformedBlobUrl(url)) |
| 684 return false; | 690 return false; |
| 685 | 691 |
| 686 url::Origin origin(url); | 692 url::Origin origin(url); |
| 687 return origin.unique() || CanCommitURL(child_id, GURL(origin.Serialize())); | 693 return origin.unique() || CanCommitURL(child_id, GURL(origin.Serialize())); |
| 688 } | 694 } |
| 689 | 695 |
| 690 { | 696 { |
| 691 base::AutoLock lock(lock_); | 697 base::AutoLock lock(lock_); |
| 692 | 698 |
| 693 // Most schemes can commit in any process. Note that we check | 699 // Most schemes can commit in any process. Note that we check |
| 694 // schemes_okay_to_commit_in_any_process_ here, which is stricter than | 700 // schemes_okay_to_commit_in_any_process_ here, which is stricter than |
| 695 // IsWebSafeScheme(). | 701 // IsWebSafeScheme(). |
| 696 // | 702 // |
| 697 // TODO(creis, nick): https://crbug.com/515309: in generalized Site | 703 // TODO(creis, nick): https://crbug.com/515309: in generalized Site |
| 698 // Isolation and/or --site-per-process, there will be no such thing as a | 704 // Isolation and/or --site-per-process, there will be no such thing as a |
| 699 // scheme that is okay to commit in any process. Instead, an URL from a site | 705 // scheme that is okay to commit in any process. Instead, an URL from a site |
| 700 // that is isolated may only be committed in a process dedicated to that | 706 // that is isolated may only be committed in a process dedicated to that |
| 701 // site, so CanCommitURL will need to rely on explicit, per-process grants. | 707 // site, so CanCommitURL will need to rely on explicit, per-process grants. |
| 702 // Note how today, even with extension isolation, the line below does not | 708 // Note how today, even with extension isolation, the line below does not |
| 703 // enforce that http pages cannot commit in an extension process. | 709 // enforce that http pages cannot commit in an extension process. |
| 704 if (base::ContainsKey(schemes_okay_to_commit_in_any_process_, url.scheme())) | 710 if (base::ContainsKey(schemes_okay_to_commit_in_any_process_, scheme)) |
| 705 return true; | 711 return true; |
| 706 | 712 |
| 707 SecurityStateMap::iterator state = security_state_.find(child_id); | 713 SecurityStateMap::iterator state = security_state_.find(child_id); |
| 708 if (state == security_state_.end()) | 714 if (state == security_state_.end()) |
| 709 return false; | 715 return false; |
| 710 | 716 |
| 711 // Otherwise, we consult the child process's security state to see if it is | 717 // Otherwise, we consult the child process's security state to see if it is |
| 712 // allowed to commit the URL. | 718 // allowed to commit the URL. |
| 713 return state->second->CanCommitURL(url); | 719 return state->second->CanCommitURL(url); |
| 714 } | 720 } |
| 715 } | 721 } |
| 716 | 722 |
| 717 bool ChildProcessSecurityPolicyImpl::CanSetAsOriginHeader(int child_id, | 723 bool ChildProcessSecurityPolicyImpl::CanSetAsOriginHeader(int child_id, |
| 718 const GURL& url) { | 724 const GURL& url) { |
| 719 if (!url.is_valid()) | 725 if (!url.is_valid()) |
| 720 return false; // Can't set invalid URLs as origin headers. | 726 return false; // Can't set invalid URLs as origin headers. |
| 721 | 727 |
| 728 const std::string& scheme = url.scheme(); |
| 729 |
| 722 // Suborigin URLs are a special case and are allowed to be an origin header. | 730 // Suborigin URLs are a special case and are allowed to be an origin header. |
| 723 if (url.scheme() == url::kHttpSuboriginScheme || | 731 if (scheme == url::kHttpSuboriginScheme || |
| 724 url.scheme() == url::kHttpsSuboriginScheme) { | 732 scheme == url::kHttpsSuboriginScheme) { |
| 725 DCHECK(IsPseudoScheme(url.scheme())); | 733 DCHECK(IsPseudoScheme(scheme)); |
| 726 return true; | 734 return true; |
| 727 } | 735 } |
| 728 | 736 |
| 729 // about:srcdoc cannot be used as an origin | 737 // about:srcdoc cannot be used as an origin |
| 730 if (url == kAboutSrcDocURL) | 738 if (url == kAboutSrcDocURL) |
| 731 return false; | 739 return false; |
| 732 | 740 |
| 733 // If this process can commit |url|, it can use |url| as an origin for | 741 // If this process can commit |url|, it can use |url| as an origin for |
| 734 // outbound requests. | 742 // outbound requests. |
| 735 if (CanCommitURL(child_id, url)) | 743 if (CanCommitURL(child_id, url)) |
| 736 return true; | 744 return true; |
| 737 | 745 |
| 738 // Allow schemes which may come from scripts executing in isolated worlds; | 746 // Allow schemes which may come from scripts executing in isolated worlds; |
| 739 // XHRs issued by such scripts reflect the script origin rather than the | 747 // XHRs issued by such scripts reflect the script origin rather than the |
| 740 // document origin. | 748 // document origin. |
| 741 { | 749 { |
| 742 base::AutoLock lock(lock_); | 750 base::AutoLock lock(lock_); |
| 743 if (base::ContainsKey(schemes_okay_to_appear_as_origin_headers_, | 751 if (base::ContainsKey(schemes_okay_to_appear_as_origin_headers_, scheme)) |
| 744 url.scheme())) | |
| 745 return true; | 752 return true; |
| 746 } | 753 } |
| 747 return false; | 754 return false; |
| 748 } | 755 } |
| 749 | 756 |
| 750 bool ChildProcessSecurityPolicyImpl::CanReadFile(int child_id, | 757 bool ChildProcessSecurityPolicyImpl::CanReadFile(int child_id, |
| 751 const base::FilePath& file) { | 758 const base::FilePath& file) { |
| 752 return HasPermissionsForFile(child_id, file, READ_FILE_GRANT); | 759 return HasPermissionsForFile(child_id, file, READ_FILE_GRANT); |
| 753 } | 760 } |
| 754 | 761 |
| (...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1143 return found; | 1150 return found; |
| 1144 } | 1151 } |
| 1145 | 1152 |
| 1146 void ChildProcessSecurityPolicyImpl::RemoveIsolatedOriginForTesting( | 1153 void ChildProcessSecurityPolicyImpl::RemoveIsolatedOriginForTesting( |
| 1147 const url::Origin& origin) { | 1154 const url::Origin& origin) { |
| 1148 base::AutoLock lock(lock_); | 1155 base::AutoLock lock(lock_); |
| 1149 isolated_origins_.erase(origin); | 1156 isolated_origins_.erase(origin); |
| 1150 } | 1157 } |
| 1151 | 1158 |
| 1152 } // namespace content | 1159 } // namespace content |
| OLD | NEW |