| 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 "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/file_path.h" | 8 #include "base/file_path.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 73 void GrantScheme(const std::string& scheme) { | 73 void GrantScheme(const std::string& scheme) { |
| 74 scheme_policy_[scheme] = true; | 74 scheme_policy_[scheme] = true; |
| 75 } | 75 } |
| 76 | 76 |
| 77 // Revoke permission to request URLs with the specified scheme. | 77 // Revoke permission to request URLs with the specified scheme. |
| 78 void RevokeScheme(const std::string& scheme) { | 78 void RevokeScheme(const std::string& scheme) { |
| 79 scheme_policy_[scheme] = false; | 79 scheme_policy_[scheme] = false; |
| 80 } | 80 } |
| 81 | 81 |
| 82 // Grant certain permissions to a file. | 82 // Grant certain permissions to a file. |
| 83 void GrantPermissionsForFile(const FilePath& file, int permissions) { | 83 void GrantPermissionsForFile(const base::FilePath& file, int permissions) { |
| 84 FilePath stripped = file.StripTrailingSeparators(); | 84 base::FilePath stripped = file.StripTrailingSeparators(); |
| 85 file_permissions_[stripped] |= permissions; | 85 file_permissions_[stripped] |= permissions; |
| 86 UMA_HISTOGRAM_COUNTS("ChildProcessSecurityPolicy.FilePermissionPathLength", | 86 UMA_HISTOGRAM_COUNTS("ChildProcessSecurityPolicy.FilePermissionPathLength", |
| 87 stripped.value().size()); | 87 stripped.value().size()); |
| 88 } | 88 } |
| 89 | 89 |
| 90 // Grant navigation to a file but not the file:// scheme in general. | 90 // Grant navigation to a file but not the file:// scheme in general. |
| 91 void GrantRequestOfSpecificFile(const FilePath &file) { | 91 void GrantRequestOfSpecificFile(const base::FilePath &file) { |
| 92 request_file_set_.insert(file.StripTrailingSeparators()); | 92 request_file_set_.insert(file.StripTrailingSeparators()); |
| 93 } | 93 } |
| 94 | 94 |
| 95 // Revokes all permissions granted to a file. | 95 // Revokes all permissions granted to a file. |
| 96 void RevokeAllPermissionsForFile(const FilePath& file) { | 96 void RevokeAllPermissionsForFile(const base::FilePath& file) { |
| 97 FilePath stripped = file.StripTrailingSeparators(); | 97 base::FilePath stripped = file.StripTrailingSeparators(); |
| 98 file_permissions_.erase(stripped); | 98 file_permissions_.erase(stripped); |
| 99 request_file_set_.erase(stripped); | 99 request_file_set_.erase(stripped); |
| 100 } | 100 } |
| 101 | 101 |
| 102 // Grant certain permissions to a file. | 102 // Grant certain permissions to a file. |
| 103 void GrantPermissionsForFileSystem(const std::string& filesystem_id, | 103 void GrantPermissionsForFileSystem(const std::string& filesystem_id, |
| 104 int permissions) { | 104 int permissions) { |
| 105 if (filesystem_permissions_.find(filesystem_id) == | 105 if (filesystem_permissions_.find(filesystem_id) == |
| 106 filesystem_permissions_.end()) | 106 filesystem_permissions_.end()) |
| 107 fileapi::IsolatedContext::GetInstance()->AddReference(filesystem_id); | 107 fileapi::IsolatedContext::GetInstance()->AddReference(filesystem_id); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 132 // Determine whether permission has been granted to request |url|. | 132 // Determine whether permission has been granted to request |url|. |
| 133 bool CanRequestURL(const GURL& url) { | 133 bool CanRequestURL(const GURL& url) { |
| 134 // Having permission to a scheme implies permssion to all of its URLs. | 134 // Having permission to a scheme implies permssion to all of its URLs. |
| 135 SchemeMap::const_iterator judgment(scheme_policy_.find(url.scheme())); | 135 SchemeMap::const_iterator judgment(scheme_policy_.find(url.scheme())); |
| 136 if (judgment != scheme_policy_.end()) | 136 if (judgment != scheme_policy_.end()) |
| 137 return judgment->second; | 137 return judgment->second; |
| 138 | 138 |
| 139 // file:// URLs are more granular. The child may have been given | 139 // file:// URLs are more granular. The child may have been given |
| 140 // permission to a specific file but not the file:// scheme in general. | 140 // permission to a specific file but not the file:// scheme in general. |
| 141 if (url.SchemeIs(chrome::kFileScheme)) { | 141 if (url.SchemeIs(chrome::kFileScheme)) { |
| 142 FilePath path; | 142 base::FilePath path; |
| 143 if (net::FileURLToFilePath(url, &path)) | 143 if (net::FileURLToFilePath(url, &path)) |
| 144 return request_file_set_.find(path) != request_file_set_.end(); | 144 return request_file_set_.find(path) != request_file_set_.end(); |
| 145 } | 145 } |
| 146 | 146 |
| 147 return false; // Unmentioned schemes are disallowed. | 147 return false; // Unmentioned schemes are disallowed. |
| 148 } | 148 } |
| 149 | 149 |
| 150 // Determine if the certain permissions have been granted to a file. | 150 // Determine if the certain permissions have been granted to a file. |
| 151 bool HasPermissionsForFile(const FilePath& file, int permissions) { | 151 bool HasPermissionsForFile(const base::FilePath& file, int permissions) { |
| 152 if (!permissions || file.empty() || !file.IsAbsolute()) | 152 if (!permissions || file.empty() || !file.IsAbsolute()) |
| 153 return false; | 153 return false; |
| 154 FilePath current_path = file.StripTrailingSeparators(); | 154 base::FilePath current_path = file.StripTrailingSeparators(); |
| 155 FilePath last_path; | 155 base::FilePath last_path; |
| 156 int skip = 0; | 156 int skip = 0; |
| 157 while (current_path != last_path) { | 157 while (current_path != last_path) { |
| 158 FilePath base_name = current_path.BaseName(); | 158 base::FilePath base_name = current_path.BaseName(); |
| 159 if (base_name.value() == FilePath::kParentDirectory) { | 159 if (base_name.value() == base::FilePath::kParentDirectory) { |
| 160 ++skip; | 160 ++skip; |
| 161 } else if (skip > 0) { | 161 } else if (skip > 0) { |
| 162 if (base_name.value() != FilePath::kCurrentDirectory) | 162 if (base_name.value() != base::FilePath::kCurrentDirectory) |
| 163 --skip; | 163 --skip; |
| 164 } else { | 164 } else { |
| 165 if (file_permissions_.find(current_path) != file_permissions_.end()) | 165 if (file_permissions_.find(current_path) != file_permissions_.end()) |
| 166 return (file_permissions_[current_path] & permissions) == permissions; | 166 return (file_permissions_[current_path] & permissions) == permissions; |
| 167 } | 167 } |
| 168 last_path = current_path; | 168 last_path = current_path; |
| 169 current_path = current_path.DirName(); | 169 current_path = current_path.DirName(); |
| 170 } | 170 } |
| 171 | 171 |
| 172 return false; | 172 return false; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 221 } | 221 } |
| 222 | 222 |
| 223 bool can_read_raw_cookies() const { | 223 bool can_read_raw_cookies() const { |
| 224 return can_read_raw_cookies_; | 224 return can_read_raw_cookies_; |
| 225 } | 225 } |
| 226 | 226 |
| 227 private: | 227 private: |
| 228 typedef std::map<std::string, bool> SchemeMap; | 228 typedef std::map<std::string, bool> SchemeMap; |
| 229 | 229 |
| 230 typedef int FilePermissionFlags; // bit-set of PlatformFileFlags | 230 typedef int FilePermissionFlags; // bit-set of PlatformFileFlags |
| 231 typedef std::map<FilePath, FilePermissionFlags> FileMap; | 231 typedef std::map<base::FilePath, FilePermissionFlags> FileMap; |
| 232 typedef std::map<std::string, FilePermissionFlags> FileSystemMap; | 232 typedef std::map<std::string, FilePermissionFlags> FileSystemMap; |
| 233 typedef std::set<FilePath> FileSet; | 233 typedef std::set<base::FilePath> FileSet; |
| 234 | 234 |
| 235 // Maps URL schemes to whether permission has been granted or revoked: | 235 // Maps URL schemes to whether permission has been granted or revoked: |
| 236 // |true| means the scheme has been granted. | 236 // |true| means the scheme has been granted. |
| 237 // |false| means the scheme has been revoked. | 237 // |false| means the scheme has been revoked. |
| 238 // If a scheme is not present in the map, then it has never been granted | 238 // If a scheme is not present in the map, then it has never been granted |
| 239 // or revoked. | 239 // or revoked. |
| 240 SchemeMap scheme_policy_; | 240 SchemeMap scheme_policy_; |
| 241 | 241 |
| 242 // The set of files the child process is permited to upload to the web. | 242 // The set of files the child process is permited to upload to the web. |
| 243 FileMap file_permissions_; | 243 FileMap file_permissions_; |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 399 return; | 399 return; |
| 400 | 400 |
| 401 { | 401 { |
| 402 base::AutoLock lock(lock_); | 402 base::AutoLock lock(lock_); |
| 403 SecurityStateMap::iterator state = security_state_.find(child_id); | 403 SecurityStateMap::iterator state = security_state_.find(child_id); |
| 404 if (state == security_state_.end()) | 404 if (state == security_state_.end()) |
| 405 return; | 405 return; |
| 406 | 406 |
| 407 // When the child process has been commanded to request a file:// URL, | 407 // When the child process has been commanded to request a file:// URL, |
| 408 // then we grant it the capability for that URL only. | 408 // then we grant it the capability for that URL only. |
| 409 FilePath path; | 409 base::FilePath path; |
| 410 if (net::FileURLToFilePath(url, &path)) | 410 if (net::FileURLToFilePath(url, &path)) |
| 411 state->second->GrantRequestOfSpecificFile(path); | 411 state->second->GrantRequestOfSpecificFile(path); |
| 412 } | 412 } |
| 413 } | 413 } |
| 414 | 414 |
| 415 void ChildProcessSecurityPolicyImpl::GrantReadFile(int child_id, | 415 void ChildProcessSecurityPolicyImpl::GrantReadFile(int child_id, |
| 416 const FilePath& file) { | 416 const base::FilePath& file) { |
| 417 GrantPermissionsForFile(child_id, file, kReadFilePermissions); | 417 GrantPermissionsForFile(child_id, file, kReadFilePermissions); |
| 418 } | 418 } |
| 419 | 419 |
| 420 void ChildProcessSecurityPolicyImpl::GrantReadDirectory( | 420 void ChildProcessSecurityPolicyImpl::GrantReadDirectory( |
| 421 int child_id, const FilePath& directory) { | 421 int child_id, const base::FilePath& directory) { |
| 422 GrantPermissionsForFile(child_id, directory, kEnumerateDirectoryPermissions); | 422 GrantPermissionsForFile(child_id, directory, kEnumerateDirectoryPermissions); |
| 423 } | 423 } |
| 424 | 424 |
| 425 void ChildProcessSecurityPolicyImpl::GrantPermissionsForFile( | 425 void ChildProcessSecurityPolicyImpl::GrantPermissionsForFile( |
| 426 int child_id, const FilePath& file, int permissions) { | 426 int child_id, const base::FilePath& file, int permissions) { |
| 427 base::AutoLock lock(lock_); | 427 base::AutoLock lock(lock_); |
| 428 | 428 |
| 429 SecurityStateMap::iterator state = security_state_.find(child_id); | 429 SecurityStateMap::iterator state = security_state_.find(child_id); |
| 430 if (state == security_state_.end()) | 430 if (state == security_state_.end()) |
| 431 return; | 431 return; |
| 432 | 432 |
| 433 state->second->GrantPermissionsForFile(file, permissions); | 433 state->second->GrantPermissionsForFile(file, permissions); |
| 434 } | 434 } |
| 435 | 435 |
| 436 void ChildProcessSecurityPolicyImpl::RevokeAllPermissionsForFile( | 436 void ChildProcessSecurityPolicyImpl::RevokeAllPermissionsForFile( |
| 437 int child_id, const FilePath& file) { | 437 int child_id, const base::FilePath& file) { |
| 438 base::AutoLock lock(lock_); | 438 base::AutoLock lock(lock_); |
| 439 | 439 |
| 440 SecurityStateMap::iterator state = security_state_.find(child_id); | 440 SecurityStateMap::iterator state = security_state_.find(child_id); |
| 441 if (state == security_state_.end()) | 441 if (state == security_state_.end()) |
| 442 return; | 442 return; |
| 443 | 443 |
| 444 state->second->RevokeAllPermissionsForFile(file); | 444 state->second->RevokeAllPermissionsForFile(file); |
| 445 } | 445 } |
| 446 | 446 |
| 447 void ChildProcessSecurityPolicyImpl::GrantReadFileSystem( | 447 void ChildProcessSecurityPolicyImpl::GrantReadFileSystem( |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 568 if (state == security_state_.end()) | 568 if (state == security_state_.end()) |
| 569 return false; | 569 return false; |
| 570 | 570 |
| 571 // Otherwise, we consult the child process's security state to see if it is | 571 // Otherwise, we consult the child process's security state to see if it is |
| 572 // allowed to request the URL. | 572 // allowed to request the URL. |
| 573 return state->second->CanRequestURL(url); | 573 return state->second->CanRequestURL(url); |
| 574 } | 574 } |
| 575 } | 575 } |
| 576 | 576 |
| 577 bool ChildProcessSecurityPolicyImpl::CanReadFile(int child_id, | 577 bool ChildProcessSecurityPolicyImpl::CanReadFile(int child_id, |
| 578 const FilePath& file) { | 578 const base::FilePath& file) { |
| 579 return HasPermissionsForFile(child_id, file, kReadFilePermissions); | 579 return HasPermissionsForFile(child_id, file, kReadFilePermissions); |
| 580 } | 580 } |
| 581 | 581 |
| 582 bool ChildProcessSecurityPolicyImpl::CanReadDirectory( | 582 bool ChildProcessSecurityPolicyImpl::CanReadDirectory( |
| 583 int child_id, const FilePath& directory) { | 583 int child_id, const base::FilePath& directory) { |
| 584 return HasPermissionsForFile(child_id, | 584 return HasPermissionsForFile(child_id, |
| 585 directory, | 585 directory, |
| 586 kEnumerateDirectoryPermissions); | 586 kEnumerateDirectoryPermissions); |
| 587 } | 587 } |
| 588 | 588 |
| 589 bool ChildProcessSecurityPolicyImpl::CanReadFileSystem( | 589 bool ChildProcessSecurityPolicyImpl::CanReadFileSystem( |
| 590 int child_id, const std::string& filesystem_id) { | 590 int child_id, const std::string& filesystem_id) { |
| 591 return HasPermissionsForFileSystem(child_id, | 591 return HasPermissionsForFileSystem(child_id, |
| 592 filesystem_id, | 592 filesystem_id, |
| 593 kReadFilePermissions); | 593 kReadFilePermissions); |
| 594 } | 594 } |
| 595 | 595 |
| 596 bool ChildProcessSecurityPolicyImpl::CanReadWriteFileSystem( | 596 bool ChildProcessSecurityPolicyImpl::CanReadWriteFileSystem( |
| 597 int child_id, const std::string& filesystem_id) { | 597 int child_id, const std::string& filesystem_id) { |
| 598 return HasPermissionsForFileSystem(child_id, | 598 return HasPermissionsForFileSystem(child_id, |
| 599 filesystem_id, | 599 filesystem_id, |
| 600 kReadFilePermissions | | 600 kReadFilePermissions | |
| 601 kWriteFilePermissions); | 601 kWriteFilePermissions); |
| 602 } | 602 } |
| 603 | 603 |
| 604 bool ChildProcessSecurityPolicyImpl::HasPermissionsForFile( | 604 bool ChildProcessSecurityPolicyImpl::HasPermissionsForFile( |
| 605 int child_id, const FilePath& file, int permissions) { | 605 int child_id, const base::FilePath& file, int permissions) { |
| 606 base::AutoLock lock(lock_); | 606 base::AutoLock lock(lock_); |
| 607 bool result = ChildProcessHasPermissionsForFile(child_id, file, permissions); | 607 bool result = ChildProcessHasPermissionsForFile(child_id, file, permissions); |
| 608 if (!result) { | 608 if (!result) { |
| 609 // If this is a worker thread that has no access to a given file, | 609 // If this is a worker thread that has no access to a given file, |
| 610 // let's check that its renderer process has access to that file instead. | 610 // let's check that its renderer process has access to that file instead. |
| 611 WorkerToMainProcessMap::iterator iter = worker_map_.find(child_id); | 611 WorkerToMainProcessMap::iterator iter = worker_map_.find(child_id); |
| 612 if (iter != worker_map_.end() && iter->second != 0) { | 612 if (iter != worker_map_.end() && iter->second != 0) { |
| 613 result = ChildProcessHasPermissionsForFile(iter->second, | 613 result = ChildProcessHasPermissionsForFile(iter->second, |
| 614 file, | 614 file, |
| 615 permissions); | 615 permissions); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 641 void ChildProcessSecurityPolicyImpl::AddChild(int child_id) { | 641 void ChildProcessSecurityPolicyImpl::AddChild(int child_id) { |
| 642 if (security_state_.count(child_id) != 0) { | 642 if (security_state_.count(child_id) != 0) { |
| 643 NOTREACHED() << "Add child process at most once."; | 643 NOTREACHED() << "Add child process at most once."; |
| 644 return; | 644 return; |
| 645 } | 645 } |
| 646 | 646 |
| 647 security_state_[child_id] = new SecurityState(); | 647 security_state_[child_id] = new SecurityState(); |
| 648 } | 648 } |
| 649 | 649 |
| 650 bool ChildProcessSecurityPolicyImpl::ChildProcessHasPermissionsForFile( | 650 bool ChildProcessSecurityPolicyImpl::ChildProcessHasPermissionsForFile( |
| 651 int child_id, const FilePath& file, int permissions) { | 651 int child_id, const base::FilePath& file, int permissions) { |
| 652 SecurityStateMap::iterator state = security_state_.find(child_id); | 652 SecurityStateMap::iterator state = security_state_.find(child_id); |
| 653 if (state == security_state_.end()) | 653 if (state == security_state_.end()) |
| 654 return false; | 654 return false; |
| 655 return state->second->HasPermissionsForFile(file, permissions); | 655 return state->second->HasPermissionsForFile(file, permissions); |
| 656 } | 656 } |
| 657 | 657 |
| 658 bool ChildProcessSecurityPolicyImpl::CanAccessCookiesForOrigin( | 658 bool ChildProcessSecurityPolicyImpl::CanAccessCookiesForOrigin( |
| 659 int child_id, const GURL& gurl) { | 659 int child_id, const GURL& gurl) { |
| 660 base::AutoLock lock(lock_); | 660 base::AutoLock lock(lock_); |
| 661 SecurityStateMap::iterator state = security_state_.find(child_id); | 661 SecurityStateMap::iterator state = security_state_.find(child_id); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 701 int permission) { | 701 int permission) { |
| 702 base::AutoLock lock(lock_); | 702 base::AutoLock lock(lock_); |
| 703 | 703 |
| 704 SecurityStateMap::iterator state = security_state_.find(child_id); | 704 SecurityStateMap::iterator state = security_state_.find(child_id); |
| 705 if (state == security_state_.end()) | 705 if (state == security_state_.end()) |
| 706 return false; | 706 return false; |
| 707 return state->second->HasPermissionsForFileSystem(filesystem_id, permission); | 707 return state->second->HasPermissionsForFileSystem(filesystem_id, permission); |
| 708 } | 708 } |
| 709 | 709 |
| 710 } // namespace content | 710 } // namespace content |
| OLD | NEW |