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/stl_util.h" 12 #include "base/strings/string_util.h" 13 #include "content/browser/plugin_process_host.h" 14 #include "content/browser/site_instance_impl.h" 15 #include "content/public/browser/child_process_data.h" 16 #include "content/public/browser/content_browser_client.h" 17 #include "content/public/browser/render_process_host.h" 18 #include "content/public/common/bindings_policy.h" 19 #include "content/public/common/content_switches.h" 20 #include "content/public/common/url_constants.h" 21 #include "net/base/filename_util.h" 22 #include "net/url_request/url_request.h" 23 #include "storage/browser/fileapi/file_permission_policy.h" 24 #include "storage/browser/fileapi/file_system_url.h" 25 #include "storage/browser/fileapi/isolated_context.h" 26 #include "storage/common/fileapi/file_system_util.h" 27 #include "url/gurl.h" 28 29 namespace content { 30 31 namespace { 32 33 // Used internally only. These bit positions have no relationship to any 34 // underlying OS and can be changed to accommodate finer-grained permissions. 35 enum ChildProcessSecurityPermissions { 36 READ_FILE_PERMISSION = 1 << 0, 37 WRITE_FILE_PERMISSION = 1 << 1, 38 CREATE_NEW_FILE_PERMISSION = 1 << 2, 39 CREATE_OVERWRITE_FILE_PERMISSION = 1 << 3, 40 DELETE_FILE_PERMISSION = 1 << 4, 41 42 // Used by Media Galleries API 43 COPY_INTO_FILE_PERMISSION = 1 << 5, 44 }; 45 46 // Used internally only. Bitmasks that are actually used by the Grant* and Can* 47 // methods. These contain one or more ChildProcessSecurityPermissions. 48 enum ChildProcessSecurityGrants { 49 READ_FILE_GRANT = READ_FILE_PERMISSION, 50 WRITE_FILE_GRANT = WRITE_FILE_PERMISSION, 51 52 CREATE_NEW_FILE_GRANT = CREATE_NEW_FILE_PERMISSION | 53 COPY_INTO_FILE_PERMISSION, 54 55 CREATE_READ_WRITE_FILE_GRANT = CREATE_NEW_FILE_PERMISSION | 56 CREATE_OVERWRITE_FILE_PERMISSION | 57 READ_FILE_PERMISSION | 58 WRITE_FILE_PERMISSION | 59 COPY_INTO_FILE_PERMISSION | 60 DELETE_FILE_PERMISSION, 61 62 COPY_INTO_FILE_GRANT = COPY_INTO_FILE_PERMISSION, 63 DELETE_FILE_GRANT = DELETE_FILE_PERMISSION, 64 }; 65 66 } // namespace 67 68 // The SecurityState class is used to maintain per-child process security state 69 // information. 70 class ChildProcessSecurityPolicyImpl::SecurityState { 71 public: 72 SecurityState() 73 : enabled_bindings_(0), 74 can_read_raw_cookies_(false), 75 can_send_midi_sysex_(false) { } 76 77 ~SecurityState() { 78 scheme_policy_.clear(); 79 storage::IsolatedContext* isolated_context = 80 storage::IsolatedContext::GetInstance(); 81 for (FileSystemMap::iterator iter = filesystem_permissions_.begin(); 82 iter != filesystem_permissions_.end(); 83 ++iter) { 84 isolated_context->RemoveReference(iter->first); 85 } 86 UMA_HISTOGRAM_COUNTS("ChildProcessSecurityPolicy.PerChildFilePermissions", 87 file_permissions_.size()); 88 } 89 90 // Grant permission to request URLs with the specified scheme. 91 void GrantScheme(const std::string& scheme) { 92 scheme_policy_[scheme] = true; 93 } 94 95 // Revoke permission to request URLs with the specified scheme. 96 void RevokeScheme(const std::string& scheme) { 97 scheme_policy_[scheme] = false; 98 } 99 100 // Grant certain permissions to a file. 101 void GrantPermissionsForFile(const base::FilePath& file, int permissions) { 102 base::FilePath stripped = file.StripTrailingSeparators(); 103 file_permissions_[stripped] |= permissions; 104 UMA_HISTOGRAM_COUNTS("ChildProcessSecurityPolicy.FilePermissionPathLength", 105 stripped.value().size()); 106 } 107 108 // Grant navigation to a file but not the file:// scheme in general. 109 void GrantRequestOfSpecificFile(const base::FilePath &file) { 110 request_file_set_.insert(file.StripTrailingSeparators()); 111 } 112 113 // Revokes all permissions granted to a file. 114 void RevokeAllPermissionsForFile(const base::FilePath& file) { 115 base::FilePath stripped = file.StripTrailingSeparators(); 116 file_permissions_.erase(stripped); 117 request_file_set_.erase(stripped); 118 } 119 120 // Grant certain permissions to a file. 121 void GrantPermissionsForFileSystem(const std::string& filesystem_id, 122 int permissions) { 123 if (!ContainsKey(filesystem_permissions_, filesystem_id)) 124 storage::IsolatedContext::GetInstance()->AddReference(filesystem_id); 125 filesystem_permissions_[filesystem_id] |= permissions; 126 } 127 128 bool HasPermissionsForFileSystem(const std::string& filesystem_id, 129 int permissions) { 130 FileSystemMap::const_iterator it = 131 filesystem_permissions_.find(filesystem_id); 132 if (it == filesystem_permissions_.end()) 133 return false; 134 return (it->second & permissions) == permissions; 135 } 136 137 #if defined(OS_ANDROID) 138 // Determine if the certain permissions have been granted to a content URI. 139 bool HasPermissionsForContentUri(const base::FilePath& file, 140 int permissions) { 141 DCHECK(!file.empty()); 142 DCHECK(file.IsContentUri()); 143 if (!permissions) 144 return false; 145 base::FilePath file_path = file.StripTrailingSeparators(); 146 FileMap::const_iterator it = file_permissions_.find(file_path); 147 if (it != file_permissions_.end()) 148 return (it->second & permissions) == permissions; 149 return false; 150 } 151 #endif 152 153 void GrantBindings(int bindings) { 154 enabled_bindings_ |= bindings; 155 } 156 157 void GrantReadRawCookies() { 158 can_read_raw_cookies_ = true; 159 } 160 161 void RevokeReadRawCookies() { 162 can_read_raw_cookies_ = false; 163 } 164 165 void GrantPermissionForMidiSysEx() { 166 can_send_midi_sysex_ = true; 167 } 168 169 // Determine whether permission has been granted to request |url|. 170 bool CanRequestURL(const GURL& url) { 171 // Having permission to a scheme implies permssion to all of its URLs. 172 SchemeMap::const_iterator judgment(scheme_policy_.find(url.scheme())); 173 if (judgment != scheme_policy_.end()) 174 return judgment->second; 175 176 // file:// URLs are more granular. The child may have been given 177 // permission to a specific file but not the file:// scheme in general. 178 if (url.SchemeIs(url::kFileScheme)) { 179 base::FilePath path; 180 if (net::FileURLToFilePath(url, &path)) 181 return ContainsKey(request_file_set_, path); 182 } 183 184 return false; // Unmentioned schemes are disallowed. 185 } 186 187 // Determine if the certain permissions have been granted to a file. 188 bool HasPermissionsForFile(const base::FilePath& file, int permissions) { 189 #if defined(OS_ANDROID) 190 if (file.IsContentUri()) 191 return HasPermissionsForContentUri(file, permissions); 192 #endif 193 if (!permissions || file.empty() || !file.IsAbsolute()) 194 return false; 195 base::FilePath current_path = file.StripTrailingSeparators(); 196 base::FilePath last_path; 197 int skip = 0; 198 while (current_path != last_path) { 199 base::FilePath base_name = current_path.BaseName(); 200 if (base_name.value() == base::FilePath::kParentDirectory) { 201 ++skip; 202 } else if (skip > 0) { 203 if (base_name.value() != base::FilePath::kCurrentDirectory) 204 --skip; 205 } else { 206 FileMap::const_iterator it = file_permissions_.find(current_path); 207 if (it != file_permissions_.end()) 208 return (it->second & permissions) == permissions; 209 } 210 last_path = current_path; 211 current_path = current_path.DirName(); 212 } 213 214 return false; 215 } 216 217 bool CanLoadPage(const GURL& gurl) { 218 if (origin_lock_.is_empty()) 219 return true; 220 221 // TODO(creis): We must pass the valid browser_context to convert hosted 222 // apps URLs. Currently, hosted apps cannot be loaded in this mode. 223 // See http://crbug.com/160576. 224 GURL site_gurl = SiteInstanceImpl::GetSiteForURL(NULL, gurl); 225 return origin_lock_ == site_gurl; 226 } 227 228 bool CanAccessCookiesForOrigin(const GURL& gurl) { 229 if (origin_lock_.is_empty()) 230 return true; 231 // TODO(creis): We must pass the valid browser_context to convert hosted 232 // apps URLs. Currently, hosted apps cannot set cookies in this mode. 233 // See http://crbug.com/160576. 234 GURL site_gurl = SiteInstanceImpl::GetSiteForURL(NULL, gurl); 235 return origin_lock_ == site_gurl; 236 } 237 238 bool CanSendCookiesForOrigin(const GURL& gurl) { 239 // We only block cross-site cookies on network requests if the 240 // --enable-strict-site-isolation flag is passed. This is expected to break 241 // compatibility with many sites. The similar --site-per-process flag only 242 // blocks JavaScript access to cross-site cookies (in 243 // CanAccessCookiesForOrigin). 244 const base::CommandLine& command_line = 245 *base::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 base::File::Flags 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 309 ChildProcessSecurityPolicyImpl::ChildProcessSecurityPolicyImpl() { 310 // We know about these schemes and believe them to be safe. 311 RegisterWebSafeScheme(url::kHttpScheme); 312 RegisterWebSafeScheme(url::kHttpsScheme); 313 RegisterWebSafeScheme(url::kFtpScheme); 314 RegisterWebSafeScheme(url::kDataScheme); 315 RegisterWebSafeScheme("feed"); 316 RegisterWebSafeScheme(url::kBlobScheme); 317 RegisterWebSafeScheme(url::kFileSystemScheme); 318 319 // We know about the following pseudo schemes and treat them specially. 320 RegisterPseudoScheme(url::kAboutScheme); 321 RegisterPseudoScheme(url::kJavaScriptScheme); 322 RegisterPseudoScheme(kViewSourceScheme); 323 } 324 325 ChildProcessSecurityPolicyImpl::~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 334 ChildProcessSecurityPolicy* ChildProcessSecurityPolicy::GetInstance() { 335 return ChildProcessSecurityPolicyImpl::GetInstance(); 336 } 337 338 ChildProcessSecurityPolicyImpl* ChildProcessSecurityPolicyImpl::GetInstance() { 339 return Singleton<ChildProcessSecurityPolicyImpl>::get(); 340 } 341 342 void ChildProcessSecurityPolicyImpl::Add(int child_id) { 343 base::AutoLock lock(lock_); 344 AddChild(child_id); 345 } 346 347 void 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 354 void 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 365 void 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 375 bool ChildProcessSecurityPolicyImpl::IsWebSafeScheme( 376 const std::string& scheme) { 377 base::AutoLock lock(lock_); 378 379 return ContainsKey(web_safe_schemes_, scheme); 380 } 381 382 void 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 392 bool ChildProcessSecurityPolicyImpl::IsPseudoScheme( 393 const std::string& scheme) { 394 base::AutoLock lock(lock_); 395 396 return ContainsKey(pseudo_schemes_, scheme); 397 } 398 399 void 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 434 void ChildProcessSecurityPolicyImpl::GrantRequestSpecificFileURL( 435 int child_id, 436 const GURL& url) { 437 if (!url.SchemeIs(url::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 454 void ChildProcessSecurityPolicyImpl::GrantReadFile(int child_id, 455 const base::FilePath& file) { 456 GrantPermissionsForFile(child_id, file, READ_FILE_GRANT); 457 } 458 459 void ChildProcessSecurityPolicyImpl::GrantCreateReadWriteFile( 460 int child_id, const base::FilePath& file) { 461 GrantPermissionsForFile(child_id, file, CREATE_READ_WRITE_FILE_GRANT); 462 } 463 464 void ChildProcessSecurityPolicyImpl::GrantCopyInto(int child_id, 465 const base::FilePath& dir) { 466 GrantPermissionsForFile(child_id, dir, COPY_INTO_FILE_GRANT); 467 } 468 469 void ChildProcessSecurityPolicyImpl::GrantDeleteFrom( 470 int child_id, const base::FilePath& dir) { 471 GrantPermissionsForFile(child_id, dir, DELETE_FILE_GRANT); 472 } 473 474 void 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 485 void 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 496 void ChildProcessSecurityPolicyImpl::GrantReadFileSystem( 497 int child_id, const std::string& filesystem_id) { 498 GrantPermissionsForFileSystem(child_id, filesystem_id, READ_FILE_GRANT); 499 } 500 501 void ChildProcessSecurityPolicyImpl::GrantWriteFileSystem( 502 int child_id, const std::string& filesystem_id) { 503 GrantPermissionsForFileSystem(child_id, filesystem_id, WRITE_FILE_GRANT); 504 } 505 506 void ChildProcessSecurityPolicyImpl::GrantCreateFileForFileSystem( 507 int child_id, const std::string& filesystem_id) { 508 GrantPermissionsForFileSystem(child_id, filesystem_id, CREATE_NEW_FILE_GRANT); 509 } 510 511 void 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 517 void ChildProcessSecurityPolicyImpl::GrantCopyIntoFileSystem( 518 int child_id, const std::string& filesystem_id) { 519 GrantPermissionsForFileSystem(child_id, filesystem_id, COPY_INTO_FILE_GRANT); 520 } 521 522 void ChildProcessSecurityPolicyImpl::GrantDeleteFromFileSystem( 523 int child_id, const std::string& filesystem_id) { 524 GrantPermissionsForFileSystem(child_id, filesystem_id, DELETE_FILE_GRANT); 525 } 526 527 void 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 537 void 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 548 void 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(url::kFileScheme); 562 } 563 564 void 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 574 void 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 584 bool ChildProcessSecurityPolicyImpl::CanLoadPage(int child_id, 585 const GURL& url, 586 ResourceType resource_type) { 587 // If --site-per-process flag is passed, we should enforce 588 // stronger security restrictions on page navigation. 589 if (base::CommandLine::ForCurrentProcess()->HasSwitch( 590 switches::kSitePerProcess) && 591 IsResourceTypeFrame(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 599 bool 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(), url::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 648 bool ChildProcessSecurityPolicyImpl::CanReadFile(int child_id, 649 const base::FilePath& file) { 650 return HasPermissionsForFile(child_id, file, READ_FILE_GRANT); 651 } 652 653 bool ChildProcessSecurityPolicyImpl::CanCreateReadWriteFile( 654 int child_id, 655 const base::FilePath& file) { 656 return HasPermissionsForFile(child_id, file, CREATE_READ_WRITE_FILE_GRANT); 657 } 658 659 bool ChildProcessSecurityPolicyImpl::CanReadFileSystem( 660 int child_id, const std::string& filesystem_id) { 661 return HasPermissionsForFileSystem(child_id, filesystem_id, READ_FILE_GRANT); 662 } 663 664 bool 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 670 bool 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 676 bool ChildProcessSecurityPolicyImpl::CanDeleteFromFileSystem( 677 int child_id, const std::string& filesystem_id) { 678 return HasPermissionsForFileSystem(child_id, filesystem_id, 679 DELETE_FILE_GRANT); 680 } 681 682 bool 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 699 bool ChildProcessSecurityPolicyImpl::HasPermissionsForFileSystemFile( 700 int child_id, 701 const storage::FileSystemURL& url, 702 int permissions) { 703 if (!url.is_valid()) 704 return false; 705 706 if (url.path().ReferencesParent()) 707 return false; 708 709 // Any write access is disallowed on the root path. 710 if (storage::VirtualPath::IsRootPath(url.path()) && 711 (permissions & ~READ_FILE_GRANT)) { 712 return false; 713 } 714 715 if (url.mount_type() == storage::kFileSystemTypeIsolated) { 716 // When Isolated filesystems is overlayed on top of another filesystem, 717 // its per-filesystem permission overrides the underlying filesystem 718 // permissions). 719 return HasPermissionsForFileSystem( 720 child_id, url.mount_filesystem_id(), permissions); 721 } 722 723 FileSystemPermissionPolicyMap::iterator found = 724 file_system_policy_map_.find(url.type()); 725 if (found == file_system_policy_map_.end()) 726 return false; 727 728 if ((found->second & storage::FILE_PERMISSION_READ_ONLY) && 729 permissions & ~READ_FILE_GRANT) { 730 return false; 731 } 732 733 if (found->second & storage::FILE_PERMISSION_USE_FILE_PERMISSION) 734 return HasPermissionsForFile(child_id, url.path(), permissions); 735 736 if (found->second & storage::FILE_PERMISSION_SANDBOX) 737 return true; 738 739 return false; 740 } 741 742 bool ChildProcessSecurityPolicyImpl::CanReadFileSystemFile( 743 int child_id, 744 const storage::FileSystemURL& url) { 745 return HasPermissionsForFileSystemFile(child_id, url, READ_FILE_GRANT); 746 } 747 748 bool ChildProcessSecurityPolicyImpl::CanWriteFileSystemFile( 749 int child_id, 750 const storage::FileSystemURL& url) { 751 return HasPermissionsForFileSystemFile(child_id, url, WRITE_FILE_GRANT); 752 } 753 754 bool ChildProcessSecurityPolicyImpl::CanCreateFileSystemFile( 755 int child_id, 756 const storage::FileSystemURL& url) { 757 return HasPermissionsForFileSystemFile(child_id, url, CREATE_NEW_FILE_GRANT); 758 } 759 760 bool ChildProcessSecurityPolicyImpl::CanCreateReadWriteFileSystemFile( 761 int child_id, 762 const storage::FileSystemURL& url) { 763 return HasPermissionsForFileSystemFile(child_id, url, 764 CREATE_READ_WRITE_FILE_GRANT); 765 } 766 767 bool ChildProcessSecurityPolicyImpl::CanCopyIntoFileSystemFile( 768 int child_id, 769 const storage::FileSystemURL& url) { 770 return HasPermissionsForFileSystemFile(child_id, url, COPY_INTO_FILE_GRANT); 771 } 772 773 bool ChildProcessSecurityPolicyImpl::CanDeleteFileSystemFile( 774 int child_id, 775 const storage::FileSystemURL& url) { 776 return HasPermissionsForFileSystemFile(child_id, url, DELETE_FILE_GRANT); 777 } 778 779 bool ChildProcessSecurityPolicyImpl::HasWebUIBindings(int child_id) { 780 base::AutoLock lock(lock_); 781 782 SecurityStateMap::iterator state = security_state_.find(child_id); 783 if (state == security_state_.end()) 784 return false; 785 786 return state->second->has_web_ui_bindings(); 787 } 788 789 bool ChildProcessSecurityPolicyImpl::CanReadRawCookies(int child_id) { 790 base::AutoLock lock(lock_); 791 792 SecurityStateMap::iterator state = security_state_.find(child_id); 793 if (state == security_state_.end()) 794 return false; 795 796 return state->second->can_read_raw_cookies(); 797 } 798 799 void ChildProcessSecurityPolicyImpl::AddChild(int child_id) { 800 if (security_state_.count(child_id) != 0) { 801 NOTREACHED() << "Add child process at most once."; 802 return; 803 } 804 805 security_state_[child_id] = new SecurityState(); 806 } 807 808 bool ChildProcessSecurityPolicyImpl::ChildProcessHasPermissionsForFile( 809 int child_id, const base::FilePath& file, int permissions) { 810 SecurityStateMap::iterator state = security_state_.find(child_id); 811 if (state == security_state_.end()) 812 return false; 813 return state->second->HasPermissionsForFile(file, permissions); 814 } 815 816 bool ChildProcessSecurityPolicyImpl::CanAccessCookiesForOrigin( 817 int child_id, const GURL& gurl) { 818 base::AutoLock lock(lock_); 819 SecurityStateMap::iterator state = security_state_.find(child_id); 820 if (state == security_state_.end()) 821 return false; 822 return state->second->CanAccessCookiesForOrigin(gurl); 823 } 824 825 bool ChildProcessSecurityPolicyImpl::CanSendCookiesForOrigin(int child_id, 826 const GURL& gurl) { 827 for (PluginProcessHostIterator iter; !iter.Done(); ++iter) { 828 if (iter.GetData().id == child_id) { 829 if (iter.GetData().process_type == PROCESS_TYPE_PLUGIN) { 830 // NPAPI plugin processes are unsandboxed and so are trusted. Plugins 831 // can make request to any origin. 832 return true; 833 } 834 break; 835 } 836 } 837 838 base::AutoLock lock(lock_); 839 SecurityStateMap::iterator state = security_state_.find(child_id); 840 if (state == security_state_.end()) 841 return false; 842 return state->second->CanSendCookiesForOrigin(gurl); 843 } 844 845 void ChildProcessSecurityPolicyImpl::LockToOrigin(int child_id, 846 const GURL& gurl) { 847 // "gurl" can be currently empty in some cases, such as file://blah. 848 DCHECK(SiteInstanceImpl::GetSiteForURL(NULL, gurl) == gurl); 849 base::AutoLock lock(lock_); 850 SecurityStateMap::iterator state = security_state_.find(child_id); 851 DCHECK(state != security_state_.end()); 852 state->second->LockToOrigin(gurl); 853 } 854 855 void ChildProcessSecurityPolicyImpl::GrantPermissionsForFileSystem( 856 int child_id, 857 const std::string& filesystem_id, 858 int permission) { 859 base::AutoLock lock(lock_); 860 861 SecurityStateMap::iterator state = security_state_.find(child_id); 862 if (state == security_state_.end()) 863 return; 864 state->second->GrantPermissionsForFileSystem(filesystem_id, permission); 865 } 866 867 bool ChildProcessSecurityPolicyImpl::HasPermissionsForFileSystem( 868 int child_id, 869 const std::string& filesystem_id, 870 int permission) { 871 base::AutoLock lock(lock_); 872 873 SecurityStateMap::iterator state = security_state_.find(child_id); 874 if (state == security_state_.end()) 875 return false; 876 return state->second->HasPermissionsForFileSystem(filesystem_id, permission); 877 } 878 879 void ChildProcessSecurityPolicyImpl::RegisterFileSystemPermissionPolicy( 880 storage::FileSystemType type, 881 int policy) { 882 base::AutoLock lock(lock_); 883 file_system_policy_map_[type] = policy; 884 } 885 886 bool ChildProcessSecurityPolicyImpl::CanSendMidiSysExMessage(int child_id) { 887 base::AutoLock lock(lock_); 888 889 SecurityStateMap::iterator state = security_state_.find(child_id); 890 if (state == security_state_.end()) 891 return false; 892 893 return state->second->can_send_midi_sysex(); 894 } 895 896 } // namespace content 897