| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/child_process_security_policy.h" | 5 #include "chrome/browser/child_process_security_policy.h" |
| 6 | 6 |
| 7 #include "base/file_path.h" | 7 #include "base/file_path.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/platform_file.h" | 9 #include "base/platform_file.h" |
| 10 #include "base/stl_util-inl.h" | 10 #include "base/stl_util-inl.h" |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 144 security_state_.end()); | 144 security_state_.end()); |
| 145 security_state_.clear(); | 145 security_state_.clear(); |
| 146 } | 146 } |
| 147 | 147 |
| 148 // static | 148 // static |
| 149 ChildProcessSecurityPolicy* ChildProcessSecurityPolicy::GetInstance() { | 149 ChildProcessSecurityPolicy* ChildProcessSecurityPolicy::GetInstance() { |
| 150 return Singleton<ChildProcessSecurityPolicy>::get(); | 150 return Singleton<ChildProcessSecurityPolicy>::get(); |
| 151 } | 151 } |
| 152 | 152 |
| 153 void ChildProcessSecurityPolicy::Add(int child_id) { | 153 void ChildProcessSecurityPolicy::Add(int child_id) { |
| 154 AutoLock lock(lock_); | 154 base::AutoLock lock(lock_); |
| 155 if (security_state_.count(child_id) != 0) { | 155 if (security_state_.count(child_id) != 0) { |
| 156 NOTREACHED() << "Add child process at most once."; | 156 NOTREACHED() << "Add child process at most once."; |
| 157 return; | 157 return; |
| 158 } | 158 } |
| 159 | 159 |
| 160 security_state_[child_id] = new SecurityState(); | 160 security_state_[child_id] = new SecurityState(); |
| 161 } | 161 } |
| 162 | 162 |
| 163 void ChildProcessSecurityPolicy::Remove(int child_id) { | 163 void ChildProcessSecurityPolicy::Remove(int child_id) { |
| 164 AutoLock lock(lock_); | 164 base::AutoLock lock(lock_); |
| 165 if (!security_state_.count(child_id)) | 165 if (!security_state_.count(child_id)) |
| 166 return; // May be called multiple times. | 166 return; // May be called multiple times. |
| 167 | 167 |
| 168 delete security_state_[child_id]; | 168 delete security_state_[child_id]; |
| 169 security_state_.erase(child_id); | 169 security_state_.erase(child_id); |
| 170 } | 170 } |
| 171 | 171 |
| 172 void ChildProcessSecurityPolicy::RegisterWebSafeScheme( | 172 void ChildProcessSecurityPolicy::RegisterWebSafeScheme( |
| 173 const std::string& scheme) { | 173 const std::string& scheme) { |
| 174 AutoLock lock(lock_); | 174 base::AutoLock lock(lock_); |
| 175 DCHECK(web_safe_schemes_.count(scheme) == 0) << "Add schemes at most once."; | 175 DCHECK(web_safe_schemes_.count(scheme) == 0) << "Add schemes at most once."; |
| 176 DCHECK(pseudo_schemes_.count(scheme) == 0) << "Web-safe implies not psuedo."; | 176 DCHECK(pseudo_schemes_.count(scheme) == 0) << "Web-safe implies not psuedo."; |
| 177 | 177 |
| 178 web_safe_schemes_.insert(scheme); | 178 web_safe_schemes_.insert(scheme); |
| 179 } | 179 } |
| 180 | 180 |
| 181 bool ChildProcessSecurityPolicy::IsWebSafeScheme(const std::string& scheme) { | 181 bool ChildProcessSecurityPolicy::IsWebSafeScheme(const std::string& scheme) { |
| 182 AutoLock lock(lock_); | 182 base::AutoLock lock(lock_); |
| 183 | 183 |
| 184 return (web_safe_schemes_.find(scheme) != web_safe_schemes_.end()); | 184 return (web_safe_schemes_.find(scheme) != web_safe_schemes_.end()); |
| 185 } | 185 } |
| 186 | 186 |
| 187 void ChildProcessSecurityPolicy::RegisterPseudoScheme( | 187 void ChildProcessSecurityPolicy::RegisterPseudoScheme( |
| 188 const std::string& scheme) { | 188 const std::string& scheme) { |
| 189 AutoLock lock(lock_); | 189 base::AutoLock lock(lock_); |
| 190 DCHECK(pseudo_schemes_.count(scheme) == 0) << "Add schemes at most once."; | 190 DCHECK(pseudo_schemes_.count(scheme) == 0) << "Add schemes at most once."; |
| 191 DCHECK(web_safe_schemes_.count(scheme) == 0) << | 191 DCHECK(web_safe_schemes_.count(scheme) == 0) << |
| 192 "Psuedo implies not web-safe."; | 192 "Psuedo implies not web-safe."; |
| 193 | 193 |
| 194 pseudo_schemes_.insert(scheme); | 194 pseudo_schemes_.insert(scheme); |
| 195 } | 195 } |
| 196 | 196 |
| 197 bool ChildProcessSecurityPolicy::IsPseudoScheme(const std::string& scheme) { | 197 bool ChildProcessSecurityPolicy::IsPseudoScheme(const std::string& scheme) { |
| 198 AutoLock lock(lock_); | 198 base::AutoLock lock(lock_); |
| 199 | 199 |
| 200 return (pseudo_schemes_.find(scheme) != pseudo_schemes_.end()); | 200 return (pseudo_schemes_.find(scheme) != pseudo_schemes_.end()); |
| 201 } | 201 } |
| 202 | 202 |
| 203 void ChildProcessSecurityPolicy::GrantRequestURL( | 203 void ChildProcessSecurityPolicy::GrantRequestURL( |
| 204 int child_id, const GURL& url) { | 204 int child_id, const GURL& url) { |
| 205 | 205 |
| 206 if (!url.is_valid()) | 206 if (!url.is_valid()) |
| 207 return; // Can't grant the capability to request invalid URLs. | 207 return; // Can't grant the capability to request invalid URLs. |
| 208 | 208 |
| 209 if (IsWebSafeScheme(url.scheme())) | 209 if (IsWebSafeScheme(url.scheme())) |
| 210 return; // The scheme has already been whitelisted for every child process. | 210 return; // The scheme has already been whitelisted for every child process. |
| 211 | 211 |
| 212 if (IsPseudoScheme(url.scheme())) { | 212 if (IsPseudoScheme(url.scheme())) { |
| 213 // The view-source scheme is a special case of a pseudo-URL that eventually | 213 // The view-source scheme is a special case of a pseudo-URL that eventually |
| 214 // results in requesting its embedded URL. | 214 // results in requesting its embedded URL. |
| 215 if (url.SchemeIs(chrome::kViewSourceScheme)) { | 215 if (url.SchemeIs(chrome::kViewSourceScheme)) { |
| 216 // URLs with the view-source scheme typically look like: | 216 // URLs with the view-source scheme typically look like: |
| 217 // view-source:http://www.google.com/a | 217 // view-source:http://www.google.com/a |
| 218 // In order to request these URLs, the child_id needs to be able to | 218 // In order to request these URLs, the child_id needs to be able to |
| 219 // request the embedded URL. | 219 // request the embedded URL. |
| 220 GrantRequestURL(child_id, GURL(url.path())); | 220 GrantRequestURL(child_id, GURL(url.path())); |
| 221 } | 221 } |
| 222 | 222 |
| 223 return; // Can't grant the capability to request pseudo schemes. | 223 return; // Can't grant the capability to request pseudo schemes. |
| 224 } | 224 } |
| 225 | 225 |
| 226 { | 226 { |
| 227 AutoLock lock(lock_); | 227 base::AutoLock lock(lock_); |
| 228 SecurityStateMap::iterator state = security_state_.find(child_id); | 228 SecurityStateMap::iterator state = security_state_.find(child_id); |
| 229 if (state == security_state_.end()) | 229 if (state == security_state_.end()) |
| 230 return; | 230 return; |
| 231 | 231 |
| 232 // If the child process has been commanded to request a scheme, then we | 232 // If the child process has been commanded to request a scheme, then we |
| 233 // grant it the capability to request URLs of that scheme. | 233 // grant it the capability to request URLs of that scheme. |
| 234 state->second->GrantScheme(url.scheme()); | 234 state->second->GrantScheme(url.scheme()); |
| 235 } | 235 } |
| 236 } | 236 } |
| 237 | 237 |
| 238 void ChildProcessSecurityPolicy::GrantReadFile(int child_id, | 238 void ChildProcessSecurityPolicy::GrantReadFile(int child_id, |
| 239 const FilePath& file) { | 239 const FilePath& file) { |
| 240 GrantPermissionsForFile(child_id, file, kReadFilePermissions); | 240 GrantPermissionsForFile(child_id, file, kReadFilePermissions); |
| 241 } | 241 } |
| 242 | 242 |
| 243 void ChildProcessSecurityPolicy::GrantPermissionsForFile( | 243 void ChildProcessSecurityPolicy::GrantPermissionsForFile( |
| 244 int child_id, const FilePath& file, int permissions) { | 244 int child_id, const FilePath& file, int permissions) { |
| 245 AutoLock lock(lock_); | 245 base::AutoLock lock(lock_); |
| 246 | 246 |
| 247 SecurityStateMap::iterator state = security_state_.find(child_id); | 247 SecurityStateMap::iterator state = security_state_.find(child_id); |
| 248 if (state == security_state_.end()) | 248 if (state == security_state_.end()) |
| 249 return; | 249 return; |
| 250 | 250 |
| 251 state->second->GrantPermissionsForFile(file, permissions); | 251 state->second->GrantPermissionsForFile(file, permissions); |
| 252 } | 252 } |
| 253 | 253 |
| 254 void ChildProcessSecurityPolicy::RevokeAllPermissionsForFile( | 254 void ChildProcessSecurityPolicy::RevokeAllPermissionsForFile( |
| 255 int child_id, const FilePath& file) { | 255 int child_id, const FilePath& file) { |
| 256 AutoLock lock(lock_); | 256 base::AutoLock lock(lock_); |
| 257 | 257 |
| 258 SecurityStateMap::iterator state = security_state_.find(child_id); | 258 SecurityStateMap::iterator state = security_state_.find(child_id); |
| 259 if (state == security_state_.end()) | 259 if (state == security_state_.end()) |
| 260 return; | 260 return; |
| 261 | 261 |
| 262 state->second->RevokeAllPermissionsForFile(file); | 262 state->second->RevokeAllPermissionsForFile(file); |
| 263 } | 263 } |
| 264 | 264 |
| 265 void ChildProcessSecurityPolicy::GrantScheme(int child_id, | 265 void ChildProcessSecurityPolicy::GrantScheme(int child_id, |
| 266 const std::string& scheme) { | 266 const std::string& scheme) { |
| 267 AutoLock lock(lock_); | 267 base::AutoLock lock(lock_); |
| 268 | 268 |
| 269 SecurityStateMap::iterator state = security_state_.find(child_id); | 269 SecurityStateMap::iterator state = security_state_.find(child_id); |
| 270 if (state == security_state_.end()) | 270 if (state == security_state_.end()) |
| 271 return; | 271 return; |
| 272 | 272 |
| 273 state->second->GrantScheme(scheme); | 273 state->second->GrantScheme(scheme); |
| 274 } | 274 } |
| 275 | 275 |
| 276 void ChildProcessSecurityPolicy::GrantDOMUIBindings(int child_id) { | 276 void ChildProcessSecurityPolicy::GrantDOMUIBindings(int child_id) { |
| 277 AutoLock lock(lock_); | 277 base::AutoLock lock(lock_); |
| 278 | 278 |
| 279 SecurityStateMap::iterator state = security_state_.find(child_id); | 279 SecurityStateMap::iterator state = security_state_.find(child_id); |
| 280 if (state == security_state_.end()) | 280 if (state == security_state_.end()) |
| 281 return; | 281 return; |
| 282 | 282 |
| 283 state->second->GrantBindings(BindingsPolicy::DOM_UI); | 283 state->second->GrantBindings(BindingsPolicy::DOM_UI); |
| 284 | 284 |
| 285 // DOM UI bindings need the ability to request chrome: URLs. | 285 // DOM UI bindings need the ability to request chrome: URLs. |
| 286 state->second->GrantScheme(chrome::kChromeUIScheme); | 286 state->second->GrantScheme(chrome::kChromeUIScheme); |
| 287 | 287 |
| 288 // DOM UI pages can contain links to file:// URLs. | 288 // DOM UI pages can contain links to file:// URLs. |
| 289 state->second->GrantScheme(chrome::kFileScheme); | 289 state->second->GrantScheme(chrome::kFileScheme); |
| 290 } | 290 } |
| 291 | 291 |
| 292 void ChildProcessSecurityPolicy::GrantExtensionBindings(int child_id) { | 292 void ChildProcessSecurityPolicy::GrantExtensionBindings(int child_id) { |
| 293 AutoLock lock(lock_); | 293 base::AutoLock lock(lock_); |
| 294 | 294 |
| 295 SecurityStateMap::iterator state = security_state_.find(child_id); | 295 SecurityStateMap::iterator state = security_state_.find(child_id); |
| 296 if (state == security_state_.end()) | 296 if (state == security_state_.end()) |
| 297 return; | 297 return; |
| 298 | 298 |
| 299 state->second->GrantBindings(BindingsPolicy::EXTENSION); | 299 state->second->GrantBindings(BindingsPolicy::EXTENSION); |
| 300 } | 300 } |
| 301 | 301 |
| 302 void ChildProcessSecurityPolicy::GrantReadRawCookies(int child_id) { | 302 void ChildProcessSecurityPolicy::GrantReadRawCookies(int child_id) { |
| 303 AutoLock lock(lock_); | 303 base::AutoLock lock(lock_); |
| 304 | 304 |
| 305 SecurityStateMap::iterator state = security_state_.find(child_id); | 305 SecurityStateMap::iterator state = security_state_.find(child_id); |
| 306 if (state == security_state_.end()) | 306 if (state == security_state_.end()) |
| 307 return; | 307 return; |
| 308 | 308 |
| 309 state->second->GrantReadRawCookies(); | 309 state->second->GrantReadRawCookies(); |
| 310 } | 310 } |
| 311 | 311 |
| 312 void ChildProcessSecurityPolicy::RevokeReadRawCookies(int child_id) { | 312 void ChildProcessSecurityPolicy::RevokeReadRawCookies(int child_id) { |
| 313 AutoLock lock(lock_); | 313 base::AutoLock lock(lock_); |
| 314 | 314 |
| 315 SecurityStateMap::iterator state = security_state_.find(child_id); | 315 SecurityStateMap::iterator state = security_state_.find(child_id); |
| 316 if (state == security_state_.end()) | 316 if (state == security_state_.end()) |
| 317 return; | 317 return; |
| 318 | 318 |
| 319 state->second->RevokeReadRawCookies(); | 319 state->second->RevokeReadRawCookies(); |
| 320 } | 320 } |
| 321 | 321 |
| 322 bool ChildProcessSecurityPolicy::CanRequestURL( | 322 bool ChildProcessSecurityPolicy::CanRequestURL( |
| 323 int child_id, const GURL& url) { | 323 int child_id, const GURL& url) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 347 // URLs like <about:memory> and <about:crash> shouldn't be requestable by | 347 // URLs like <about:memory> and <about:crash> shouldn't be requestable by |
| 348 // any child process. Also, this case covers <javascript:...>, which should | 348 // any child process. Also, this case covers <javascript:...>, which should |
| 349 // be handled internally by the process and not kicked up to the browser. | 349 // be handled internally by the process and not kicked up to the browser. |
| 350 return false; | 350 return false; |
| 351 } | 351 } |
| 352 | 352 |
| 353 if (!net::URLRequest::IsHandledURL(url)) | 353 if (!net::URLRequest::IsHandledURL(url)) |
| 354 return true; // This URL request is destined for ShellExecute. | 354 return true; // This URL request is destined for ShellExecute. |
| 355 | 355 |
| 356 { | 356 { |
| 357 AutoLock lock(lock_); | 357 base::AutoLock lock(lock_); |
| 358 | 358 |
| 359 SecurityStateMap::iterator state = security_state_.find(child_id); | 359 SecurityStateMap::iterator state = security_state_.find(child_id); |
| 360 if (state == security_state_.end()) | 360 if (state == security_state_.end()) |
| 361 return false; | 361 return false; |
| 362 | 362 |
| 363 // Otherwise, we consult the child process's security state to see if it is | 363 // Otherwise, we consult the child process's security state to see if it is |
| 364 // allowed to request the URL. | 364 // allowed to request the URL. |
| 365 return state->second->CanRequestURL(url); | 365 return state->second->CanRequestURL(url); |
| 366 } | 366 } |
| 367 } | 367 } |
| 368 | 368 |
| 369 bool ChildProcessSecurityPolicy::CanReadFile(int child_id, | 369 bool ChildProcessSecurityPolicy::CanReadFile(int child_id, |
| 370 const FilePath& file) { | 370 const FilePath& file) { |
| 371 return HasPermissionsForFile(child_id, file, kReadFilePermissions); | 371 return HasPermissionsForFile(child_id, file, kReadFilePermissions); |
| 372 } | 372 } |
| 373 | 373 |
| 374 bool ChildProcessSecurityPolicy::HasPermissionsForFile( | 374 bool ChildProcessSecurityPolicy::HasPermissionsForFile( |
| 375 int child_id, const FilePath& file, int permissions) { | 375 int child_id, const FilePath& file, int permissions) { |
| 376 AutoLock lock(lock_); | 376 base::AutoLock lock(lock_); |
| 377 | 377 |
| 378 SecurityStateMap::iterator state = security_state_.find(child_id); | 378 SecurityStateMap::iterator state = security_state_.find(child_id); |
| 379 if (state == security_state_.end()) | 379 if (state == security_state_.end()) |
| 380 return false; | 380 return false; |
| 381 | 381 |
| 382 return state->second->HasPermissionsForFile(file, permissions); | 382 return state->second->HasPermissionsForFile(file, permissions); |
| 383 } | 383 } |
| 384 | 384 |
| 385 bool ChildProcessSecurityPolicy::HasDOMUIBindings(int child_id) { | 385 bool ChildProcessSecurityPolicy::HasDOMUIBindings(int child_id) { |
| 386 AutoLock lock(lock_); | 386 base::AutoLock lock(lock_); |
| 387 | 387 |
| 388 SecurityStateMap::iterator state = security_state_.find(child_id); | 388 SecurityStateMap::iterator state = security_state_.find(child_id); |
| 389 if (state == security_state_.end()) | 389 if (state == security_state_.end()) |
| 390 return false; | 390 return false; |
| 391 | 391 |
| 392 return state->second->has_dom_ui_bindings(); | 392 return state->second->has_dom_ui_bindings(); |
| 393 } | 393 } |
| 394 | 394 |
| 395 bool ChildProcessSecurityPolicy::HasExtensionBindings(int child_id) { | 395 bool ChildProcessSecurityPolicy::HasExtensionBindings(int child_id) { |
| 396 AutoLock lock(lock_); | 396 base::AutoLock lock(lock_); |
| 397 | 397 |
| 398 SecurityStateMap::iterator state = security_state_.find(child_id); | 398 SecurityStateMap::iterator state = security_state_.find(child_id); |
| 399 if (state == security_state_.end()) | 399 if (state == security_state_.end()) |
| 400 return false; | 400 return false; |
| 401 | 401 |
| 402 return state->second->has_extension_bindings(); | 402 return state->second->has_extension_bindings(); |
| 403 } | 403 } |
| 404 | 404 |
| 405 bool ChildProcessSecurityPolicy::CanReadRawCookies(int child_id) { | 405 bool ChildProcessSecurityPolicy::CanReadRawCookies(int child_id) { |
| 406 AutoLock lock(lock_); | 406 base::AutoLock lock(lock_); |
| 407 | 407 |
| 408 SecurityStateMap::iterator state = security_state_.find(child_id); | 408 SecurityStateMap::iterator state = security_state_.find(child_id); |
| 409 if (state == security_state_.end()) | 409 if (state == security_state_.end()) |
| 410 return false; | 410 return false; |
| 411 | 411 |
| 412 return state->second->can_read_raw_cookies(); | 412 return state->second->can_read_raw_cookies(); |
| 413 } | 413 } |
| OLD | NEW |