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 "url/gurl.h" 24 #include "webkit/browser/fileapi/file_permission_policy.h" 25 #include "webkit/browser/fileapi/file_system_url.h" 26 #include "webkit/browser/fileapi/isolated_context.h" 27 #include "webkit/common/fileapi/file_system_util.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 fileapi::IsolatedContext* isolated_context = 80 fileapi::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 fileapi::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 CommandLine& command_line = *CommandLine::ForCurrentProcess(); 245 if (!command_line.HasSwitch(switches::kEnableStrictSiteIsolation)) 246 return true; 247 248 if (origin_lock_.is_empty()) 249 return true; 250 // TODO(creis): We must pass the valid browser_context to convert hosted 251 // apps URLs. Currently, hosted apps cannot set cookies in this mode. 252 // See http://crbug.com/160576. 253 GURL site_gurl = SiteInstanceImpl::GetSiteForURL(NULL, gurl); 254 return origin_lock_ == site_gurl; 255 } 256 257 void LockToOrigin(const GURL& gurl) { 258 origin_lock_ = gurl; 259 } 260 261 bool has_web_ui_bindings() const { 262 return enabled_bindings_ & BINDINGS_POLICY_WEB_UI; 263 } 264 265 bool can_read_raw_cookies() const { 266 return can_read_raw_cookies_; 267 } 268 269 bool can_send_midi_sysex() const { 270 return can_send_midi_sysex_; 271 } 272 273 private: 274 typedef std::map<std::string, bool> SchemeMap; 275 276 typedef int FilePermissionFlags; // bit-set of base::File::Flags 277 typedef std::map<base::FilePath, FilePermissionFlags> FileMap; 278 typedef std::map<std::string, FilePermissionFlags> FileSystemMap; 279 typedef std::set<base::FilePath> FileSet; 280 281 // Maps URL schemes to whether permission has been granted or revoked: 282 // |true| means the scheme has been granted. 283 // |false| means the scheme has been revoked. 284 // If a scheme is not present in the map, then it has never been granted 285 // or revoked. 286 SchemeMap scheme_policy_; 287 288 // The set of files the child process is permited to upload to the web. 289 FileMap file_permissions_; 290 291 // The set of files the child process is permitted to load. 292 FileSet request_file_set_; 293 294 int enabled_bindings_; 295 296 bool can_read_raw_cookies_; 297 298 bool can_send_midi_sysex_; 299 300 GURL origin_lock_; 301 302 // The set of isolated filesystems the child process is permitted to access. 303 FileSystemMap filesystem_permissions_; 304 305 DISALLOW_COPY_AND_ASSIGN(SecurityState); 306 }; 307 308 ChildProcessSecurityPolicyImpl::ChildProcessSecurityPolicyImpl() { 309 // We know about these schemes and believe them to be safe. 310 RegisterWebSafeScheme(url::kHttpScheme); 311 RegisterWebSafeScheme(url::kHttpsScheme); 312 RegisterWebSafeScheme(url::kFtpScheme); 313 RegisterWebSafeScheme(url::kDataScheme); 314 RegisterWebSafeScheme("feed"); 315 RegisterWebSafeScheme(url::kBlobScheme); 316 RegisterWebSafeScheme(url::kFileSystemScheme); 317 318 // We know about the following pseudo schemes and treat them specially. 319 RegisterPseudoScheme(url::kAboutScheme); 320 RegisterPseudoScheme(url::kJavaScriptScheme); 321 RegisterPseudoScheme(kViewSourceScheme); 322 } 323 324 ChildProcessSecurityPolicyImpl::~ChildProcessSecurityPolicyImpl() { 325 web_safe_schemes_.clear(); 326 pseudo_schemes_.clear(); 327 STLDeleteContainerPairSecondPointers(security_state_.begin(), 328 security_state_.end()); 329 security_state_.clear(); 330 } 331 332 // static 333 ChildProcessSecurityPolicy* ChildProcessSecurityPolicy::GetInstance() { 334 return ChildProcessSecurityPolicyImpl::GetInstance(); 335 } 336 337 ChildProcessSecurityPolicyImpl* ChildProcessSecurityPolicyImpl::GetInstance() { 338 return Singleton<ChildProcessSecurityPolicyImpl>::get(); 339 } 340 341 void ChildProcessSecurityPolicyImpl::Add(int child_id) { 342 base::AutoLock lock(lock_); 343 AddChild(child_id); 344 } 345 346 void ChildProcessSecurityPolicyImpl::AddWorker(int child_id, 347 int main_render_process_id) { 348 base::AutoLock lock(lock_); 349 AddChild(child_id); 350 worker_map_[child_id] = main_render_process_id; 351 } 352 353 void ChildProcessSecurityPolicyImpl::Remove(int child_id) { 354 base::AutoLock lock(lock_); 355 SecurityStateMap::iterator it = security_state_.find(child_id); 356 if (it == security_state_.end()) 357 return; // May be called multiple times. 358 359 delete it->second; 360 security_state_.erase(it); 361 worker_map_.erase(child_id); 362 } 363 364 void ChildProcessSecurityPolicyImpl::RegisterWebSafeScheme( 365 const std::string& scheme) { 366 base::AutoLock lock(lock_); 367 DCHECK_EQ(0U, web_safe_schemes_.count(scheme)) << "Add schemes at most once."; 368 DCHECK_EQ(0U, pseudo_schemes_.count(scheme)) 369 << "Web-safe implies not pseudo."; 370 371 web_safe_schemes_.insert(scheme); 372 } 373 374 bool ChildProcessSecurityPolicyImpl::IsWebSafeScheme( 375 const std::string& scheme) { 376 base::AutoLock lock(lock_); 377 378 return ContainsKey(web_safe_schemes_, scheme); 379 } 380 381 void ChildProcessSecurityPolicyImpl::RegisterPseudoScheme( 382 const std::string& scheme) { 383 base::AutoLock lock(lock_); 384 DCHECK_EQ(0U, pseudo_schemes_.count(scheme)) << "Add schemes at most once."; 385 DCHECK_EQ(0U, web_safe_schemes_.count(scheme)) 386 << "Pseudo implies not web-safe."; 387 388 pseudo_schemes_.insert(scheme); 389 } 390 391 bool ChildProcessSecurityPolicyImpl::IsPseudoScheme( 392 const std::string& scheme) { 393 base::AutoLock lock(lock_); 394 395 return ContainsKey(pseudo_schemes_, scheme); 396 } 397 398 void ChildProcessSecurityPolicyImpl::GrantRequestURL( 399 int child_id, const GURL& url) { 400 401 if (!url.is_valid()) 402 return; // Can't grant the capability to request invalid URLs. 403 404 if (IsWebSafeScheme(url.scheme())) 405 return; // The scheme has already been whitelisted for every child process. 406 407 if (IsPseudoScheme(url.scheme())) { 408 // The view-source scheme is a special case of a pseudo-URL that eventually 409 // results in requesting its embedded URL. 410 if (url.SchemeIs(kViewSourceScheme)) { 411 // URLs with the view-source scheme typically look like: 412 // view-source:http://www.google.com/a 413 // In order to request these URLs, the child_id needs to be able to 414 // request the embedded URL. 415 GrantRequestURL(child_id, GURL(url.GetContent())); 416 } 417 418 return; // Can't grant the capability to request pseudo schemes. 419 } 420 421 { 422 base::AutoLock lock(lock_); 423 SecurityStateMap::iterator state = security_state_.find(child_id); 424 if (state == security_state_.end()) 425 return; 426 427 // When the child process has been commanded to request this scheme, 428 // we grant it the capability to request all URLs of that scheme. 429 state->second->GrantScheme(url.scheme()); 430 } 431 } 432 433 void ChildProcessSecurityPolicyImpl::GrantRequestSpecificFileURL( 434 int child_id, 435 const GURL& url) { 436 if (!url.SchemeIs(url::kFileScheme)) 437 return; 438 439 { 440 base::AutoLock lock(lock_); 441 SecurityStateMap::iterator state = security_state_.find(child_id); 442 if (state == security_state_.end()) 443 return; 444 445 // When the child process has been commanded to request a file:// URL, 446 // then we grant it the capability for that URL only. 447 base::FilePath path; 448 if (net::FileURLToFilePath(url, &path)) 449 state->second->GrantRequestOfSpecificFile(path); 450 } 451 } 452 453 void ChildProcessSecurityPolicyImpl::GrantReadFile(int child_id, 454 const base::FilePath& file) { 455 GrantPermissionsForFile(child_id, file, READ_FILE_GRANT); 456 } 457 458 void ChildProcessSecurityPolicyImpl::GrantCreateReadWriteFile( 459 int child_id, const base::FilePath& file) { 460 GrantPermissionsForFile(child_id, file, CREATE_READ_WRITE_FILE_GRANT); 461 } 462 463 void ChildProcessSecurityPolicyImpl::GrantCopyInto(int child_id, 464 const base::FilePath& dir) { 465 GrantPermissionsForFile(child_id, dir, COPY_INTO_FILE_GRANT); 466 } 467 468 void ChildProcessSecurityPolicyImpl::GrantDeleteFrom( 469 int child_id, const base::FilePath& dir) { 470 GrantPermissionsForFile(child_id, dir, DELETE_FILE_GRANT); 471 } 472 473 void ChildProcessSecurityPolicyImpl::GrantPermissionsForFile( 474 int child_id, const base::FilePath& file, int permissions) { 475 base::AutoLock lock(lock_); 476 477 SecurityStateMap::iterator state = security_state_.find(child_id); 478 if (state == security_state_.end()) 479 return; 480 481 state->second->GrantPermissionsForFile(file, permissions); 482 } 483 484 void ChildProcessSecurityPolicyImpl::RevokeAllPermissionsForFile( 485 int child_id, const base::FilePath& file) { 486 base::AutoLock lock(lock_); 487 488 SecurityStateMap::iterator state = security_state_.find(child_id); 489 if (state == security_state_.end()) 490 return; 491 492 state->second->RevokeAllPermissionsForFile(file); 493 } 494 495 void ChildProcessSecurityPolicyImpl::GrantReadFileSystem( 496 int child_id, const std::string& filesystem_id) { 497 GrantPermissionsForFileSystem(child_id, filesystem_id, READ_FILE_GRANT); 498 } 499 500 void ChildProcessSecurityPolicyImpl::GrantWriteFileSystem( 501 int child_id, const std::string& filesystem_id) { 502 GrantPermissionsForFileSystem(child_id, filesystem_id, WRITE_FILE_GRANT); 503 } 504 505 void ChildProcessSecurityPolicyImpl::GrantCreateFileForFileSystem( 506 int child_id, const std::string& filesystem_id) { 507 GrantPermissionsForFileSystem(child_id, filesystem_id, CREATE_NEW_FILE_GRANT); 508 } 509 510 void ChildProcessSecurityPolicyImpl::GrantCreateReadWriteFileSystem( 511 int child_id, const std::string& filesystem_id) { 512 GrantPermissionsForFileSystem( 513 child_id, filesystem_id, CREATE_READ_WRITE_FILE_GRANT); 514 } 515 516 void ChildProcessSecurityPolicyImpl::GrantCopyIntoFileSystem( 517 int child_id, const std::string& filesystem_id) { 518 GrantPermissionsForFileSystem(child_id, filesystem_id, COPY_INTO_FILE_GRANT); 519 } 520 521 void ChildProcessSecurityPolicyImpl::GrantDeleteFromFileSystem( 522 int child_id, const std::string& filesystem_id) { 523 GrantPermissionsForFileSystem(child_id, filesystem_id, DELETE_FILE_GRANT); 524 } 525 526 void ChildProcessSecurityPolicyImpl::GrantSendMidiSysExMessage(int child_id) { 527 base::AutoLock lock(lock_); 528 529 SecurityStateMap::iterator state = security_state_.find(child_id); 530 if (state == security_state_.end()) 531 return; 532 533 state->second->GrantPermissionForMidiSysEx(); 534 } 535 536 void ChildProcessSecurityPolicyImpl::GrantScheme(int child_id, 537 const std::string& scheme) { 538 base::AutoLock lock(lock_); 539 540 SecurityStateMap::iterator state = security_state_.find(child_id); 541 if (state == security_state_.end()) 542 return; 543 544 state->second->GrantScheme(scheme); 545 } 546 547 void ChildProcessSecurityPolicyImpl::GrantWebUIBindings(int child_id) { 548 base::AutoLock lock(lock_); 549 550 SecurityStateMap::iterator state = security_state_.find(child_id); 551 if (state == security_state_.end()) 552 return; 553 554 state->second->GrantBindings(BINDINGS_POLICY_WEB_UI); 555 556 // Web UI bindings need the ability to request chrome: URLs. 557 state->second->GrantScheme(kChromeUIScheme); 558 559 // Web UI pages can contain links to file:// URLs. 560 state->second->GrantScheme(url::kFileScheme); 561 } 562 563 void ChildProcessSecurityPolicyImpl::GrantReadRawCookies(int child_id) { 564 base::AutoLock lock(lock_); 565 566 SecurityStateMap::iterator state = security_state_.find(child_id); 567 if (state == security_state_.end()) 568 return; 569 570 state->second->GrantReadRawCookies(); 571 } 572 573 void ChildProcessSecurityPolicyImpl::RevokeReadRawCookies(int child_id) { 574 base::AutoLock lock(lock_); 575 576 SecurityStateMap::iterator state = security_state_.find(child_id); 577 if (state == security_state_.end()) 578 return; 579 580 state->second->RevokeReadRawCookies(); 581 } 582 583 bool ChildProcessSecurityPolicyImpl::CanLoadPage( 584 int child_id, 585 const GURL& url, 586 ResourceType::Type resource_type) { 587 // If --site-per-process flag is passed, we should enforce 588 // stronger security restrictions on page navigation. 589 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess) && 590 ResourceType::IsFrame(resource_type)) { 591 // TODO(nasko): Do the proper check for site-per-process, once 592 // out-of-process iframes is ready to go. 593 return true; 594 } 595 return true; 596 } 597 598 bool ChildProcessSecurityPolicyImpl::CanRequestURL( 599 int child_id, const GURL& url) { 600 if (!url.is_valid()) 601 return false; // Can't request invalid URLs. 602 603 if (IsWebSafeScheme(url.scheme())) 604 return true; // The scheme has been white-listed for every child process. 605 606 if (IsPseudoScheme(url.scheme())) { 607 // There are a number of special cases for pseudo schemes. 608 609 if (url.SchemeIs(kViewSourceScheme)) { 610 // A view-source URL is allowed if the child process is permitted to 611 // request the embedded URL. Careful to avoid pointless recursion. 612 GURL child_url(url.GetContent()); 613 if (child_url.SchemeIs(kViewSourceScheme) && 614 url.SchemeIs(kViewSourceScheme)) 615 return false; 616 617 return CanRequestURL(child_id, child_url); 618 } 619 620 if (LowerCaseEqualsASCII(url.spec(), url::kAboutBlankURL)) 621 return true; // Every child process can request <about:blank>. 622 623 // URLs like <about:memory> and <about:crash> shouldn't be requestable by 624 // any child process. Also, this case covers <javascript:...>, which should 625 // be handled internally by the process and not kicked up to the browser. 626 return false; 627 } 628 629 if (!GetContentClient()->browser()->IsHandledURL(url) && 630 !net::URLRequest::IsHandledURL(url)) { 631 return true; // This URL request is destined for ShellExecute. 632 } 633 634 { 635 base::AutoLock lock(lock_); 636 637 SecurityStateMap::iterator state = security_state_.find(child_id); 638 if (state == security_state_.end()) 639 return false; 640 641 // Otherwise, we consult the child process's security state to see if it is 642 // allowed to request the URL. 643 return state->second->CanRequestURL(url); 644 } 645 } 646 647 bool ChildProcessSecurityPolicyImpl::CanReadFile(int child_id, 648 const base::FilePath& file) { 649 return HasPermissionsForFile(child_id, file, READ_FILE_GRANT); 650 } 651 652 bool ChildProcessSecurityPolicyImpl::CanCreateReadWriteFile( 653 int child_id, 654 const base::FilePath& file) { 655 return HasPermissionsForFile(child_id, file, CREATE_READ_WRITE_FILE_GRANT); 656 } 657 658 bool ChildProcessSecurityPolicyImpl::CanReadFileSystem( 659 int child_id, const std::string& filesystem_id) { 660 return HasPermissionsForFileSystem(child_id, filesystem_id, READ_FILE_GRANT); 661 } 662 663 bool ChildProcessSecurityPolicyImpl::CanReadWriteFileSystem( 664 int child_id, const std::string& filesystem_id) { 665 return HasPermissionsForFileSystem(child_id, filesystem_id, 666 READ_FILE_GRANT | WRITE_FILE_GRANT); 667 } 668 669 bool ChildProcessSecurityPolicyImpl::CanCopyIntoFileSystem( 670 int child_id, const std::string& filesystem_id) { 671 return HasPermissionsForFileSystem(child_id, filesystem_id, 672 COPY_INTO_FILE_GRANT); 673 } 674 675 bool ChildProcessSecurityPolicyImpl::CanDeleteFromFileSystem( 676 int child_id, const std::string& filesystem_id) { 677 return HasPermissionsForFileSystem(child_id, filesystem_id, 678 DELETE_FILE_GRANT); 679 } 680 681 bool ChildProcessSecurityPolicyImpl::HasPermissionsForFile( 682 int child_id, const base::FilePath& file, int permissions) { 683 base::AutoLock lock(lock_); 684 bool result = ChildProcessHasPermissionsForFile(child_id, file, permissions); 685 if (!result) { 686 // If this is a worker thread that has no access to a given file, 687 // let's check that its renderer process has access to that file instead. 688 WorkerToMainProcessMap::iterator iter = worker_map_.find(child_id); 689 if (iter != worker_map_.end() && iter->second != 0) { 690 result = ChildProcessHasPermissionsForFile(iter->second, 691 file, 692 permissions); 693 } 694 } 695 return result; 696 } 697 698 bool ChildProcessSecurityPolicyImpl::HasPermissionsForFileSystemFile( 699 int child_id, const fileapi::FileSystemURL& url, int permissions) { 700 if (!url.is_valid()) 701 return false; 702 703 if (url.path().ReferencesParent()) 704 return false; 705 706 // Any write access is disallowed on the root path. 707 if (fileapi::VirtualPath::IsRootPath(url.path()) && 708 (permissions & ~READ_FILE_GRANT)) { 709 return false; 710 } 711 712 if (url.mount_type() == fileapi::kFileSystemTypeIsolated) { 713 // When Isolated filesystems is overlayed on top of another filesystem, 714 // its per-filesystem permission overrides the underlying filesystem 715 // permissions). 716 return HasPermissionsForFileSystem( 717 child_id, url.mount_filesystem_id(), permissions); 718 } 719 720 FileSystemPermissionPolicyMap::iterator found = 721 file_system_policy_map_.find(url.type()); 722 if (found == file_system_policy_map_.end()) 723 return false; 724 725 if ((found->second & fileapi::FILE_PERMISSION_READ_ONLY) && 726 permissions & ~READ_FILE_GRANT) { 727 return false; 728 } 729 730 if (found->second & fileapi::FILE_PERMISSION_USE_FILE_PERMISSION) 731 return HasPermissionsForFile(child_id, url.path(), permissions); 732 733 if (found->second & fileapi::FILE_PERMISSION_SANDBOX) 734 return true; 735 736 return false; 737 } 738 739 bool ChildProcessSecurityPolicyImpl::CanReadFileSystemFile( 740 int child_id, 741 const fileapi::FileSystemURL& url) { 742 return HasPermissionsForFileSystemFile(child_id, url, READ_FILE_GRANT); 743 } 744 745 bool ChildProcessSecurityPolicyImpl::CanWriteFileSystemFile( 746 int child_id, 747 const fileapi::FileSystemURL& url) { 748 return HasPermissionsForFileSystemFile(child_id, url, WRITE_FILE_GRANT); 749 } 750 751 bool ChildProcessSecurityPolicyImpl::CanCreateFileSystemFile( 752 int child_id, 753 const fileapi::FileSystemURL& url) { 754 return HasPermissionsForFileSystemFile(child_id, url, CREATE_NEW_FILE_GRANT); 755 } 756 757 bool ChildProcessSecurityPolicyImpl::CanCreateReadWriteFileSystemFile( 758 int child_id, 759 const fileapi::FileSystemURL& url) { 760 return HasPermissionsForFileSystemFile(child_id, url, 761 CREATE_READ_WRITE_FILE_GRANT); 762 } 763 764 bool ChildProcessSecurityPolicyImpl::CanCopyIntoFileSystemFile( 765 int child_id, 766 const fileapi::FileSystemURL& url) { 767 return HasPermissionsForFileSystemFile(child_id, url, COPY_INTO_FILE_GRANT); 768 } 769 770 bool ChildProcessSecurityPolicyImpl::CanDeleteFileSystemFile( 771 int child_id, 772 const fileapi::FileSystemURL& url) { 773 return HasPermissionsForFileSystemFile(child_id, url, DELETE_FILE_GRANT); 774 } 775 776 bool ChildProcessSecurityPolicyImpl::HasWebUIBindings(int child_id) { 777 base::AutoLock lock(lock_); 778 779 SecurityStateMap::iterator state = security_state_.find(child_id); 780 if (state == security_state_.end()) 781 return false; 782 783 return state->second->has_web_ui_bindings(); 784 } 785 786 bool ChildProcessSecurityPolicyImpl::CanReadRawCookies(int child_id) { 787 base::AutoLock lock(lock_); 788 789 SecurityStateMap::iterator state = security_state_.find(child_id); 790 if (state == security_state_.end()) 791 return false; 792 793 return state->second->can_read_raw_cookies(); 794 } 795 796 void ChildProcessSecurityPolicyImpl::AddChild(int child_id) { 797 if (security_state_.count(child_id) != 0) { 798 NOTREACHED() << "Add child process at most once."; 799 return; 800 } 801 802 security_state_[child_id] = new SecurityState(); 803 } 804 805 bool ChildProcessSecurityPolicyImpl::ChildProcessHasPermissionsForFile( 806 int child_id, const base::FilePath& file, int permissions) { 807 SecurityStateMap::iterator state = security_state_.find(child_id); 808 if (state == security_state_.end()) 809 return false; 810 return state->second->HasPermissionsForFile(file, permissions); 811 } 812 813 bool ChildProcessSecurityPolicyImpl::CanAccessCookiesForOrigin( 814 int child_id, const GURL& gurl) { 815 base::AutoLock lock(lock_); 816 SecurityStateMap::iterator state = security_state_.find(child_id); 817 if (state == security_state_.end()) 818 return false; 819 return state->second->CanAccessCookiesForOrigin(gurl); 820 } 821 822 bool ChildProcessSecurityPolicyImpl::CanSendCookiesForOrigin(int child_id, 823 const GURL& gurl) { 824 for (PluginProcessHostIterator iter; !iter.Done(); ++iter) { 825 if (iter.GetData().id == child_id) { 826 if (iter.GetData().process_type == PROCESS_TYPE_PLUGIN) { 827 // NPAPI plugin processes are unsandboxed and so are trusted. Plugins 828 // can make request to any origin. 829 return true; 830 } 831 break; 832 } 833 } 834 835 base::AutoLock lock(lock_); 836 SecurityStateMap::iterator state = security_state_.find(child_id); 837 if (state == security_state_.end()) 838 return false; 839 return state->second->CanSendCookiesForOrigin(gurl); 840 } 841 842 void ChildProcessSecurityPolicyImpl::LockToOrigin(int child_id, 843 const GURL& gurl) { 844 // "gurl" can be currently empty in some cases, such as file://blah. 845 DCHECK(SiteInstanceImpl::GetSiteForURL(NULL, gurl) == gurl); 846 base::AutoLock lock(lock_); 847 SecurityStateMap::iterator state = security_state_.find(child_id); 848 DCHECK(state != security_state_.end()); 849 state->second->LockToOrigin(gurl); 850 } 851 852 void ChildProcessSecurityPolicyImpl::GrantPermissionsForFileSystem( 853 int child_id, 854 const std::string& filesystem_id, 855 int permission) { 856 base::AutoLock lock(lock_); 857 858 SecurityStateMap::iterator state = security_state_.find(child_id); 859 if (state == security_state_.end()) 860 return; 861 state->second->GrantPermissionsForFileSystem(filesystem_id, permission); 862 } 863 864 bool ChildProcessSecurityPolicyImpl::HasPermissionsForFileSystem( 865 int child_id, 866 const std::string& filesystem_id, 867 int permission) { 868 base::AutoLock lock(lock_); 869 870 SecurityStateMap::iterator state = security_state_.find(child_id); 871 if (state == security_state_.end()) 872 return false; 873 return state->second->HasPermissionsForFileSystem(filesystem_id, permission); 874 } 875 876 void ChildProcessSecurityPolicyImpl::RegisterFileSystemPermissionPolicy( 877 fileapi::FileSystemType type, 878 int policy) { 879 base::AutoLock lock(lock_); 880 file_system_policy_map_[type] = policy; 881 } 882 883 bool ChildProcessSecurityPolicyImpl::CanSendMidiSysExMessage(int child_id) { 884 base::AutoLock lock(lock_); 885 886 SecurityStateMap::iterator state = security_state_.find(child_id); 887 if (state == security_state_.end()) 888 return false; 889 890 return state->second->can_send_midi_sysex(); 891 } 892 893 } // namespace content 894