child_process_security_policy_impl.cc revision 010d83a9304c5a91596085d917d248abff47903a
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 3// found in the LICENSE file. 4 5#include "content/browser/child_process_security_policy_impl.h" 6 7#include "base/command_line.h" 8#include "base/files/file_path.h" 9#include "base/logging.h" 10#include "base/metrics/histogram.h" 11#include "base/platform_file.h" 12#include "base/stl_util.h" 13#include "base/strings/string_util.h" 14#include "content/browser/plugin_process_host.h" 15#include "content/browser/site_instance_impl.h" 16#include "content/public/browser/child_process_data.h" 17#include "content/public/browser/content_browser_client.h" 18#include "content/public/browser/render_process_host.h" 19#include "content/public/common/bindings_policy.h" 20#include "content/public/common/content_switches.h" 21#include "content/public/common/url_constants.h" 22#include "net/base/filename_util.h" 23#include "net/url_request/url_request.h" 24#include "url/gurl.h" 25#include "webkit/browser/fileapi/file_permission_policy.h" 26#include "webkit/browser/fileapi/file_system_url.h" 27#include "webkit/browser/fileapi/isolated_context.h" 28#include "webkit/common/fileapi/file_system_util.h" 29 30namespace content { 31 32namespace { 33 34// Used internally only. These bit positions have no relationship to any 35// underlying OS and can be changed to accommodate finer-grained permissions. 36enum ChildProcessSecurityPermissions { 37 READ_FILE_PERMISSION = 1 << 0, 38 WRITE_FILE_PERMISSION = 1 << 1, 39 CREATE_NEW_FILE_PERMISSION = 1 << 2, 40 CREATE_OVERWRITE_FILE_PERMISSION = 1 << 3, 41 DELETE_FILE_PERMISSION = 1 << 4, 42 43 // Used by Media Galleries API 44 COPY_INTO_FILE_PERMISSION = 1 << 5, 45}; 46 47// Used internally only. Bitmasks that are actually used by the Grant* and Can* 48// methods. These contain one or more ChildProcessSecurityPermissions. 49enum ChildProcessSecurityGrants { 50 READ_FILE_GRANT = READ_FILE_PERMISSION, 51 WRITE_FILE_GRANT = WRITE_FILE_PERMISSION, 52 53 CREATE_NEW_FILE_GRANT = CREATE_NEW_FILE_PERMISSION | 54 COPY_INTO_FILE_PERMISSION, 55 56 CREATE_READ_WRITE_FILE_GRANT = CREATE_NEW_FILE_PERMISSION | 57 CREATE_OVERWRITE_FILE_PERMISSION | 58 READ_FILE_PERMISSION | 59 WRITE_FILE_PERMISSION | 60 COPY_INTO_FILE_PERMISSION | 61 DELETE_FILE_PERMISSION, 62 63 COPY_INTO_FILE_GRANT = COPY_INTO_FILE_PERMISSION, 64 DELETE_FILE_GRANT = DELETE_FILE_PERMISSION, 65}; 66 67} // namespace 68 69// The SecurityState class is used to maintain per-child process security state 70// information. 71class ChildProcessSecurityPolicyImpl::SecurityState { 72 public: 73 SecurityState() 74 : enabled_bindings_(0), 75 can_read_raw_cookies_(false), 76 can_send_midi_sysex_(false) { } 77 78 ~SecurityState() { 79 scheme_policy_.clear(); 80 fileapi::IsolatedContext* isolated_context = 81 fileapi::IsolatedContext::GetInstance(); 82 for (FileSystemMap::iterator iter = filesystem_permissions_.begin(); 83 iter != filesystem_permissions_.end(); 84 ++iter) { 85 isolated_context->RemoveReference(iter->first); 86 } 87 UMA_HISTOGRAM_COUNTS("ChildProcessSecurityPolicy.PerChildFilePermissions", 88 file_permissions_.size()); 89 } 90 91 // Grant permission to request URLs with the specified scheme. 92 void GrantScheme(const std::string& scheme) { 93 scheme_policy_[scheme] = true; 94 } 95 96 // Revoke permission to request URLs with the specified scheme. 97 void RevokeScheme(const std::string& scheme) { 98 scheme_policy_[scheme] = false; 99 } 100 101 // Grant certain permissions to a file. 102 void GrantPermissionsForFile(const base::FilePath& file, int permissions) { 103 base::FilePath stripped = file.StripTrailingSeparators(); 104 file_permissions_[stripped] |= permissions; 105 UMA_HISTOGRAM_COUNTS("ChildProcessSecurityPolicy.FilePermissionPathLength", 106 stripped.value().size()); 107 } 108 109 // Grant navigation to a file but not the file:// scheme in general. 110 void GrantRequestOfSpecificFile(const base::FilePath &file) { 111 request_file_set_.insert(file.StripTrailingSeparators()); 112 } 113 114 // Revokes all permissions granted to a file. 115 void RevokeAllPermissionsForFile(const base::FilePath& file) { 116 base::FilePath stripped = file.StripTrailingSeparators(); 117 file_permissions_.erase(stripped); 118 request_file_set_.erase(stripped); 119 } 120 121 // Grant certain permissions to a file. 122 void GrantPermissionsForFileSystem(const std::string& filesystem_id, 123 int permissions) { 124 if (!ContainsKey(filesystem_permissions_, filesystem_id)) 125 fileapi::IsolatedContext::GetInstance()->AddReference(filesystem_id); 126 filesystem_permissions_[filesystem_id] |= permissions; 127 } 128 129 bool HasPermissionsForFileSystem(const std::string& filesystem_id, 130 int permissions) { 131 FileSystemMap::const_iterator it = 132 filesystem_permissions_.find(filesystem_id); 133 if (it == filesystem_permissions_.end()) 134 return false; 135 return (it->second & permissions) == permissions; 136 } 137 138#if defined(OS_ANDROID) 139 // Determine if the certain permissions have been granted to a content URI. 140 bool HasPermissionsForContentUri(const base::FilePath& file, 141 int permissions) { 142 DCHECK(!file.empty()); 143 DCHECK(file.IsContentUri()); 144 if (!permissions) 145 return false; 146 base::FilePath file_path = file.StripTrailingSeparators(); 147 FileMap::const_iterator it = file_permissions_.find(file_path); 148 if (it != file_permissions_.end()) 149 return (it->second & permissions) == permissions; 150 return false; 151 } 152#endif 153 154 void GrantBindings(int bindings) { 155 enabled_bindings_ |= bindings; 156 } 157 158 void GrantReadRawCookies() { 159 can_read_raw_cookies_ = true; 160 } 161 162 void RevokeReadRawCookies() { 163 can_read_raw_cookies_ = false; 164 } 165 166 void GrantPermissionForMidiSysEx() { 167 can_send_midi_sysex_ = true; 168 } 169 170 // Determine whether permission has been granted to request |url|. 171 bool CanRequestURL(const GURL& url) { 172 // Having permission to a scheme implies permssion to all of its URLs. 173 SchemeMap::const_iterator judgment(scheme_policy_.find(url.scheme())); 174 if (judgment != scheme_policy_.end()) 175 return judgment->second; 176 177 // file:// URLs are more granular. The child may have been given 178 // permission to a specific file but not the file:// scheme in general. 179 if (url.SchemeIs(kFileScheme)) { 180 base::FilePath path; 181 if (net::FileURLToFilePath(url, &path)) 182 return ContainsKey(request_file_set_, path); 183 } 184 185 return false; // Unmentioned schemes are disallowed. 186 } 187 188 // Determine if the certain permissions have been granted to a file. 189 bool HasPermissionsForFile(const base::FilePath& file, int permissions) { 190#if defined(OS_ANDROID) 191 if (file.IsContentUri()) 192 return HasPermissionsForContentUri(file, permissions); 193#endif 194 if (!permissions || file.empty() || !file.IsAbsolute()) 195 return false; 196 base::FilePath current_path = file.StripTrailingSeparators(); 197 base::FilePath last_path; 198 int skip = 0; 199 while (current_path != last_path) { 200 base::FilePath base_name = current_path.BaseName(); 201 if (base_name.value() == base::FilePath::kParentDirectory) { 202 ++skip; 203 } else if (skip > 0) { 204 if (base_name.value() != base::FilePath::kCurrentDirectory) 205 --skip; 206 } else { 207 FileMap::const_iterator it = file_permissions_.find(current_path); 208 if (it != file_permissions_.end()) 209 return (it->second & permissions) == permissions; 210 } 211 last_path = current_path; 212 current_path = current_path.DirName(); 213 } 214 215 return false; 216 } 217 218 bool CanLoadPage(const GURL& gurl) { 219 if (origin_lock_.is_empty()) 220 return true; 221 222 // TODO(creis): We must pass the valid browser_context to convert hosted 223 // apps URLs. Currently, hosted apps cannot be loaded in this mode. 224 // See http://crbug.com/160576. 225 GURL site_gurl = SiteInstanceImpl::GetSiteForURL(NULL, gurl); 226 return origin_lock_ == site_gurl; 227 } 228 229 bool CanAccessCookiesForOrigin(const GURL& gurl) { 230 if (origin_lock_.is_empty()) 231 return true; 232 // TODO(creis): We must pass the valid browser_context to convert hosted 233 // apps URLs. Currently, hosted apps cannot set cookies in this mode. 234 // See http://crbug.com/160576. 235 GURL site_gurl = SiteInstanceImpl::GetSiteForURL(NULL, gurl); 236 return origin_lock_ == site_gurl; 237 } 238 239 bool CanSendCookiesForOrigin(const GURL& gurl) { 240 // We only block cross-site cookies on network requests if the 241 // --enable-strict-site-isolation flag is passed. This is expected to break 242 // compatibility with many sites. The similar --site-per-process flag only 243 // blocks JavaScript access to cross-site cookies (in 244 // CanAccessCookiesForOrigin). 245 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 246 if (!command_line.HasSwitch(switches::kEnableStrictSiteIsolation)) 247 return true; 248 249 if (origin_lock_.is_empty()) 250 return true; 251 // TODO(creis): We must pass the valid browser_context to convert hosted 252 // apps URLs. Currently, hosted apps cannot set cookies in this mode. 253 // See http://crbug.com/160576. 254 GURL site_gurl = SiteInstanceImpl::GetSiteForURL(NULL, gurl); 255 return origin_lock_ == site_gurl; 256 } 257 258 void LockToOrigin(const GURL& gurl) { 259 origin_lock_ = gurl; 260 } 261 262 bool has_web_ui_bindings() const { 263 return enabled_bindings_ & BINDINGS_POLICY_WEB_UI; 264 } 265 266 bool can_read_raw_cookies() const { 267 return can_read_raw_cookies_; 268 } 269 270 bool can_send_midi_sysex() const { 271 return can_send_midi_sysex_; 272 } 273 274 private: 275 typedef std::map<std::string, bool> SchemeMap; 276 277 typedef int FilePermissionFlags; // bit-set of PlatformFileFlags 278 typedef std::map<base::FilePath, FilePermissionFlags> FileMap; 279 typedef std::map<std::string, FilePermissionFlags> FileSystemMap; 280 typedef std::set<base::FilePath> FileSet; 281 282 // Maps URL schemes to whether permission has been granted or revoked: 283 // |true| means the scheme has been granted. 284 // |false| means the scheme has been revoked. 285 // If a scheme is not present in the map, then it has never been granted 286 // or revoked. 287 SchemeMap scheme_policy_; 288 289 // The set of files the child process is permited to upload to the web. 290 FileMap file_permissions_; 291 292 // The set of files the child process is permitted to load. 293 FileSet request_file_set_; 294 295 int enabled_bindings_; 296 297 bool can_read_raw_cookies_; 298 299 bool can_send_midi_sysex_; 300 301 GURL origin_lock_; 302 303 // The set of isolated filesystems the child process is permitted to access. 304 FileSystemMap filesystem_permissions_; 305 306 DISALLOW_COPY_AND_ASSIGN(SecurityState); 307}; 308 309ChildProcessSecurityPolicyImpl::ChildProcessSecurityPolicyImpl() { 310 // We know about these schemes and believe them to be safe. 311 RegisterWebSafeScheme(url::kHttpScheme); 312 RegisterWebSafeScheme(url::kHttpsScheme); 313 RegisterWebSafeScheme(kFtpScheme); 314 RegisterWebSafeScheme(kDataScheme); 315 RegisterWebSafeScheme("feed"); 316 RegisterWebSafeScheme(kBlobScheme); 317 RegisterWebSafeScheme(kFileSystemScheme); 318 319 // We know about the following pseudo schemes and treat them specially. 320 RegisterPseudoScheme(kAboutScheme); 321 RegisterPseudoScheme(kJavaScriptScheme); 322 RegisterPseudoScheme(kViewSourceScheme); 323} 324 325ChildProcessSecurityPolicyImpl::~ChildProcessSecurityPolicyImpl() { 326 web_safe_schemes_.clear(); 327 pseudo_schemes_.clear(); 328 STLDeleteContainerPairSecondPointers(security_state_.begin(), 329 security_state_.end()); 330 security_state_.clear(); 331} 332 333// static 334ChildProcessSecurityPolicy* ChildProcessSecurityPolicy::GetInstance() { 335 return ChildProcessSecurityPolicyImpl::GetInstance(); 336} 337 338ChildProcessSecurityPolicyImpl* ChildProcessSecurityPolicyImpl::GetInstance() { 339 return Singleton<ChildProcessSecurityPolicyImpl>::get(); 340} 341 342void ChildProcessSecurityPolicyImpl::Add(int child_id) { 343 base::AutoLock lock(lock_); 344 AddChild(child_id); 345} 346 347void ChildProcessSecurityPolicyImpl::AddWorker(int child_id, 348 int main_render_process_id) { 349 base::AutoLock lock(lock_); 350 AddChild(child_id); 351 worker_map_[child_id] = main_render_process_id; 352} 353 354void ChildProcessSecurityPolicyImpl::Remove(int child_id) { 355 base::AutoLock lock(lock_); 356 SecurityStateMap::iterator it = security_state_.find(child_id); 357 if (it == security_state_.end()) 358 return; // May be called multiple times. 359 360 delete it->second; 361 security_state_.erase(it); 362 worker_map_.erase(child_id); 363} 364 365void ChildProcessSecurityPolicyImpl::RegisterWebSafeScheme( 366 const std::string& scheme) { 367 base::AutoLock lock(lock_); 368 DCHECK_EQ(0U, web_safe_schemes_.count(scheme)) << "Add schemes at most once."; 369 DCHECK_EQ(0U, pseudo_schemes_.count(scheme)) 370 << "Web-safe implies not pseudo."; 371 372 web_safe_schemes_.insert(scheme); 373} 374 375bool ChildProcessSecurityPolicyImpl::IsWebSafeScheme( 376 const std::string& scheme) { 377 base::AutoLock lock(lock_); 378 379 return ContainsKey(web_safe_schemes_, scheme); 380} 381 382void ChildProcessSecurityPolicyImpl::RegisterPseudoScheme( 383 const std::string& scheme) { 384 base::AutoLock lock(lock_); 385 DCHECK_EQ(0U, pseudo_schemes_.count(scheme)) << "Add schemes at most once."; 386 DCHECK_EQ(0U, web_safe_schemes_.count(scheme)) 387 << "Pseudo implies not web-safe."; 388 389 pseudo_schemes_.insert(scheme); 390} 391 392bool ChildProcessSecurityPolicyImpl::IsPseudoScheme( 393 const std::string& scheme) { 394 base::AutoLock lock(lock_); 395 396 return ContainsKey(pseudo_schemes_, scheme); 397} 398 399void ChildProcessSecurityPolicyImpl::GrantRequestURL( 400 int child_id, const GURL& url) { 401 402 if (!url.is_valid()) 403 return; // Can't grant the capability to request invalid URLs. 404 405 if (IsWebSafeScheme(url.scheme())) 406 return; // The scheme has already been whitelisted for every child process. 407 408 if (IsPseudoScheme(url.scheme())) { 409 // The view-source scheme is a special case of a pseudo-URL that eventually 410 // results in requesting its embedded URL. 411 if (url.SchemeIs(kViewSourceScheme)) { 412 // URLs with the view-source scheme typically look like: 413 // view-source:http://www.google.com/a 414 // In order to request these URLs, the child_id needs to be able to 415 // request the embedded URL. 416 GrantRequestURL(child_id, GURL(url.GetContent())); 417 } 418 419 return; // Can't grant the capability to request pseudo schemes. 420 } 421 422 { 423 base::AutoLock lock(lock_); 424 SecurityStateMap::iterator state = security_state_.find(child_id); 425 if (state == security_state_.end()) 426 return; 427 428 // When the child process has been commanded to request this scheme, 429 // we grant it the capability to request all URLs of that scheme. 430 state->second->GrantScheme(url.scheme()); 431 } 432} 433 434void ChildProcessSecurityPolicyImpl::GrantRequestSpecificFileURL( 435 int child_id, 436 const GURL& url) { 437 if (!url.SchemeIs(kFileScheme)) 438 return; 439 440 { 441 base::AutoLock lock(lock_); 442 SecurityStateMap::iterator state = security_state_.find(child_id); 443 if (state == security_state_.end()) 444 return; 445 446 // When the child process has been commanded to request a file:// URL, 447 // then we grant it the capability for that URL only. 448 base::FilePath path; 449 if (net::FileURLToFilePath(url, &path)) 450 state->second->GrantRequestOfSpecificFile(path); 451 } 452} 453 454void ChildProcessSecurityPolicyImpl::GrantReadFile(int child_id, 455 const base::FilePath& file) { 456 GrantPermissionsForFile(child_id, file, READ_FILE_GRANT); 457} 458 459void ChildProcessSecurityPolicyImpl::GrantCreateReadWriteFile( 460 int child_id, const base::FilePath& file) { 461 GrantPermissionsForFile(child_id, file, CREATE_READ_WRITE_FILE_GRANT); 462} 463 464void ChildProcessSecurityPolicyImpl::GrantCopyInto(int child_id, 465 const base::FilePath& dir) { 466 GrantPermissionsForFile(child_id, dir, COPY_INTO_FILE_GRANT); 467} 468 469void ChildProcessSecurityPolicyImpl::GrantDeleteFrom( 470 int child_id, const base::FilePath& dir) { 471 GrantPermissionsForFile(child_id, dir, DELETE_FILE_GRANT); 472} 473 474void ChildProcessSecurityPolicyImpl::GrantPermissionsForFile( 475 int child_id, const base::FilePath& file, int permissions) { 476 base::AutoLock lock(lock_); 477 478 SecurityStateMap::iterator state = security_state_.find(child_id); 479 if (state == security_state_.end()) 480 return; 481 482 state->second->GrantPermissionsForFile(file, permissions); 483} 484 485void ChildProcessSecurityPolicyImpl::RevokeAllPermissionsForFile( 486 int child_id, const base::FilePath& file) { 487 base::AutoLock lock(lock_); 488 489 SecurityStateMap::iterator state = security_state_.find(child_id); 490 if (state == security_state_.end()) 491 return; 492 493 state->second->RevokeAllPermissionsForFile(file); 494} 495 496void ChildProcessSecurityPolicyImpl::GrantReadFileSystem( 497 int child_id, const std::string& filesystem_id) { 498 GrantPermissionsForFileSystem(child_id, filesystem_id, READ_FILE_GRANT); 499} 500 501void ChildProcessSecurityPolicyImpl::GrantWriteFileSystem( 502 int child_id, const std::string& filesystem_id) { 503 GrantPermissionsForFileSystem(child_id, filesystem_id, WRITE_FILE_GRANT); 504} 505 506void ChildProcessSecurityPolicyImpl::GrantCreateFileForFileSystem( 507 int child_id, const std::string& filesystem_id) { 508 GrantPermissionsForFileSystem(child_id, filesystem_id, CREATE_NEW_FILE_GRANT); 509} 510 511void ChildProcessSecurityPolicyImpl::GrantCreateReadWriteFileSystem( 512 int child_id, const std::string& filesystem_id) { 513 GrantPermissionsForFileSystem( 514 child_id, filesystem_id, CREATE_READ_WRITE_FILE_GRANT); 515} 516 517void ChildProcessSecurityPolicyImpl::GrantCopyIntoFileSystem( 518 int child_id, const std::string& filesystem_id) { 519 GrantPermissionsForFileSystem(child_id, filesystem_id, COPY_INTO_FILE_GRANT); 520} 521 522void ChildProcessSecurityPolicyImpl::GrantDeleteFromFileSystem( 523 int child_id, const std::string& filesystem_id) { 524 GrantPermissionsForFileSystem(child_id, filesystem_id, DELETE_FILE_GRANT); 525} 526 527void ChildProcessSecurityPolicyImpl::GrantSendMidiSysExMessage(int child_id) { 528 base::AutoLock lock(lock_); 529 530 SecurityStateMap::iterator state = security_state_.find(child_id); 531 if (state == security_state_.end()) 532 return; 533 534 state->second->GrantPermissionForMidiSysEx(); 535} 536 537void ChildProcessSecurityPolicyImpl::GrantScheme(int child_id, 538 const std::string& scheme) { 539 base::AutoLock lock(lock_); 540 541 SecurityStateMap::iterator state = security_state_.find(child_id); 542 if (state == security_state_.end()) 543 return; 544 545 state->second->GrantScheme(scheme); 546} 547 548void ChildProcessSecurityPolicyImpl::GrantWebUIBindings(int child_id) { 549 base::AutoLock lock(lock_); 550 551 SecurityStateMap::iterator state = security_state_.find(child_id); 552 if (state == security_state_.end()) 553 return; 554 555 state->second->GrantBindings(BINDINGS_POLICY_WEB_UI); 556 557 // Web UI bindings need the ability to request chrome: URLs. 558 state->second->GrantScheme(kChromeUIScheme); 559 560 // Web UI pages can contain links to file:// URLs. 561 state->second->GrantScheme(kFileScheme); 562} 563 564void ChildProcessSecurityPolicyImpl::GrantReadRawCookies(int child_id) { 565 base::AutoLock lock(lock_); 566 567 SecurityStateMap::iterator state = security_state_.find(child_id); 568 if (state == security_state_.end()) 569 return; 570 571 state->second->GrantReadRawCookies(); 572} 573 574void ChildProcessSecurityPolicyImpl::RevokeReadRawCookies(int child_id) { 575 base::AutoLock lock(lock_); 576 577 SecurityStateMap::iterator state = security_state_.find(child_id); 578 if (state == security_state_.end()) 579 return; 580 581 state->second->RevokeReadRawCookies(); 582} 583 584bool ChildProcessSecurityPolicyImpl::CanLoadPage( 585 int child_id, 586 const GURL& url, 587 ResourceType::Type resource_type) { 588 // If --site-per-process flag is passed, we should enforce 589 // stronger security restrictions on page navigation. 590 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess) && 591 ResourceType::IsFrame(resource_type)) { 592 // TODO(nasko): Do the proper check for site-per-process, once 593 // out-of-process iframes is ready to go. 594 return true; 595 } 596 return true; 597} 598 599bool ChildProcessSecurityPolicyImpl::CanRequestURL( 600 int child_id, const GURL& url) { 601 if (!url.is_valid()) 602 return false; // Can't request invalid URLs. 603 604 if (IsWebSafeScheme(url.scheme())) 605 return true; // The scheme has been white-listed for every child process. 606 607 if (IsPseudoScheme(url.scheme())) { 608 // There are a number of special cases for pseudo schemes. 609 610 if (url.SchemeIs(kViewSourceScheme)) { 611 // A view-source URL is allowed if the child process is permitted to 612 // request the embedded URL. Careful to avoid pointless recursion. 613 GURL child_url(url.GetContent()); 614 if (child_url.SchemeIs(kViewSourceScheme) && 615 url.SchemeIs(kViewSourceScheme)) 616 return false; 617 618 return CanRequestURL(child_id, child_url); 619 } 620 621 if (LowerCaseEqualsASCII(url.spec(), kAboutBlankURL)) 622 return true; // Every child process can request <about:blank>. 623 624 // URLs like <about:memory> and <about:crash> shouldn't be requestable by 625 // any child process. Also, this case covers <javascript:...>, which should 626 // be handled internally by the process and not kicked up to the browser. 627 return false; 628 } 629 630 if (!GetContentClient()->browser()->IsHandledURL(url) && 631 !net::URLRequest::IsHandledURL(url)) { 632 return true; // This URL request is destined for ShellExecute. 633 } 634 635 { 636 base::AutoLock lock(lock_); 637 638 SecurityStateMap::iterator state = security_state_.find(child_id); 639 if (state == security_state_.end()) 640 return false; 641 642 // Otherwise, we consult the child process's security state to see if it is 643 // allowed to request the URL. 644 return state->second->CanRequestURL(url); 645 } 646} 647 648bool ChildProcessSecurityPolicyImpl::CanReadFile(int child_id, 649 const base::FilePath& file) { 650 return HasPermissionsForFile(child_id, file, READ_FILE_GRANT); 651} 652 653bool ChildProcessSecurityPolicyImpl::CanCreateReadWriteFile( 654 int child_id, 655 const base::FilePath& file) { 656 return HasPermissionsForFile(child_id, file, CREATE_READ_WRITE_FILE_GRANT); 657} 658 659bool ChildProcessSecurityPolicyImpl::CanReadFileSystem( 660 int child_id, const std::string& filesystem_id) { 661 return HasPermissionsForFileSystem(child_id, filesystem_id, READ_FILE_GRANT); 662} 663 664bool ChildProcessSecurityPolicyImpl::CanReadWriteFileSystem( 665 int child_id, const std::string& filesystem_id) { 666 return HasPermissionsForFileSystem(child_id, filesystem_id, 667 READ_FILE_GRANT | WRITE_FILE_GRANT); 668} 669 670bool ChildProcessSecurityPolicyImpl::CanCopyIntoFileSystem( 671 int child_id, const std::string& filesystem_id) { 672 return HasPermissionsForFileSystem(child_id, filesystem_id, 673 COPY_INTO_FILE_GRANT); 674} 675 676bool ChildProcessSecurityPolicyImpl::CanDeleteFromFileSystem( 677 int child_id, const std::string& filesystem_id) { 678 return HasPermissionsForFileSystem(child_id, filesystem_id, 679 DELETE_FILE_GRANT); 680} 681 682bool ChildProcessSecurityPolicyImpl::HasPermissionsForFile( 683 int child_id, const base::FilePath& file, int permissions) { 684 base::AutoLock lock(lock_); 685 bool result = ChildProcessHasPermissionsForFile(child_id, file, permissions); 686 if (!result) { 687 // If this is a worker thread that has no access to a given file, 688 // let's check that its renderer process has access to that file instead. 689 WorkerToMainProcessMap::iterator iter = worker_map_.find(child_id); 690 if (iter != worker_map_.end() && iter->second != 0) { 691 result = ChildProcessHasPermissionsForFile(iter->second, 692 file, 693 permissions); 694 } 695 } 696 return result; 697} 698 699bool ChildProcessSecurityPolicyImpl::HasPermissionsForFileSystemFile( 700 int child_id, const fileapi::FileSystemURL& url, int permissions) { 701 if (!url.is_valid()) 702 return false; 703 704 if (url.path().ReferencesParent()) 705 return false; 706 707 // Any write access is disallowed on the root path. 708 if (fileapi::VirtualPath::IsRootPath(url.path()) && 709 (permissions & ~READ_FILE_GRANT)) { 710 return false; 711 } 712 713 if (url.mount_type() == fileapi::kFileSystemTypeIsolated) { 714 // When Isolated filesystems is overlayed on top of another filesystem, 715 // its per-filesystem permission overrides the underlying filesystem 716 // permissions). 717 return HasPermissionsForFileSystem( 718 child_id, url.mount_filesystem_id(), permissions); 719 } 720 721 FileSystemPermissionPolicyMap::iterator found = 722 file_system_policy_map_.find(url.type()); 723 if (found == file_system_policy_map_.end()) 724 return false; 725 726 if ((found->second & fileapi::FILE_PERMISSION_READ_ONLY) && 727 permissions & ~READ_FILE_GRANT) { 728 return false; 729 } 730 731 if (found->second & fileapi::FILE_PERMISSION_USE_FILE_PERMISSION) 732 return HasPermissionsForFile(child_id, url.path(), permissions); 733 734 if (found->second & fileapi::FILE_PERMISSION_SANDBOX) 735 return true; 736 737 return false; 738} 739 740bool ChildProcessSecurityPolicyImpl::CanReadFileSystemFile( 741 int child_id, 742 const fileapi::FileSystemURL& url) { 743 return HasPermissionsForFileSystemFile(child_id, url, READ_FILE_GRANT); 744} 745 746bool ChildProcessSecurityPolicyImpl::CanWriteFileSystemFile( 747 int child_id, 748 const fileapi::FileSystemURL& url) { 749 return HasPermissionsForFileSystemFile(child_id, url, WRITE_FILE_GRANT); 750} 751 752bool ChildProcessSecurityPolicyImpl::CanCreateFileSystemFile( 753 int child_id, 754 const fileapi::FileSystemURL& url) { 755 return HasPermissionsForFileSystemFile(child_id, url, CREATE_NEW_FILE_GRANT); 756} 757 758bool ChildProcessSecurityPolicyImpl::CanCreateReadWriteFileSystemFile( 759 int child_id, 760 const fileapi::FileSystemURL& url) { 761 return HasPermissionsForFileSystemFile(child_id, url, 762 CREATE_READ_WRITE_FILE_GRANT); 763} 764 765bool ChildProcessSecurityPolicyImpl::CanCopyIntoFileSystemFile( 766 int child_id, 767 const fileapi::FileSystemURL& url) { 768 return HasPermissionsForFileSystemFile(child_id, url, COPY_INTO_FILE_GRANT); 769} 770 771bool ChildProcessSecurityPolicyImpl::CanDeleteFileSystemFile( 772 int child_id, 773 const fileapi::FileSystemURL& url) { 774 return HasPermissionsForFileSystemFile(child_id, url, DELETE_FILE_GRANT); 775} 776 777bool ChildProcessSecurityPolicyImpl::HasWebUIBindings(int child_id) { 778 base::AutoLock lock(lock_); 779 780 SecurityStateMap::iterator state = security_state_.find(child_id); 781 if (state == security_state_.end()) 782 return false; 783 784 return state->second->has_web_ui_bindings(); 785} 786 787bool ChildProcessSecurityPolicyImpl::CanReadRawCookies(int child_id) { 788 base::AutoLock lock(lock_); 789 790 SecurityStateMap::iterator state = security_state_.find(child_id); 791 if (state == security_state_.end()) 792 return false; 793 794 return state->second->can_read_raw_cookies(); 795} 796 797void ChildProcessSecurityPolicyImpl::AddChild(int child_id) { 798 if (security_state_.count(child_id) != 0) { 799 NOTREACHED() << "Add child process at most once."; 800 return; 801 } 802 803 security_state_[child_id] = new SecurityState(); 804} 805 806bool ChildProcessSecurityPolicyImpl::ChildProcessHasPermissionsForFile( 807 int child_id, const base::FilePath& file, int permissions) { 808 SecurityStateMap::iterator state = security_state_.find(child_id); 809 if (state == security_state_.end()) 810 return false; 811 return state->second->HasPermissionsForFile(file, permissions); 812} 813 814bool ChildProcessSecurityPolicyImpl::CanAccessCookiesForOrigin( 815 int child_id, const GURL& gurl) { 816 base::AutoLock lock(lock_); 817 SecurityStateMap::iterator state = security_state_.find(child_id); 818 if (state == security_state_.end()) 819 return false; 820 return state->second->CanAccessCookiesForOrigin(gurl); 821} 822 823bool ChildProcessSecurityPolicyImpl::CanSendCookiesForOrigin(int child_id, 824 const GURL& gurl) { 825 for (PluginProcessHostIterator iter; !iter.Done(); ++iter) { 826 if (iter.GetData().id == child_id) { 827 if (iter.GetData().process_type == PROCESS_TYPE_PLUGIN) { 828 // NPAPI plugin processes are unsandboxed and so are trusted. Plugins 829 // can make request to any origin. 830 return true; 831 } 832 break; 833 } 834 } 835 836 base::AutoLock lock(lock_); 837 SecurityStateMap::iterator state = security_state_.find(child_id); 838 if (state == security_state_.end()) 839 return false; 840 return state->second->CanSendCookiesForOrigin(gurl); 841} 842 843void ChildProcessSecurityPolicyImpl::LockToOrigin(int child_id, 844 const GURL& gurl) { 845 // "gurl" can be currently empty in some cases, such as file://blah. 846 DCHECK(SiteInstanceImpl::GetSiteForURL(NULL, gurl) == gurl); 847 base::AutoLock lock(lock_); 848 SecurityStateMap::iterator state = security_state_.find(child_id); 849 DCHECK(state != security_state_.end()); 850 state->second->LockToOrigin(gurl); 851} 852 853void ChildProcessSecurityPolicyImpl::GrantPermissionsForFileSystem( 854 int child_id, 855 const std::string& filesystem_id, 856 int permission) { 857 base::AutoLock lock(lock_); 858 859 SecurityStateMap::iterator state = security_state_.find(child_id); 860 if (state == security_state_.end()) 861 return; 862 state->second->GrantPermissionsForFileSystem(filesystem_id, permission); 863} 864 865bool ChildProcessSecurityPolicyImpl::HasPermissionsForFileSystem( 866 int child_id, 867 const std::string& filesystem_id, 868 int permission) { 869 base::AutoLock lock(lock_); 870 871 SecurityStateMap::iterator state = security_state_.find(child_id); 872 if (state == security_state_.end()) 873 return false; 874 return state->second->HasPermissionsForFileSystem(filesystem_id, permission); 875} 876 877void ChildProcessSecurityPolicyImpl::RegisterFileSystemPermissionPolicy( 878 fileapi::FileSystemType type, 879 int policy) { 880 base::AutoLock lock(lock_); 881 file_system_policy_map_[type] = policy; 882} 883 884bool ChildProcessSecurityPolicyImpl::CanSendMidiSysExMessage(int child_id) { 885 base::AutoLock lock(lock_); 886 887 SecurityStateMap::iterator state = security_state_.find(child_id); 888 if (state == security_state_.end()) 889 return false; 890 891 return state->second->can_send_midi_sysex(); 892} 893 894} // namespace content 895