Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/ssl/ssl_manager.h" | 5 #include "content/browser/ssl/ssl_manager.h" |
| 6 | 6 |
| 7 #include <set> | 7 #include <set> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/macros.h" | 10 #include "base/macros.h" |
| 11 #include "base/metrics/histogram_macros.h" | 11 #include "base/metrics/histogram_macros.h" |
| 12 #include "base/strings/utf_string_conversions.h" | 12 #include "base/strings/utf_string_conversions.h" |
| 13 #include "base/supports_user_data.h" | 13 #include "base/supports_user_data.h" |
| 14 #include "content/browser/frame_host/navigation_entry_impl.h" | 14 #include "content/browser/frame_host/navigation_entry_impl.h" |
| 15 #include "content/browser/loader/resource_dispatcher_host_impl.h" | 15 #include "content/browser/loader/resource_dispatcher_host_impl.h" |
| 16 #include "content/browser/loader/resource_request_info_impl.h" | 16 #include "content/browser/loader/resource_request_info_impl.h" |
| 17 #include "content/browser/ssl/ssl_error_handler.h" | 17 #include "content/browser/ssl/ssl_error_handler.h" |
| 18 #include "content/browser/web_contents/web_contents_impl.h" | 18 #include "content/browser/web_contents/web_contents_impl.h" |
| 19 #include "content/public/browser/browser_context.h" | 19 #include "content/public/browser/browser_context.h" |
| 20 #include "content/public/browser/browser_thread.h" | 20 #include "content/public/browser/browser_thread.h" |
| 21 #include "content/public/browser/certificate_request_result_type.h" | 21 #include "content/public/browser/certificate_request_result_type.h" |
| 22 #include "content/public/browser/content_browser_client.h" | 22 #include "content/public/browser/content_browser_client.h" |
| 23 #include "content/public/browser/navigation_details.h" | 23 #include "content/public/browser/navigation_details.h" |
| 24 #include "content/public/browser/ssl_host_state_delegate.h" | 24 #include "content/public/browser/ssl_host_state_delegate.h" |
| 25 #include "content/public/browser/ssl_status.h" | |
| 26 #include "net/url_request/url_request.h" | 25 #include "net/url_request/url_request.h" |
| 27 | 26 |
| 28 namespace content { | 27 namespace content { |
| 29 | 28 |
| 30 namespace { | 29 namespace { |
| 31 | 30 |
| 32 const char kSSLManagerKeyName[] = "content_ssl_manager"; | 31 const char kSSLManagerKeyName[] = "content_ssl_manager"; |
| 33 | 32 |
| 34 // Events for UMA. Do not reorder or change! | 33 // Events for UMA. Do not reorder or change! |
| 35 enum SSLGoodCertSeenEvent { | 34 enum SSLGoodCertSeenEvent { |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 144 int render_process_id, | 143 int render_process_id, |
| 145 int render_frame_id, | 144 int render_frame_id, |
| 146 const net::SSLInfo& ssl_info, | 145 const net::SSLInfo& ssl_info, |
| 147 bool fatal) { | 146 bool fatal) { |
| 148 OnSSLCertificateError(delegate, RESOURCE_TYPE_SUB_RESOURCE, url, | 147 OnSSLCertificateError(delegate, RESOURCE_TYPE_SUB_RESOURCE, url, |
| 149 base::Bind(&WebContentsImpl::FromRenderFrameHostID, | 148 base::Bind(&WebContentsImpl::FromRenderFrameHostID, |
| 150 render_process_id, render_frame_id), | 149 render_process_id, render_frame_id), |
| 151 ssl_info, fatal); | 150 ssl_info, fatal); |
| 152 } | 151 } |
| 153 | 152 |
| 154 // static | |
| 155 void SSLManager::NotifySSLInternalStateChanged(BrowserContext* context) { | |
| 156 SSLManagerSet* managers = static_cast<SSLManagerSet*>( | |
| 157 context->GetUserData(kSSLManagerKeyName)); | |
| 158 | |
| 159 for (std::set<SSLManager*>::iterator i = managers->get().begin(); | |
| 160 i != managers->get().end(); ++i) { | |
| 161 (*i)->UpdateEntry((*i)->controller()->GetLastCommittedEntry()); | |
| 162 } | |
| 163 } | |
| 164 | |
| 165 SSLManager::SSLManager(NavigationControllerImpl* controller) | 153 SSLManager::SSLManager(NavigationControllerImpl* controller) |
| 166 : controller_(controller), | 154 : controller_(controller), |
| 167 ssl_host_state_delegate_( | 155 ssl_host_state_delegate_( |
| 168 controller->GetBrowserContext()->GetSSLHostStateDelegate()) { | 156 controller->GetBrowserContext()->GetSSLHostStateDelegate()) { |
| 169 DCHECK(controller_); | 157 DCHECK(controller_); |
| 170 | 158 |
| 171 SSLManagerSet* managers = static_cast<SSLManagerSet*>( | 159 SSLManagerSet* managers = static_cast<SSLManagerSet*>( |
| 172 controller_->GetBrowserContext()->GetUserData(kSSLManagerKeyName)); | 160 controller_->GetBrowserContext()->GetUserData(kSSLManagerKeyName)); |
| 173 if (!managers) { | 161 if (!managers) { |
| 174 managers = new SSLManagerSet; | 162 managers = new SSLManagerSet; |
| 175 controller_->GetBrowserContext()->SetUserData(kSSLManagerKeyName, managers); | 163 controller_->GetBrowserContext()->SetUserData(kSSLManagerKeyName, managers); |
| 176 } | 164 } |
| 177 managers->get().insert(this); | 165 managers->get().insert(this); |
| 178 } | 166 } |
| 179 | 167 |
| 180 SSLManager::~SSLManager() { | 168 SSLManager::~SSLManager() { |
| 181 SSLManagerSet* managers = static_cast<SSLManagerSet*>( | 169 SSLManagerSet* managers = static_cast<SSLManagerSet*>( |
| 182 controller_->GetBrowserContext()->GetUserData(kSSLManagerKeyName)); | 170 controller_->GetBrowserContext()->GetUserData(kSSLManagerKeyName)); |
| 183 managers->get().erase(this); | 171 managers->get().erase(this); |
| 184 } | 172 } |
| 185 | 173 |
| 186 void SSLManager::DidCommitProvisionalLoad(const LoadCommittedDetails& details) { | 174 void SSLManager::DidCommitProvisionalLoad(const LoadCommittedDetails& details) { |
| 187 NavigationEntryImpl* entry = controller_->GetLastCommittedEntry(); | 175 NavigationEntryImpl* entry = controller_->GetLastCommittedEntry(); |
| 188 UpdateEntry(entry); | 176 UpdateEntry(entry, SSLStatus::NORMAL_CONTENT); |
| 189 // Always notify the WebContents that the SSL state changed when a | 177 // Always notify the WebContents that the SSL state changed when a |
| 190 // load is committed, in case the active navigation entry has changed. | 178 // load is committed, in case the active navigation entry has changed. |
| 191 NotifyDidChangeVisibleSSLState(); | 179 NotifyDidChangeVisibleSSLState(); |
| 192 } | 180 } |
| 193 | 181 |
| 194 void SSLManager::DidRunInsecureContent(const GURL& security_origin) { | 182 void SSLManager::DidDisplayMixedContent() { |
| 183 UpdateLastCommittedEntry(SSLStatus::DISPLAYED_INSECURE_CONTENT); | |
| 184 } | |
| 185 | |
| 186 void SSLManager::DidDisplayContentWithCertErrors() { | |
| 195 NavigationEntryImpl* entry = controller_->GetLastCommittedEntry(); | 187 NavigationEntryImpl* entry = controller_->GetLastCommittedEntry(); |
| 196 if (!entry) | 188 if (!entry) |
| 197 return; | 189 return; |
| 190 // Only record information about subresources with cert errors if the | |
| 191 // main page is HTTPS with a certificate. | |
| 192 if (entry->GetURL().SchemeIsCryptographic() && entry->GetSSL().certificate) { | |
| 193 UpdateLastCommittedEntry(SSLStatus::DISPLAYED_CONTENT_WITH_CERT_ERRORS); | |
| 194 } | |
| 195 } | |
| 196 | |
| 197 void SSLManager::DidShowPasswordInputOnHttp() { | |
| 198 UpdateLastCommittedEntry(SSLStatus::DISPLAYED_PASSWORD_FIELD_ON_HTTP); | |
| 199 } | |
| 200 | |
| 201 void SSLManager::DidShowCreditCardInputOnHttp() { | |
| 202 UpdateLastCommittedEntry(SSLStatus::DISPLAYED_CREDIT_CARD_FIELD_ON_HTTP); | |
| 203 } | |
| 204 | |
| 205 void SSLManager::DidRunMixedContent(const GURL& security_origin) { | |
| 206 NavigationEntryImpl* entry = controller_->GetLastCommittedEntry(); | |
| 207 if (!entry) | |
| 208 return; | |
| 198 | 209 |
| 199 SiteInstance* site_instance = entry->site_instance(); | 210 SiteInstance* site_instance = entry->site_instance(); |
| 200 if (!site_instance) | 211 if (!site_instance) |
| 201 return; | 212 return; |
| 202 | 213 |
| 203 if (ssl_host_state_delegate_) { | 214 if (ssl_host_state_delegate_) { |
| 204 ssl_host_state_delegate_->HostRanInsecureContent( | 215 ssl_host_state_delegate_->HostRanInsecureContent( |
| 205 security_origin.host(), site_instance->GetProcess()->GetID(), | 216 security_origin.host(), site_instance->GetProcess()->GetID(), |
| 206 SSLHostStateDelegate::MIXED_CONTENT); | 217 SSLHostStateDelegate::MIXED_CONTENT); |
| 207 } | 218 } |
| 208 UpdateEntry(entry); | 219 UpdateEntry(entry, SSLStatus::NORMAL_CONTENT); |
| 209 NotifySSLInternalStateChanged(controller_->GetBrowserContext()); | 220 NotifySSLInternalStateChanged(controller_->GetBrowserContext()); |
| 210 } | 221 } |
| 211 | 222 |
| 212 void SSLManager::DidRunContentWithCertErrors(const GURL& security_origin) { | 223 void SSLManager::DidRunContentWithCertErrors(const GURL& security_origin) { |
| 213 NavigationEntryImpl* entry = controller_->GetLastCommittedEntry(); | 224 NavigationEntryImpl* entry = controller_->GetLastCommittedEntry(); |
| 214 if (!entry) | 225 if (!entry) |
| 215 return; | 226 return; |
| 216 | 227 |
| 217 SiteInstance* site_instance = entry->site_instance(); | 228 SiteInstance* site_instance = entry->site_instance(); |
| 218 if (!site_instance) | 229 if (!site_instance) |
| 219 return; | 230 return; |
| 220 | 231 |
| 221 if (ssl_host_state_delegate_) { | 232 if (ssl_host_state_delegate_) { |
| 222 ssl_host_state_delegate_->HostRanInsecureContent( | 233 ssl_host_state_delegate_->HostRanInsecureContent( |
| 223 security_origin.host(), site_instance->GetProcess()->GetID(), | 234 security_origin.host(), site_instance->GetProcess()->GetID(), |
| 224 SSLHostStateDelegate::CERT_ERRORS_CONTENT); | 235 SSLHostStateDelegate::CERT_ERRORS_CONTENT); |
| 225 } | 236 } |
| 226 UpdateEntry(entry); | 237 UpdateEntry(entry, SSLStatus::NORMAL_CONTENT); |
| 227 NotifySSLInternalStateChanged(controller_->GetBrowserContext()); | 238 NotifySSLInternalStateChanged(controller_->GetBrowserContext()); |
| 228 } | 239 } |
| 229 | 240 |
| 230 void SSLManager::OnCertError(std::unique_ptr<SSLErrorHandler> handler) { | 241 void SSLManager::OnCertError(std::unique_ptr<SSLErrorHandler> handler) { |
| 231 bool expired_previous_decision = false; | 242 bool expired_previous_decision = false; |
| 232 // First we check if we know the policy for this error. | 243 // First we check if we know the policy for this error. |
| 233 DCHECK(handler->ssl_info().is_valid()); | 244 DCHECK(handler->ssl_info().is_valid()); |
| 234 SSLHostStateDelegate::CertJudgment judgment = | 245 SSLHostStateDelegate::CertJudgment judgment = |
| 235 ssl_host_state_delegate_ | 246 ssl_host_state_delegate_ |
| 236 ? ssl_host_state_delegate_->QueryPolicy( | 247 ? ssl_host_state_delegate_->QueryPolicy( |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 328 const net::SSLInfo& ssl_info = handler->ssl_info(); | 339 const net::SSLInfo& ssl_info = handler->ssl_info(); |
| 329 const GURL& request_url = handler->request_url(); | 340 const GURL& request_url = handler->request_url(); |
| 330 ResourceType resource_type = handler->resource_type(); | 341 ResourceType resource_type = handler->resource_type(); |
| 331 GetContentClient()->browser()->AllowCertificateError( | 342 GetContentClient()->browser()->AllowCertificateError( |
| 332 web_contents, cert_error, ssl_info, request_url, resource_type, | 343 web_contents, cert_error, ssl_info, request_url, resource_type, |
| 333 overridable, strict_enforcement, expired_previous_decision, | 344 overridable, strict_enforcement, expired_previous_decision, |
| 334 base::Bind(&OnAllowCertificate, base::Owned(handler.release()), | 345 base::Bind(&OnAllowCertificate, base::Owned(handler.release()), |
| 335 ssl_host_state_delegate_)); | 346 ssl_host_state_delegate_)); |
| 336 } | 347 } |
| 337 | 348 |
| 338 void SSLManager::UpdateEntry(NavigationEntryImpl* entry) { | 349 void SSLManager::UpdateEntry( |
| 350 NavigationEntryImpl* entry, | |
| 351 SSLStatus::ContentStatusFlags additional_content_status_flags) { | |
| 339 // We don't always have a navigation entry to update, for example in the | 352 // We don't always have a navigation entry to update, for example in the |
| 340 // case of the Web Inspector. | 353 // case of the Web Inspector. |
| 341 if (!entry) | 354 if (!entry) |
| 342 return; | 355 return; |
| 343 | 356 |
| 344 SSLStatus original_ssl_status = entry->GetSSL(); // Copy! | 357 SSLStatus original_ssl_status = entry->GetSSL(); // Copy! |
| 345 entry->GetSSL().initialized = true; | 358 entry->GetSSL().initialized = true; |
| 346 | 359 entry->GetSSL().content_status |= additional_content_status_flags; |
| 347 WebContentsImpl* web_contents_impl = | |
| 348 static_cast<WebContentsImpl*>(controller_->delegate()->GetWebContents()); | |
| 349 | |
| 350 // For sensitive inputs (password, credit card) on HTTP, do not clear | |
| 351 // the |content_status| flag when the WebContents no longer has the | |
| 352 // flag set. This is different from how DISPLAYED_INSECURE_CONTENT and | |
| 353 // DISPLAYED_CONTENT_WITH_CERT_ERRORS are handled below. For sensitive | |
| 354 // inputs on HTTP, once the NavigationEntry has been marked as having | |
| 355 // displayed a sensitive input, it stays that way, even if the | |
| 356 // sensitive input is subsequently removed from the page. | |
| 357 if (web_contents_impl->DisplayedPasswordFieldOnHttp()) { | |
| 358 entry->GetSSL().content_status |= | |
| 359 SSLStatus::DISPLAYED_PASSWORD_FIELD_ON_HTTP; | |
| 360 } | |
| 361 | |
| 362 if (web_contents_impl->DisplayedCreditCardFieldOnHttp()) { | |
| 363 entry->GetSSL().content_status |= | |
| 364 SSLStatus::DISPLAYED_CREDIT_CARD_FIELD_ON_HTTP; | |
| 365 } | |
| 366 | |
| 367 // Do not record information about insecure subresources if the main | |
| 368 // page is HTTP or HTTPS without a certificate. | |
| 369 if (!entry->GetURL().SchemeIsCryptographic() || !entry->GetSSL().certificate) | |
| 370 return; | |
| 371 | |
| 372 // Update the entry's flags for insecure content. | |
| 373 if (!web_contents_impl->DisplayedInsecureContent()) | |
| 374 entry->GetSSL().content_status &= ~SSLStatus::DISPLAYED_INSECURE_CONTENT; | |
|
estark
2016/10/12 07:01:19
You might notice here that we used to clear flags
| |
| 375 if (web_contents_impl->DisplayedInsecureContent()) | |
| 376 entry->GetSSL().content_status |= SSLStatus::DISPLAYED_INSECURE_CONTENT; | |
| 377 if (!web_contents_impl->DisplayedContentWithCertErrors()) { | |
| 378 entry->GetSSL().content_status &= | |
| 379 ~SSLStatus::DISPLAYED_CONTENT_WITH_CERT_ERRORS; | |
| 380 } | |
| 381 if (web_contents_impl->DisplayedContentWithCertErrors()) { | |
| 382 entry->GetSSL().content_status |= | |
| 383 SSLStatus::DISPLAYED_CONTENT_WITH_CERT_ERRORS; | |
| 384 } | |
| 385 | 360 |
| 386 SiteInstance* site_instance = entry->site_instance(); | 361 SiteInstance* site_instance = entry->site_instance(); |
| 387 // Note that |site_instance| can be NULL here because NavigationEntries don't | 362 // Note that |site_instance| can be NULL here because NavigationEntries don't |
| 388 // necessarily have site instances. Without a process, the entry can't | 363 // necessarily have site instances. Without a process, the entry can't |
| 389 // possibly have insecure content. See bug http://crbug.com/12423. | 364 // possibly have insecure content. See bug http://crbug.com/12423. |
| 390 if (site_instance && ssl_host_state_delegate_ && | 365 if (site_instance && ssl_host_state_delegate_ && |
| 391 ssl_host_state_delegate_->DidHostRunInsecureContent( | 366 ssl_host_state_delegate_->DidHostRunInsecureContent( |
| 392 entry->GetURL().host(), site_instance->GetProcess()->GetID(), | 367 entry->GetURL().host(), site_instance->GetProcess()->GetID(), |
| 393 SSLHostStateDelegate::MIXED_CONTENT)) { | 368 SSLHostStateDelegate::MIXED_CONTENT)) { |
| 394 entry->GetSSL().content_status |= SSLStatus::RAN_INSECURE_CONTENT; | 369 entry->GetSSL().content_status |= SSLStatus::RAN_INSECURE_CONTENT; |
| 395 } | 370 } |
| 396 | 371 |
| 397 if (site_instance && ssl_host_state_delegate_ && | 372 // Only record information about subresources with cert errors if the |
| 373 // main page is HTTPS with a certificate. | |
| 374 if (entry->GetURL().SchemeIsCryptographic() && entry->GetSSL().certificate && | |
| 375 site_instance && ssl_host_state_delegate_ && | |
| 398 ssl_host_state_delegate_->DidHostRunInsecureContent( | 376 ssl_host_state_delegate_->DidHostRunInsecureContent( |
| 399 entry->GetURL().host(), site_instance->GetProcess()->GetID(), | 377 entry->GetURL().host(), site_instance->GetProcess()->GetID(), |
| 400 SSLHostStateDelegate::CERT_ERRORS_CONTENT)) { | 378 SSLHostStateDelegate::CERT_ERRORS_CONTENT)) { |
| 401 entry->GetSSL().content_status |= SSLStatus::RAN_CONTENT_WITH_CERT_ERRORS; | 379 entry->GetSSL().content_status |= SSLStatus::RAN_CONTENT_WITH_CERT_ERRORS; |
| 402 } | 380 } |
| 403 | 381 |
| 404 if (!entry->GetSSL().Equals(original_ssl_status)) | 382 if (!entry->GetSSL().Equals(original_ssl_status)) |
| 405 NotifyDidChangeVisibleSSLState(); | 383 NotifyDidChangeVisibleSSLState(); |
| 406 } | 384 } |
| 407 | 385 |
| 386 void SSLManager::UpdateLastCommittedEntry( | |
| 387 SSLStatus::ContentStatusFlags additional_content_status_flags) { | |
| 388 NavigationEntryImpl* entry = controller_->GetLastCommittedEntry(); | |
| 389 if (!entry) | |
| 390 return; | |
| 391 UpdateEntry(entry, additional_content_status_flags); | |
| 392 } | |
| 393 | |
| 408 void SSLManager::NotifyDidChangeVisibleSSLState() { | 394 void SSLManager::NotifyDidChangeVisibleSSLState() { |
| 409 WebContentsImpl* contents = | 395 WebContentsImpl* contents = |
| 410 static_cast<WebContentsImpl*>(controller_->delegate()->GetWebContents()); | 396 static_cast<WebContentsImpl*>(controller_->delegate()->GetWebContents()); |
| 411 contents->DidChangeVisibleSSLState(); | 397 contents->DidChangeVisibleSSLState(); |
| 412 } | 398 } |
| 413 | 399 |
| 400 // static | |
| 401 void SSLManager::NotifySSLInternalStateChanged(BrowserContext* context) { | |
| 402 SSLManagerSet* managers = | |
| 403 static_cast<SSLManagerSet*>(context->GetUserData(kSSLManagerKeyName)); | |
| 404 | |
| 405 for (std::set<SSLManager*>::iterator i = managers->get().begin(); | |
| 406 i != managers->get().end(); ++i) { | |
| 407 (*i)->UpdateEntry((*i)->controller()->GetLastCommittedEntry(), | |
| 408 SSLStatus::NORMAL_CONTENT); | |
| 409 } | |
| 410 } | |
| 411 | |
| 414 } // namespace content | 412 } // namespace content |
| OLD | NEW |