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 |