Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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/ssl/ssl_policy.h" | 5 #include "chrome/browser/ssl/ssl_policy.h" |
| 6 | 6 |
| 7 #include "base/singleton.h" | |
| 8 #include "base/string_piece.h" | 7 #include "base/string_piece.h" |
| 9 #include "base/string_util.h" | 8 #include "base/string_util.h" |
| 10 #include "chrome/browser/cert_store.h" | 9 #include "chrome/browser/cert_store.h" |
| 11 #include "chrome/browser/renderer_host/render_view_host.h" | 10 #include "chrome/browser/renderer_host/render_view_host.h" |
| 12 #include "chrome/browser/ssl/ssl_error_info.h" | 11 #include "chrome/browser/ssl/ssl_error_info.h" |
| 13 #include "chrome/browser/tab_contents/navigation_entry.h" | 12 #include "chrome/browser/tab_contents/navigation_entry.h" |
| 14 #include "chrome/browser/tab_contents/web_contents.h" | 13 #include "chrome/browser/tab_contents/web_contents.h" |
| 15 #include "chrome/common/jstemplate_builder.h" | 14 #include "chrome/common/jstemplate_builder.h" |
| 16 #include "chrome/common/l10n_util.h" | 15 #include "chrome/common/l10n_util.h" |
| 17 #include "chrome/common/notification_service.h" | 16 #include "chrome/common/notification_service.h" |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 31 #if defined(OS_WIN) | 30 #if defined(OS_WIN) |
| 32 // TODO(port): port these files. | 31 // TODO(port): port these files. |
| 33 #include "chrome/browser/tab_contents/tab_contents.h" | 32 #include "chrome/browser/tab_contents/tab_contents.h" |
| 34 #elif defined(OS_POSIX) | 33 #elif defined(OS_POSIX) |
| 35 #include "chrome/common/temp_scaffolding_stubs.h" | 34 #include "chrome/common/temp_scaffolding_stubs.h" |
| 36 #endif | 35 #endif |
| 37 | 36 |
| 38 // Wrap all these helper classes in an anonymous namespace. | 37 // Wrap all these helper classes in an anonymous namespace. |
| 39 namespace { | 38 namespace { |
| 40 | 39 |
| 41 static const char kDot = '.'; | 40 class ShowMixedContentTask : public Task { |
| 42 | |
| 43 class ShowUnsafeContentTask : public Task { | |
| 44 public: | 41 public: |
| 45 ShowUnsafeContentTask(const GURL& main_frame_url, | 42 ShowMixedContentTask(SSLPolicy* ssl_policy, |
| 46 SSLManager::ErrorHandler* error_handler); | 43 SSLManager::MixedContentHandler* handler); |
| 47 virtual ~ShowUnsafeContentTask(); | 44 virtual ~ShowMixedContentTask(); |
| 48 | 45 |
| 49 virtual void Run(); | 46 virtual void Run(); |
| 50 | 47 |
| 51 private: | 48 private: |
| 52 scoped_refptr<SSLManager::ErrorHandler> error_handler_; | 49 scoped_refptr<SSLManager::MixedContentHandler> handler_; |
| 53 GURL main_frame_url_; | |
| 54 | 50 |
| 55 DISALLOW_EVIL_CONSTRUCTORS(ShowUnsafeContentTask); | 51 SSLPolicy* ssl_policy_; |
| 52 | |
| 53 DISALLOW_COPY_AND_ASSIGN(ShowMixedContentTask); | |
| 56 }; | 54 }; |
| 57 | 55 |
| 58 ShowUnsafeContentTask::ShowUnsafeContentTask( | 56 ShowMixedContentTask::ShowMixedContentTask( |
| 59 const GURL& main_frame_url, | 57 SSLPolicy* ssl_policy, SSLManager::MixedContentHandler* handler) |
| 60 SSLManager::ErrorHandler* error_handler) | 58 : ssl_policy_(ssl_policy), handler_(handler) { |
| 61 : error_handler_(error_handler), | |
| 62 main_frame_url_(main_frame_url) { | |
| 63 } | 59 } |
| 64 | 60 |
| 65 ShowUnsafeContentTask::~ShowUnsafeContentTask() { | 61 ShowMixedContentTask::~ShowMixedContentTask() { |
| 66 } | 62 } |
| 67 | 63 |
| 68 void ShowUnsafeContentTask::Run() { | 64 void ShowMixedContentTask::Run() { |
| 69 error_handler_->manager()->AllowShowInsecureContentForURL(main_frame_url_); | 65 ssl_policy_->AllowMixedContent(handler_); |
| 70 // Reload the page. | 66 handler_->GetWebContents()->controller()->Reload(true); |
| 71 error_handler_->GetWebContents()->controller()->Reload(true); | |
| 72 } | 67 } |
| 73 | 68 |
| 74 static void ShowErrorPage(SSLPolicy* policy, SSLManager::CertError* error) { | 69 static void ShowErrorPage(SSLPolicy* policy, SSLManager::CertError* error) { |
| 75 SSLErrorInfo error_info = policy->GetSSLErrorInfo(error); | 70 SSLErrorInfo error_info = policy->GetSSLErrorInfo(error); |
| 76 | 71 |
| 77 // Let's build the html error page. | 72 // Let's build the html error page. |
| 78 DictionaryValue strings; | 73 DictionaryValue strings; |
| 79 strings.SetString(L"title", l10n_util::GetString(IDS_SSL_ERROR_PAGE_TITLE)); | 74 strings.SetString(L"title", l10n_util::GetString(IDS_SSL_ERROR_PAGE_TITLE)); |
| 80 strings.SetString(L"headLine", error_info.title()); | 75 strings.SetString(L"headLine", error_info.title()); |
| 81 strings.SetString(L"description", error_info.details()); | 76 strings.SetString(L"description", error_info.details()); |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 109 security_info); | 104 security_info); |
| 110 tab->controller()->GetActiveEntry()->set_page_type( | 105 tab->controller()->GetActiveEntry()->set_page_type( |
| 111 NavigationEntry::ERROR_PAGE); | 106 NavigationEntry::ERROR_PAGE); |
| 112 } | 107 } |
| 113 | 108 |
| 114 static void ShowBlockingPage(SSLPolicy* policy, SSLManager::CertError* error) { | 109 static void ShowBlockingPage(SSLPolicy* policy, SSLManager::CertError* error) { |
| 115 SSLBlockingPage* blocking_page = new SSLBlockingPage(error, policy); | 110 SSLBlockingPage* blocking_page = new SSLBlockingPage(error, policy); |
| 116 blocking_page->Show(); | 111 blocking_page->Show(); |
| 117 } | 112 } |
| 118 | 113 |
| 119 #if 0 | 114 static void InitializeEntryIfNeeded(NavigationEntry* entry) { |
| 120 // See TODO(jcampan) below. | 115 if (entry->ssl().security_style() != SECURITY_STYLE_UNKNOWN) |
| 121 static bool IsIntranetHost(const std::string& host) { | 116 return; |
| 122 const size_t dot = host.find(kDot); | 117 |
| 123 return dot == std::string::npos || dot == host.length() - 1; | 118 SecurityStyle security_style = entry->url().SchemeIsSecure() ? |
| 119 SECURITY_STYLE_AUTHENTICATED : SECURITY_STYLE_UNAUTHENTICATED; | |
|
jcampan
2009/03/16 18:43:54
Nit: indent 4 spaces
abarth-chromium
2009/03/16 21:34:21
Fixed.
| |
| 120 | |
| 121 entry->ssl().set_security_style(security_style); | |
| 124 } | 122 } |
| 125 #endif | |
| 126 | 123 |
| 127 class CommonNameInvalidPolicy : public SSLPolicy { | 124 static void AddMixedContentWarningToConsole( |
| 128 public: | 125 SSLManager::MixedContentHandler* handler) { |
| 129 static SSLPolicy* GetInstance() { | 126 const std::wstring& msg = l10n_util::GetStringF( |
| 130 return Singleton<CommonNameInvalidPolicy>::get(); | 127 IDS_MIXED_CONTENT_LOG_MESSAGE, |
| 131 } | 128 UTF8ToWide(handler->frame_origin()), |
| 129 UTF8ToWide(handler->request_url().spec())); | |
| 130 handler->manager()->AddMessageToConsole(msg, MESSAGE_LEVEL_WARNING); | |
| 131 } | |
| 132 | 132 |
| 133 void OnCertError(const GURL& main_frame_url, | 133 static bool HasSafeScheme(const GURL& url) { |
| 134 SSLManager::CertError* error) { | 134 return (url.SchemeIsSecure() || |
| 135 OnOverridableCertError(main_frame_url, error); | 135 url.SchemeIs(chrome::kDataScheme) || |
| 136 } | 136 url.SchemeIs(chrome::kJavaScriptScheme) || |
| 137 }; | 137 url.SchemeIs(chrome::kAboutScheme)); |
| 138 | 138 } |
| 139 class DateInvalidPolicy : public SSLPolicy { | |
| 140 public: | |
| 141 static SSLPolicy* GetInstance() { | |
| 142 return Singleton<DateInvalidPolicy>::get(); | |
| 143 } | |
| 144 | |
| 145 void OnCertError(const GURL& main_frame_url, | |
| 146 SSLManager::CertError* error) { | |
| 147 OnOverridableCertError(main_frame_url, error); | |
| 148 } | |
| 149 }; | |
| 150 | |
| 151 class AuthorityInvalidPolicy : public SSLPolicy { | |
| 152 public: | |
| 153 static SSLPolicy* GetInstance() { | |
| 154 return Singleton<AuthorityInvalidPolicy>::get(); | |
| 155 } | |
| 156 | |
| 157 void OnCertError(const GURL& main_frame_url, | |
| 158 SSLManager::CertError* error) { | |
| 159 OnOverridableCertError(main_frame_url, error); | |
| 160 } | |
| 161 }; | |
| 162 | |
| 163 class ContainsErrorsPolicy : public SSLPolicy { | |
| 164 public: | |
| 165 static SSLPolicy* GetInstance() { | |
| 166 return Singleton<ContainsErrorsPolicy>::get(); | |
| 167 } | |
| 168 | |
| 169 void OnCertError(const GURL& main_frame_url, | |
| 170 SSLManager::CertError* error) { | |
| 171 OnFatalCertError(main_frame_url, error); | |
| 172 } | |
| 173 }; | |
| 174 | |
| 175 class NoRevocationMechanismPolicy : public SSLPolicy { | |
| 176 public: | |
| 177 static SSLPolicy* GetInstance() { | |
| 178 return Singleton<NoRevocationMechanismPolicy>::get(); | |
| 179 } | |
| 180 | |
| 181 void OnCertError(const GURL& main_frame_url, | |
| 182 SSLManager::CertError* error) { | |
| 183 // Silently ignore this error. | |
| 184 error->ContinueRequest(); | |
| 185 } | |
| 186 }; | |
| 187 | |
| 188 class UnableToCheckRevocationPolicy : public SSLPolicy { | |
| 189 public: | |
| 190 static SSLPolicy* GetInstance() { | |
| 191 return Singleton<UnableToCheckRevocationPolicy>::get(); | |
| 192 } | |
| 193 | |
| 194 void OnCertError(const GURL& main_frame_url, | |
| 195 SSLManager::CertError* error) { | |
| 196 // We ignore this error and display an info-bar. | |
| 197 error->ContinueRequest(); | |
| 198 error->manager()->ShowMessage(l10n_util::GetString( | |
| 199 IDS_CERT_ERROR_UNABLE_TO_CHECK_REVOCATION_INFO_BAR)); | |
| 200 } | |
| 201 }; | |
| 202 | |
| 203 class RevokedPolicy : public SSLPolicy { | |
| 204 public: | |
| 205 static SSLPolicy* GetInstance() { | |
| 206 return Singleton<RevokedPolicy>::get(); | |
| 207 } | |
| 208 | |
| 209 void OnCertError(const GURL& main_frame_url, | |
| 210 SSLManager::CertError* error) { | |
| 211 OnFatalCertError(main_frame_url, error); | |
| 212 } | |
| 213 }; | |
| 214 | |
| 215 class InvalidPolicy : public SSLPolicy { | |
| 216 public: | |
| 217 static SSLPolicy* GetInstance() { | |
| 218 return Singleton<InvalidPolicy>::get(); | |
| 219 } | |
| 220 | |
| 221 void OnCertError(const GURL& main_frame_url, | |
| 222 SSLManager::CertError* error) { | |
| 223 OnFatalCertError(main_frame_url, error); | |
| 224 } | |
| 225 }; | |
| 226 | |
| 227 class DefaultPolicy : public SSLPolicy { | |
| 228 public: | |
| 229 DefaultPolicy() { | |
| 230 // Load our helper classes to handle various cert errors. | |
| 231 DCHECK(SubPolicyIndex(net::ERR_CERT_COMMON_NAME_INVALID) == 0); | |
| 232 sub_policies_[0] = CommonNameInvalidPolicy::GetInstance(); | |
| 233 DCHECK(SubPolicyIndex(net::ERR_CERT_DATE_INVALID) == 1); | |
| 234 sub_policies_[1] = DateInvalidPolicy::GetInstance(); | |
| 235 DCHECK(SubPolicyIndex(net::ERR_CERT_AUTHORITY_INVALID) == 2); | |
| 236 sub_policies_[2] = AuthorityInvalidPolicy::GetInstance(); | |
| 237 DCHECK(SubPolicyIndex(net::ERR_CERT_CONTAINS_ERRORS) == 3); | |
| 238 sub_policies_[3] = ContainsErrorsPolicy::GetInstance(); | |
| 239 DCHECK(SubPolicyIndex(net::ERR_CERT_NO_REVOCATION_MECHANISM) == 4); | |
| 240 sub_policies_[4] = NoRevocationMechanismPolicy::GetInstance(); | |
| 241 DCHECK(SubPolicyIndex(net::ERR_CERT_UNABLE_TO_CHECK_REVOCATION) == 5); | |
| 242 sub_policies_[5] = UnableToCheckRevocationPolicy::GetInstance(); | |
| 243 DCHECK(SubPolicyIndex(net::ERR_CERT_REVOKED) == 6); | |
| 244 sub_policies_[6] = RevokedPolicy::GetInstance(); | |
| 245 DCHECK(SubPolicyIndex(net::ERR_CERT_INVALID) == 7); | |
| 246 sub_policies_[7] = InvalidPolicy::GetInstance(); | |
| 247 DCHECK(SubPolicyIndex(net::ERR_CERT_END) == 8); | |
| 248 } | |
| 249 | |
| 250 void OnCertError(const GURL& main_frame_url, | |
| 251 SSLManager::CertError* error) { | |
| 252 size_t index = SubPolicyIndex(error->cert_error()); | |
| 253 if (index < 0 || index >= arraysize(sub_policies_)) { | |
| 254 NOTREACHED(); | |
| 255 error->CancelRequest(); | |
| 256 return; | |
| 257 } | |
| 258 | |
| 259 // First we check if we know the policy for this error. | |
| 260 net::X509Certificate::Policy::Judgment judgment = | |
| 261 error->manager()->QueryPolicy(error->ssl_info().cert, | |
| 262 error->request_url().host()); | |
| 263 | |
| 264 switch (judgment) { | |
| 265 case net::X509Certificate::Policy::ALLOWED: | |
| 266 // We've been told to allow this certificate. | |
| 267 if (error->manager()->SetMaxSecurityStyle( | |
| 268 SECURITY_STYLE_AUTHENTICATION_BROKEN)) { | |
| 269 NotificationService::current()->Notify( | |
| 270 NotificationType::SSL_STATE_CHANGED, | |
| 271 Source<NavigationController>(error->manager()->controller()), | |
| 272 Details<NavigationEntry>( | |
| 273 error->manager()->controller()->GetActiveEntry())); | |
| 274 } | |
| 275 error->ContinueRequest(); | |
| 276 break; | |
| 277 case net::X509Certificate::Policy::DENIED: | |
| 278 // For now we handle the DENIED as the UNKNOWN, which means a blocking | |
| 279 // page is shown to the user every time he comes back to the page. | |
| 280 case net::X509Certificate::Policy::UNKNOWN: | |
| 281 // We don't know how to handle this error. Ask our sub-policies. | |
| 282 sub_policies_[index]->OnCertError(main_frame_url, error); | |
| 283 break; | |
| 284 default: | |
| 285 NOTREACHED(); | |
| 286 } | |
| 287 } | |
| 288 | |
| 289 void OnMixedContent(NavigationController* navigation_controller, | |
| 290 const GURL& main_frame_url, | |
| 291 SSLManager::MixedContentHandler* mixed_content_handler) { | |
| 292 PrefService* prefs = navigation_controller->profile()->GetPrefs(); | |
| 293 FilterPolicy::Type filter_policy = FilterPolicy::DONT_FILTER; | |
| 294 if (!mixed_content_handler->manager()-> | |
| 295 CanShowInsecureContent(main_frame_url)) { | |
| 296 filter_policy = FilterPolicy::FromInt( | |
| 297 prefs->GetInteger(prefs::kMixedContentFiltering)); | |
| 298 } | |
| 299 if (filter_policy != FilterPolicy::DONT_FILTER) { | |
| 300 mixed_content_handler->manager()->ShowMessageWithLink( | |
| 301 l10n_util::GetString(IDS_SSL_INFO_BAR_FILTERED_CONTENT), | |
| 302 l10n_util::GetString(IDS_SSL_INFO_BAR_SHOW_CONTENT), | |
| 303 new ShowUnsafeContentTask(main_frame_url, mixed_content_handler)); | |
| 304 } | |
| 305 mixed_content_handler->StartRequest(filter_policy); | |
| 306 | |
| 307 NavigationEntry* entry = navigation_controller->GetLastCommittedEntry(); | |
| 308 DCHECK(entry); | |
| 309 // Even though we are loading the mixed-content resource, it will not be | |
| 310 // included in the page when we set the policy to FILTER_ALL or | |
| 311 // FILTER_ALL_EXCEPT_IMAGES (only images and they are stamped with warning | |
| 312 // icons), so we don't set the mixed-content mode in these cases. | |
| 313 if (filter_policy == FilterPolicy::DONT_FILTER) | |
| 314 entry->ssl().set_has_mixed_content(); | |
| 315 | |
| 316 // Print a message indicating the mixed-contents resource in the console. | |
| 317 const std::wstring& msg = l10n_util::GetStringF( | |
| 318 IDS_MIXED_CONTENT_LOG_MESSAGE, | |
| 319 UTF8ToWide(entry->url().spec()), | |
| 320 UTF8ToWide(mixed_content_handler->request_url().spec())); | |
| 321 mixed_content_handler->manager()-> | |
| 322 AddMessageToConsole(msg, MESSAGE_LEVEL_WARNING); | |
| 323 | |
| 324 NotificationService::current()->Notify( | |
| 325 NotificationType::SSL_STATE_CHANGED, | |
| 326 Source<NavigationController>(navigation_controller), | |
| 327 Details<NavigationEntry>(entry)); | |
| 328 } | |
| 329 | |
| 330 void OnDenyCertificate(SSLManager::CertError* error) { | |
| 331 size_t index = SubPolicyIndex(error->cert_error()); | |
| 332 if (index < 0 || index >= arraysize(sub_policies_)) { | |
| 333 NOTREACHED(); | |
| 334 return; | |
| 335 } | |
| 336 sub_policies_[index]->OnDenyCertificate(error); | |
| 337 } | |
| 338 | |
| 339 void OnAllowCertificate(SSLManager::CertError* error) { | |
| 340 size_t index = SubPolicyIndex(error->cert_error()); | |
| 341 if (index < 0 || index >= arraysize(sub_policies_)) { | |
| 342 NOTREACHED(); | |
| 343 return; | |
| 344 } | |
| 345 sub_policies_[index]->OnAllowCertificate(error); | |
| 346 } | |
| 347 | |
| 348 private: | |
| 349 // Returns the index of the sub-policy for |cert_error| in the | |
| 350 // sub_policies_ array. | |
| 351 int SubPolicyIndex(int cert_error) { | |
| 352 // Certificate errors are negative integers from net::ERR_CERT_BEGIN | |
| 353 // (inclusive) to net::ERR_CERT_END (exclusive) in *decreasing* order. | |
| 354 return net::ERR_CERT_BEGIN - cert_error; | |
| 355 } | |
| 356 SSLPolicy* sub_policies_[net::ERR_CERT_BEGIN - net::ERR_CERT_END]; | |
| 357 }; | |
| 358 | 139 |
| 359 } // namespace | 140 } // namespace |
| 360 | 141 |
| 361 SSLPolicy* SSLPolicy::GetDefaultPolicy() { | |
| 362 // Lazily initialize our default policy instance. | |
| 363 static SSLPolicy* default_policy = new DefaultPolicy(); | |
| 364 return default_policy; | |
| 365 } | |
| 366 | |
| 367 SSLPolicy::SSLPolicy() { | 142 SSLPolicy::SSLPolicy() { |
| 368 } | 143 } |
| 369 | 144 |
| 370 void SSLPolicy::OnCertError(const GURL& main_frame_url, | 145 SSLPolicy* SSLPolicy::GetDefaultPolicy() { |
| 371 SSLManager::CertError* error) { | 146 return Singleton<SSLPolicy>::get(); |
| 372 // Default to secure behavior. | |
| 373 error->CancelRequest(); | |
| 374 } | 147 } |
| 375 | 148 |
| 376 void SSLPolicy::OnRequestStarted(SSLManager* manager, const GURL& url, | 149 void SSLPolicy::OnCertError(SSLManager::CertError* error) { |
| 377 ResourceType::Type resource_type, | 150 // First we check if we know the policy for this error. |
| 378 int ssl_cert_id, int ssl_cert_status) { | 151 net::X509Certificate::Policy::Judgment judgment = |
| 379 // These schemes never leave the browser and don't require a warning. | 152 error->manager()->QueryPolicy(error->ssl_info().cert, |
| 380 if (url.SchemeIs(chrome::kDataScheme) || | 153 error->request_url().host()); |
| 381 url.SchemeIs(chrome::kJavaScriptScheme) || | |
| 382 url.SchemeIs(chrome::kAboutScheme)) | |
| 383 return; | |
| 384 | 154 |
| 385 NavigationEntry* entry = manager->controller()->GetActiveEntry(); | 155 if (judgment == net::X509Certificate::Policy::ALLOWED) { |
| 386 if (!entry) { | 156 error->ContinueRequest(); |
| 387 // We may not have an entry for cases such as the inspector. | |
| 388 return; | 157 return; |
| 389 } | 158 } |
| 390 | 159 |
| 391 NavigationEntry::SSLStatus& ssl = entry->ssl(); | 160 // The judgment is either DENIED or UNKNOWN. |
| 392 bool changed = false; | 161 // For now we handle the DENIED as the UNKNOWN, which means a blocking |
| 393 if (!entry->url().SchemeIsSecure() || // Current page is not secure. | 162 // page is shown to the user every time he comes back to the page. |
| 394 resource_type == ResourceType::MAIN_FRAME || // Main frame load. | |
| 395 net::IsCertStatusError(ssl.cert_status())) { // There is already | |
| 396 // an error for the main page, don't report sub-resources as unsafe | |
| 397 // content. | |
| 398 // No mixed/unsafe content check necessary. | |
| 399 return; | |
| 400 } | |
| 401 | 163 |
| 402 if (url.SchemeIsSecure()) { | 164 switch(error->cert_error()) { |
| 403 // Check for insecure content (anything served over intranet is considered | 165 case net::ERR_CERT_COMMON_NAME_INVALID: |
| 404 // insecure). | 166 case net::ERR_CERT_DATE_INVALID: |
| 405 | 167 case net::ERR_CERT_AUTHORITY_INVALID: |
| 406 // TODO(jcampan): bug #1178228 Disabling the broken style for intranet | 168 OnOverridableCertError(error); |
| 407 // hosts for beta as it is missing error strings (and cert status). | 169 break; |
| 408 // if (IsIntranetHost(url.host()) || | 170 case net::ERR_CERT_NO_REVOCATION_MECHANISM: |
| 409 // net::IsCertStatusError(ssl_cert_status)) { | 171 // Ignore this error. |
| 410 if (net::IsCertStatusError(ssl_cert_status)) { | 172 error->ContinueRequest(); |
| 411 // The resource is unsafe. | 173 break; |
| 412 if (!ssl.has_unsafe_content()) { | 174 case net::ERR_CERT_UNABLE_TO_CHECK_REVOCATION: |
| 413 changed = true; | 175 // We ignore this error and display an infobar. |
| 414 ssl.set_has_unsafe_content(); | 176 error->ContinueRequest(); |
| 415 manager->SetMaxSecurityStyle(SECURITY_STYLE_AUTHENTICATION_BROKEN); | 177 error->manager()->ShowMessage(l10n_util::GetString( |
| 416 } | 178 IDS_CERT_ERROR_UNABLE_TO_CHECK_REVOCATION_INFO_BAR)); |
| 417 } | 179 break; |
| 418 } | 180 case net::ERR_CERT_CONTAINS_ERRORS: |
| 419 | 181 case net::ERR_CERT_REVOKED: |
| 420 if (changed) { | 182 case net::ERR_CERT_INVALID: |
| 421 // Only send the notification when something actually changed. | 183 OnFatalCertError(error); |
| 422 NotificationService::current()->Notify( | 184 break; |
| 423 NotificationType::SSL_STATE_CHANGED, | 185 default: |
| 424 Source<NavigationController>(manager->controller()), | 186 NOTREACHED(); |
| 425 NotificationService::NoDetails()); | 187 error->CancelRequest(); |
| 188 break; | |
| 426 } | 189 } |
| 427 } | 190 } |
| 428 | 191 |
| 429 SecurityStyle SSLPolicy::GetDefaultStyle(const GURL& url) { | 192 void SSLPolicy::OnMixedContent(SSLManager::MixedContentHandler* handler) { |
| 430 // Show the secure style for HTTPS. | 193 // Get the user's mixed content preference. |
| 431 if (url.SchemeIsSecure()) { | 194 PrefService* prefs = handler->GetWebContents()->profile()->GetPrefs(); |
| 432 // TODO(jcampan): bug #1178228 Disabling the broken style for intranet | 195 FilterPolicy::Type filter_policy = |
| 433 // hosts for beta as it is missing error strings (and cert status). | 196 FilterPolicy::FromInt(prefs->GetInteger(prefs::kMixedContentFiltering)); |
| 434 // CAs issue certs for intranet hosts to anyone. | |
| 435 // if (IsIntranetHost(url.host())) | |
| 436 // return SECURITY_STYLE_AUTHENTICATION_BROKEN; | |
| 437 | 197 |
| 438 return SECURITY_STYLE_AUTHENTICATED; | 198 // If the user have added an exception, doctor the |filter_policy|. |
| 199 if (!handler->manager()->DidAllowMixedContentForHost( | |
| 200 GURL(handler->main_frame_origin()).host())) | |
| 201 filter_policy = FilterPolicy::DONT_FILTER; | |
| 202 | |
| 203 if (filter_policy != FilterPolicy::DONT_FILTER) { | |
| 204 // Give the user a chance to see unfiltered content. | |
| 205 handler->manager()->ShowMessageWithLink( | |
| 206 l10n_util::GetString(IDS_SSL_INFO_BAR_FILTERED_CONTENT), | |
| 207 l10n_util::GetString(IDS_SSL_INFO_BAR_SHOW_CONTENT), | |
| 208 new ShowMixedContentTask(this, handler)); | |
| 439 } | 209 } |
| 210 handler->StartRequest(filter_policy); | |
| 211 AddMixedContentWarningToConsole(handler); | |
| 212 } | |
| 440 | 213 |
| 441 // Otherwise, show the unauthenticated style. | 214 void SSLPolicy::OnRequestStarted(SSLManager::RequestInfo* info) { |
| 442 return SECURITY_STYLE_UNAUTHENTICATED; | 215 if (IsMixedContent(info->url(), info->resource_type(), info->frame_origin())) |
| 216 UpdateStateForMixedContent(info); | |
| 217 | |
| 218 if (net::IsCertStatusError(info->ssl_cert_status())) | |
| 219 UpdateStateForUnsafeContent(info); | |
| 443 } | 220 } |
| 444 | 221 |
| 222 void SSLPolicy::UpdateEntry(SSLManager* manager, NavigationEntry* entry) { | |
| 223 DCHECK(entry); | |
| 224 | |
| 225 InitializeEntryIfNeeded(entry); | |
| 226 | |
| 227 if (!entry->url().SchemeIsSecure()) | |
| 228 return; | |
| 229 | |
| 230 const std::string& host = entry->url().host(); | |
| 231 if (manager->DidMarkHostAsBroken(host)) | |
| 232 entry->ssl().set_security_style(SECURITY_STYLE_AUTHENTICATION_BROKEN); | |
| 233 } | |
| 234 | |
| 235 // static | |
| 236 bool SSLPolicy::IsMixedContent(const GURL& url, | |
| 237 ResourceType::Type resource_type, | |
| 238 const std::string& frame_origin) { | |
| 239 //////////////////////////////////////////////////////////////////////////// | |
| 240 // WARNING: This function is called from both the IO and UI threads. Do // | |
| 241 // not touch any non-thread-safe objects! You have been warned. // | |
| 242 //////////////////////////////////////////////////////////////////////////// | |
| 243 | |
| 244 // We can't possibly have mixed content when loading the main frame. | |
| 245 if (resource_type == ResourceType::MAIN_FRAME) | |
| 246 return false; | |
| 247 | |
| 248 // If the frame doing the loading is already insecure, then we must have | |
| 249 // already dealt with whatever mixed content might be going on. | |
| 250 if (!GURL(frame_origin).SchemeIsSecure()) | |
| 251 return false; | |
| 252 | |
| 253 // We aren't worried about mixed content if we're loading an HTTPS, about, | |
| 254 // or data URL. | |
| 255 if (HasSafeScheme(url)) | |
| 256 return false; | |
| 257 | |
| 258 return true; | |
| 259 } | |
| 260 | |
| 261 void SSLPolicy::AllowMixedContent(SSLManager::MixedContentHandler* handler) { | |
| 262 std::string main_frame_host = GURL(handler->main_frame_origin()).host(); | |
| 263 handler->manager()->AllowMixedContentForHost(main_frame_host); | |
| 264 } | |
| 265 | |
| 266 //////////////////////////////////////////////////////////////////////////////// | |
| 267 // SSLBlockingPage::Delegate methods | |
| 268 | |
| 445 SSLErrorInfo SSLPolicy::GetSSLErrorInfo(SSLManager::CertError* error) { | 269 SSLErrorInfo SSLPolicy::GetSSLErrorInfo(SSLManager::CertError* error) { |
| 446 return SSLErrorInfo::CreateError( | 270 return SSLErrorInfo::CreateError( |
| 447 SSLErrorInfo::NetErrorToErrorType(error->cert_error()), | 271 SSLErrorInfo::NetErrorToErrorType(error->cert_error()), |
| 448 error->ssl_info().cert, error->request_url()); | 272 error->ssl_info().cert, error->request_url()); |
| 449 } | 273 } |
| 450 | 274 |
| 451 void SSLPolicy::OnDenyCertificate(SSLManager::CertError* error) { | 275 void SSLPolicy::OnDenyCertificate(SSLManager::CertError* error) { |
| 452 // Default behavior for rejecting a certificate. | |
| 453 error->CancelRequest(); | 276 error->CancelRequest(); |
| 454 error->manager()->DenyCertForHost(error->ssl_info().cert, | 277 error->manager()->DenyCertForHost(error->ssl_info().cert, |
| 455 error->request_url().host()); | 278 error->request_url().host()); |
| 456 } | 279 } |
| 457 | 280 |
| 458 void SSLPolicy::OnAllowCertificate(SSLManager::CertError* error) { | 281 void SSLPolicy::OnAllowCertificate(SSLManager::CertError* error) { |
| 459 // Default behavior for accepting a certificate. | |
| 460 // Note that we should not call SetMaxSecurityStyle here, because the active | |
| 461 // NavigationEntry has just been deleted (in HideInterstitialPage) and the | |
| 462 // new NavigationEntry will not be set until DidNavigate. This is ok, | |
| 463 // because the new NavigationEntry will have its max security style set | |
| 464 // within DidNavigate. | |
| 465 error->ContinueRequest(); | 282 error->ContinueRequest(); |
| 466 error->manager()->AllowCertForHost(error->ssl_info().cert, | 283 error->manager()->AllowCertForHost(error->ssl_info().cert, |
| 467 error->request_url().host()); | 284 error->request_url().host()); |
| 468 } | 285 } |
| 469 | 286 |
| 470 void SSLPolicy::OnOverridableCertError(const GURL& main_frame_url, | 287 //////////////////////////////////////////////////////////////////////////////// |
| 471 SSLManager::CertError* error) { | 288 // Certificate Error Routines |
| 289 | |
| 290 void SSLPolicy::OnOverridableCertError(SSLManager::CertError* error) { | |
| 472 if (error->resource_type() != ResourceType::MAIN_FRAME) { | 291 if (error->resource_type() != ResourceType::MAIN_FRAME) { |
| 473 // A sub-resource has a certificate error. The user doesn't really | 292 // A sub-resource has a certificate error. The user doesn't really |
| 474 // have a context for making the right decision, so block the | 293 // have a context for making the right decision, so block the |
| 475 // request hard, without an info bar to allow showing the insecure | 294 // request hard, without an info bar to allow showing the insecure |
| 476 // content. | 295 // content. |
| 477 error->DenyRequest(); | 296 error->DenyRequest(); |
| 478 return; | 297 return; |
| 479 } | 298 } |
| 480 // We need to ask the user to approve this certificate. | 299 // We need to ask the user to approve this certificate. |
| 481 ShowBlockingPage(this, error); | 300 ShowBlockingPage(this, error); |
| 482 } | 301 } |
| 483 | 302 |
| 484 void SSLPolicy::OnFatalCertError(const GURL& main_frame_url, | 303 void SSLPolicy::OnFatalCertError(SSLManager::CertError* error) { |
| 485 SSLManager::CertError* error) { | |
| 486 if (error->resource_type() != ResourceType::MAIN_FRAME) { | 304 if (error->resource_type() != ResourceType::MAIN_FRAME) { |
| 487 error->DenyRequest(); | 305 error->DenyRequest(); |
| 488 return; | 306 return; |
| 489 } | 307 } |
| 490 error->CancelRequest(); | 308 error->CancelRequest(); |
| 491 ShowErrorPage(this, error); | 309 ShowErrorPage(this, error); |
| 492 // No need to degrade our security indicators because we didn't continue. | |
| 493 } | 310 } |
| 311 | |
| 312 //////////////////////////////////////////////////////////////////////////////// | |
| 313 // State Updating | |
| 314 | |
| 315 void SSLPolicy::MarkOriginAsBroken(SSLManager* manager, | |
| 316 const std::string& origin) { | |
| 317 GURL parsed_origin(origin); | |
| 318 | |
| 319 // In particular, the origin "null" will be parsed as invalid. | |
| 320 if (!parsed_origin.is_valid() || !parsed_origin.SchemeIsSecure()) | |
| 321 return; | |
| 322 | |
| 323 manager->MarkHostAsBroken(parsed_origin.host()); | |
| 324 } | |
| 325 | |
| 326 void SSLPolicy::UpdateStateForMixedContent(SSLManager::RequestInfo* info) { | |
| 327 // The frame's origin now contains mixed content and therefore is broken. | |
| 328 MarkOriginAsBroken(info->manager(), info->frame_origin()); | |
| 329 | |
| 330 // The user approved a mixed content exception for the main frame's origin. | |
| 331 // That makes the main frame's origin broken too. | |
| 332 MarkOriginAsBroken(info->manager(), info->main_frame_origin()); | |
| 333 } | |
| 334 | |
| 335 void SSLPolicy::UpdateStateForUnsafeContent(SSLManager::RequestInfo* info) { | |
| 336 // This request as a broken cert, which means its host is broken. | |
| 337 info->manager()->MarkHostAsBroken(info->url().host()); | |
| 338 | |
| 339 if (info->resource_type() != ResourceType::MAIN_FRAME || | |
| 340 info->resource_type() != ResourceType::SUB_FRAME) { | |
| 341 // If we're loading some sort of resource into the frame, that frame is now | |
| 342 // unsafe. | |
| 343 MarkOriginAsBroken(info->manager(), info->frame_origin()); | |
| 344 } | |
| 345 | |
| 346 if (info->resource_type() != ResourceType::MAIN_FRAME) { | |
| 347 // We make the main frame unsafe even if we load an unsafe sub frame. | |
| 348 MarkOriginAsBroken(info->manager(), info->main_frame_origin()); | |
| 349 } | |
| 350 } | |
| OLD | NEW |