| 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" | 7 #include "base/singleton.h" |
| 8 #include "base/string_piece.h" | 8 #include "base/string_piece.h" |
| 9 #include "base/string_util.h" | 9 #include "base/string_util.h" |
| 10 #include "chrome/browser/cert_store.h" | 10 #include "chrome/browser/cert_store.h" |
| (...skipping 20 matching lines...) Expand all Loading... |
| 31 #if defined(OS_WIN) | 31 #if defined(OS_WIN) |
| 32 // TODO(port): port these files. | 32 // TODO(port): port these files. |
| 33 #include "chrome/browser/tab_contents/tab_contents.h" | 33 #include "chrome/browser/tab_contents/tab_contents.h" |
| 34 #elif defined(OS_POSIX) | 34 #elif defined(OS_POSIX) |
| 35 #include "chrome/common/temp_scaffolding_stubs.h" | 35 #include "chrome/common/temp_scaffolding_stubs.h" |
| 36 #endif | 36 #endif |
| 37 | 37 |
| 38 // Wrap all these helper classes in an anonymous namespace. | 38 // Wrap all these helper classes in an anonymous namespace. |
| 39 namespace { | 39 namespace { |
| 40 | 40 |
| 41 static const char kDot = '.'; | |
| 42 | |
| 43 class ShowUnsafeContentTask : public Task { | 41 class ShowUnsafeContentTask : public Task { |
| 44 public: | 42 public: |
| 45 ShowUnsafeContentTask(const GURL& main_frame_url, | 43 ShowUnsafeContentTask(const GURL& main_frame_url, |
| 46 SSLManager::ErrorHandler* error_handler); | 44 SSLManager::ErrorHandler* error_handler); |
| 47 virtual ~ShowUnsafeContentTask(); | 45 virtual ~ShowUnsafeContentTask(); |
| 48 | 46 |
| 49 virtual void Run(); | 47 virtual void Run(); |
| 50 | 48 |
| 51 private: | 49 private: |
| 52 scoped_refptr<SSLManager::ErrorHandler> error_handler_; | 50 scoped_refptr<SSLManager::ErrorHandler> error_handler_; |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 109 security_info); | 107 security_info); |
| 110 tab->controller()->GetActiveEntry()->set_page_type( | 108 tab->controller()->GetActiveEntry()->set_page_type( |
| 111 NavigationEntry::ERROR_PAGE); | 109 NavigationEntry::ERROR_PAGE); |
| 112 } | 110 } |
| 113 | 111 |
| 114 static void ShowBlockingPage(SSLPolicy* policy, SSLManager::CertError* error) { | 112 static void ShowBlockingPage(SSLPolicy* policy, SSLManager::CertError* error) { |
| 115 SSLBlockingPage* blocking_page = new SSLBlockingPage(error, policy); | 113 SSLBlockingPage* blocking_page = new SSLBlockingPage(error, policy); |
| 116 blocking_page->Show(); | 114 blocking_page->Show(); |
| 117 } | 115 } |
| 118 | 116 |
| 119 #if 0 | |
| 120 // See TODO(jcampan) below. | |
| 121 static bool IsIntranetHost(const std::string& host) { | |
| 122 const size_t dot = host.find(kDot); | |
| 123 return dot == std::string::npos || dot == host.length() - 1; | |
| 124 } | |
| 125 #endif | |
| 126 | |
| 127 class CommonNameInvalidPolicy : public SSLPolicy { | |
| 128 public: | |
| 129 static SSLPolicy* GetInstance() { | |
| 130 return Singleton<CommonNameInvalidPolicy>::get(); | |
| 131 } | |
| 132 | |
| 133 void OnCertError(const GURL& main_frame_url, | |
| 134 SSLManager::CertError* error) { | |
| 135 OnOverridableCertError(main_frame_url, error); | |
| 136 } | |
| 137 }; | |
| 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_VISIBLE_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_VISIBLE_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 | |
| 359 } // namespace | 117 } // namespace |
| 360 | 118 |
| 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() { | 119 SSLPolicy::SSLPolicy() { |
| 368 } | 120 } |
| 369 | 121 |
| 122 SSLPolicy* SSLPolicy::GetDefaultPolicy() { |
| 123 return Singleton<SSLPolicy>::get(); |
| 124 } |
| 125 |
| 370 void SSLPolicy::OnCertError(const GURL& main_frame_url, | 126 void SSLPolicy::OnCertError(const GURL& main_frame_url, |
| 371 SSLManager::CertError* error) { | 127 SSLManager::CertError* error) { |
| 372 // Default to secure behavior. | 128 // First we check if we know the policy for this error. |
| 373 error->CancelRequest(); | 129 net::X509Certificate::Policy::Judgment judgment = |
| 130 error->manager()->QueryPolicy(error->ssl_info().cert, |
| 131 error->request_url().host()); |
| 132 |
| 133 if (judgment == net::X509Certificate::Policy::ALLOWED) { |
| 134 // We've been told to allow this certificate. |
| 135 if (error->manager()->SetMaxSecurityStyle( |
| 136 SECURITY_STYLE_AUTHENTICATION_BROKEN)) { |
| 137 NotificationService::current()->Notify( |
| 138 NotificationType::SSL_VISIBLE_STATE_CHANGED, |
| 139 Source<NavigationController>(error->manager()->controller()), |
| 140 Details<NavigationEntry>( |
| 141 error->manager()->controller()->GetActiveEntry())); |
| 142 } |
| 143 error->ContinueRequest(); |
| 144 return; |
| 145 } |
| 146 |
| 147 // The judgment is either DENIED or UNKNOWN. |
| 148 // For now we handle the DENIED as the UNKNOWN, which means a blocking |
| 149 // page is shown to the user every time he comes back to the page. |
| 150 |
| 151 switch(error->cert_error()) { |
| 152 case net::ERR_CERT_COMMON_NAME_INVALID: |
| 153 case net::ERR_CERT_DATE_INVALID: |
| 154 case net::ERR_CERT_AUTHORITY_INVALID: |
| 155 OnOverridableCertError(main_frame_url, error); |
| 156 break; |
| 157 case net::ERR_CERT_NO_REVOCATION_MECHANISM: |
| 158 // Ignore this error. |
| 159 error->ContinueRequest(); |
| 160 break; |
| 161 case net::ERR_CERT_UNABLE_TO_CHECK_REVOCATION: |
| 162 // We ignore this error and display an infobar. |
| 163 error->ContinueRequest(); |
| 164 error->manager()->ShowMessage(l10n_util::GetString( |
| 165 IDS_CERT_ERROR_UNABLE_TO_CHECK_REVOCATION_INFO_BAR)); |
| 166 break; |
| 167 case net::ERR_CERT_CONTAINS_ERRORS: |
| 168 case net::ERR_CERT_REVOKED: |
| 169 case net::ERR_CERT_INVALID: |
| 170 OnFatalCertError(main_frame_url, error); |
| 171 break; |
| 172 default: |
| 173 NOTREACHED(); |
| 174 error->CancelRequest(); |
| 175 break; |
| 176 } |
| 177 } |
| 178 |
| 179 void SSLPolicy::OnMixedContent( |
| 180 NavigationController* navigation_controller, |
| 181 const GURL& main_frame_url, |
| 182 SSLManager::MixedContentHandler* mixed_content_handler) { |
| 183 PrefService* prefs = navigation_controller->profile()->GetPrefs(); |
| 184 FilterPolicy::Type filter_policy = FilterPolicy::DONT_FILTER; |
| 185 if (!mixed_content_handler->manager()-> |
| 186 CanShowInsecureContent(main_frame_url)) { |
| 187 filter_policy = FilterPolicy::FromInt( |
| 188 prefs->GetInteger(prefs::kMixedContentFiltering)); |
| 189 } |
| 190 if (filter_policy != FilterPolicy::DONT_FILTER) { |
| 191 mixed_content_handler->manager()->ShowMessageWithLink( |
| 192 l10n_util::GetString(IDS_SSL_INFO_BAR_FILTERED_CONTENT), |
| 193 l10n_util::GetString(IDS_SSL_INFO_BAR_SHOW_CONTENT), |
| 194 new ShowUnsafeContentTask(main_frame_url, mixed_content_handler)); |
| 195 } |
| 196 mixed_content_handler->StartRequest(filter_policy); |
| 197 |
| 198 NavigationEntry* entry = navigation_controller->GetLastCommittedEntry(); |
| 199 DCHECK(entry); |
| 200 // Even though we are loading the mixed-content resource, it will not be |
| 201 // included in the page when we set the policy to FILTER_ALL or |
| 202 // FILTER_ALL_EXCEPT_IMAGES (only images and they are stamped with warning |
| 203 // icons), so we don't set the mixed-content mode in these cases. |
| 204 if (filter_policy == FilterPolicy::DONT_FILTER) |
| 205 entry->ssl().set_has_mixed_content(); |
| 206 |
| 207 // Print a message indicating the mixed-contents resource in the console. |
| 208 const std::wstring& msg = l10n_util::GetStringF( |
| 209 IDS_MIXED_CONTENT_LOG_MESSAGE, |
| 210 UTF8ToWide(entry->url().spec()), |
| 211 UTF8ToWide(mixed_content_handler->request_url().spec())); |
| 212 mixed_content_handler->manager()-> |
| 213 AddMessageToConsole(msg, MESSAGE_LEVEL_WARNING); |
| 214 |
| 215 NotificationService::current()->Notify( |
| 216 NotificationType::SSL_VISIBLE_STATE_CHANGED, |
| 217 Source<NavigationController>(navigation_controller), |
| 218 Details<NavigationEntry>(entry)); |
| 374 } | 219 } |
| 375 | 220 |
| 376 void SSLPolicy::OnRequestStarted(SSLManager* manager, const GURL& url, | 221 void SSLPolicy::OnRequestStarted(SSLManager* manager, const GURL& url, |
| 377 ResourceType::Type resource_type, | 222 ResourceType::Type resource_type, |
| 378 int ssl_cert_id, int ssl_cert_status) { | 223 int ssl_cert_id, int ssl_cert_status) { |
| 379 // These schemes never leave the browser and don't require a warning. | 224 // These schemes never leave the browser and don't require a warning. |
| 380 if (url.SchemeIs(chrome::kDataScheme) || | 225 if (url.SchemeIs(chrome::kDataScheme) || |
| 381 url.SchemeIs(chrome::kJavaScriptScheme) || | 226 url.SchemeIs(chrome::kJavaScriptScheme) || |
| 382 url.SchemeIs(chrome::kAboutScheme)) | 227 url.SchemeIs(chrome::kAboutScheme)) |
| 383 return; | 228 return; |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 502 void SSLPolicy::OnFatalCertError(const GURL& main_frame_url, | 347 void SSLPolicy::OnFatalCertError(const GURL& main_frame_url, |
| 503 SSLManager::CertError* error) { | 348 SSLManager::CertError* error) { |
| 504 if (error->resource_type() != ResourceType::MAIN_FRAME) { | 349 if (error->resource_type() != ResourceType::MAIN_FRAME) { |
| 505 error->DenyRequest(); | 350 error->DenyRequest(); |
| 506 return; | 351 return; |
| 507 } | 352 } |
| 508 error->CancelRequest(); | 353 error->CancelRequest(); |
| 509 ShowErrorPage(this, error); | 354 ShowErrorPage(this, error); |
| 510 // No need to degrade our security indicators because we didn't continue. | 355 // No need to degrade our security indicators because we didn't continue. |
| 511 } | 356 } |
| OLD | NEW |