OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 // This file includes code SSLClientSocketNSS::DoVerifyCertComplete() derived | 5 // This file includes code SSLClientSocketNSS::DoVerifyCertComplete() derived |
6 // from AuthCertificateCallback() in | 6 // from AuthCertificateCallback() in |
7 // mozilla/security/manager/ssl/src/nsNSSCallbacks.cpp. | 7 // mozilla/security/manager/ssl/src/nsNSSCallbacks.cpp. |
8 | 8 |
9 /* ***** BEGIN LICENSE BLOCK ***** | 9 /* ***** BEGIN LICENSE BLOCK ***** |
10 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 | 10 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
(...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
444 user_read_buf_len_(0), | 444 user_read_buf_len_(0), |
445 user_write_buf_len_(0), | 445 user_write_buf_len_(0), |
446 server_cert_nss_(NULL), | 446 server_cert_nss_(NULL), |
447 server_cert_verify_result_(NULL), | 447 server_cert_verify_result_(NULL), |
448 ssl_connection_status_(0), | 448 ssl_connection_status_(0), |
449 client_auth_cert_needed_(false), | 449 client_auth_cert_needed_(false), |
450 cert_verifier_(cert_verifier), | 450 cert_verifier_(cert_verifier), |
451 handshake_callback_called_(false), | 451 handshake_callback_called_(false), |
452 completed_handshake_(false), | 452 completed_handshake_(false), |
453 eset_mitm_detected_(false), | 453 eset_mitm_detected_(false), |
| 454 kaspersky_mitm_detected_(false), |
454 predicted_cert_chain_correct_(false), | 455 predicted_cert_chain_correct_(false), |
455 next_handshake_state_(STATE_NONE), | 456 next_handshake_state_(STATE_NONE), |
456 nss_fd_(NULL), | 457 nss_fd_(NULL), |
457 nss_bufs_(NULL), | 458 nss_bufs_(NULL), |
458 net_log_(transport_socket->socket()->NetLog()), | 459 net_log_(transport_socket->socket()->NetLog()), |
459 ssl_host_info_(ssl_host_info), | 460 ssl_host_info_(ssl_host_info), |
460 dns_cert_checker_(dns_ctx), | 461 dns_cert_checker_(dns_ctx), |
461 valid_thread_id_(base::kInvalidThreadId) { | 462 valid_thread_id_(base::kInvalidThreadId) { |
462 EnterFunction(""); | 463 EnterFunction(""); |
463 } | 464 } |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
637 server_cert_ = NULL; | 638 server_cert_ = NULL; |
638 if (server_cert_nss_) { | 639 if (server_cert_nss_) { |
639 CERT_DestroyCertificate(server_cert_nss_); | 640 CERT_DestroyCertificate(server_cert_nss_); |
640 server_cert_nss_ = NULL; | 641 server_cert_nss_ = NULL; |
641 } | 642 } |
642 local_server_cert_verify_result_.Reset(); | 643 local_server_cert_verify_result_.Reset(); |
643 server_cert_verify_result_ = NULL; | 644 server_cert_verify_result_ = NULL; |
644 ssl_connection_status_ = 0; | 645 ssl_connection_status_ = 0; |
645 completed_handshake_ = false; | 646 completed_handshake_ = false; |
646 eset_mitm_detected_ = false; | 647 eset_mitm_detected_ = false; |
| 648 kaspersky_mitm_detected_ = false; |
647 start_cert_verification_time_ = base::TimeTicks(); | 649 start_cert_verification_time_ = base::TimeTicks(); |
648 predicted_cert_chain_correct_ = false; | 650 predicted_cert_chain_correct_ = false; |
649 nss_bufs_ = NULL; | 651 nss_bufs_ = NULL; |
650 client_certs_.clear(); | 652 client_certs_.clear(); |
651 client_auth_cert_needed_ = false; | 653 client_auth_cert_needed_ = false; |
652 | 654 |
653 LeaveFunction(""); | 655 LeaveFunction(""); |
654 } | 656 } |
655 | 657 |
656 bool SSLClientSocketNSS::IsConnected() const { | 658 bool SSLClientSocketNSS::IsConnected() const { |
(...skipping 727 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1384 // so that we won't try to resume the non-client-authenticated session in | 1386 // so that we won't try to resume the non-client-authenticated session in |
1385 // the next handshake. This will cause the server to ask for a client | 1387 // the next handshake. This will cause the server to ask for a client |
1386 // cert again. | 1388 // cert again. |
1387 if (rv == SECSuccess && SSL_InvalidateSession(nss_fd_) != SECSuccess) { | 1389 if (rv == SECSuccess && SSL_InvalidateSession(nss_fd_) != SECSuccess) { |
1388 LOG(WARNING) << "Couldn't invalidate SSL session: " << PR_GetError(); | 1390 LOG(WARNING) << "Couldn't invalidate SSL session: " << PR_GetError(); |
1389 } | 1391 } |
1390 } else if (rv == SECSuccess) { | 1392 } else if (rv == SECSuccess) { |
1391 if (handshake_callback_called_) { | 1393 if (handshake_callback_called_) { |
1392 if (eset_mitm_detected_) { | 1394 if (eset_mitm_detected_) { |
1393 net_error = ERR_ESET_ANTI_VIRUS_SSL_INTERCEPTION; | 1395 net_error = ERR_ESET_ANTI_VIRUS_SSL_INTERCEPTION; |
| 1396 } else if (kaspersky_mitm_detected_) { |
| 1397 net_error = ERR_KASPERSKY_ANTI_VIRUS_SSL_INTERCEPTION; |
1394 } else { | 1398 } else { |
1395 // We need to see if the predicted certificate chain (in | 1399 // We need to see if the predicted certificate chain (in |
1396 // |ssl_host_info_->state().certs) matches the actual certificate chain | 1400 // |ssl_host_info_->state().certs) matches the actual certificate chain |
1397 // before we call SaveSSLHostInfo, as that will update | 1401 // before we call SaveSSLHostInfo, as that will update |
1398 // |ssl_host_info_|. | 1402 // |ssl_host_info_|. |
1399 if (ssl_host_info_.get() && !ssl_host_info_->state().certs.empty()) { | 1403 if (ssl_host_info_.get() && !ssl_host_info_->state().certs.empty()) { |
1400 PeerCertificateChain certs(nss_fd_); | 1404 PeerCertificateChain certs(nss_fd_); |
1401 const SSLHostInfo::State& state = ssl_host_info_->state(); | 1405 const SSLHostInfo::State& state = ssl_host_info_->state(); |
1402 predicted_cert_chain_correct_ = certs.size() == state.certs.size(); | 1406 predicted_cert_chain_correct_ = certs.size() == state.certs.size(); |
1403 if (predicted_cert_chain_correct_) { | 1407 if (predicted_cert_chain_correct_) { |
(...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1866 #ifdef SSL_ENABLE_FALSE_START | 1870 #ifdef SSL_ENABLE_FALSE_START |
1867 // In the event that we are False Starting this connection, we wish to send | 1871 // In the event that we are False Starting this connection, we wish to send |
1868 // out the Finished message and first application data record in the same | 1872 // out the Finished message and first application data record in the same |
1869 // packet. This prevents non-determinism when talking to False Start | 1873 // packet. This prevents non-determinism when talking to False Start |
1870 // intolerant servers which, otherwise, might see the two messages in | 1874 // intolerant servers which, otherwise, might see the two messages in |
1871 // different reads or not, depending on network conditions. | 1875 // different reads or not, depending on network conditions. |
1872 PRBool false_start = 0; | 1876 PRBool false_start = 0; |
1873 SECStatus rv = SSL_OptionGet(socket, SSL_ENABLE_FALSE_START, &false_start); | 1877 SECStatus rv = SSL_OptionGet(socket, SSL_ENABLE_FALSE_START, &false_start); |
1874 DCHECK_EQ(SECSuccess, rv); | 1878 DCHECK_EQ(SECSuccess, rv); |
1875 | 1879 |
1876 if (false_start) { | 1880 SSLClientSocketNSS* that = reinterpret_cast<SSLClientSocketNSS*>(arg); |
1877 SSLClientSocketNSS* that = reinterpret_cast<SSLClientSocketNSS*>(arg); | 1881 CERTCertificate* cert = SSL_PeerCertificate(that->nss_fd_); |
| 1882 if (cert) { |
| 1883 char* common_name = CERT_GetCommonName(&cert->issuer); |
| 1884 if (common_name) { |
| 1885 if (false_start && strcmp(common_name, "ESET_RootSslCert") == 0) |
| 1886 // ESET anti-virus is capable of intercepting HTTPS connections on |
| 1887 // Windows. However, it is False Start intolerant and causes the |
| 1888 // connections to hang forever. We detect ESET by the issuer of the |
| 1889 // leaf certificate and set a flag to return a specific error, giving |
| 1890 // the user instructions for reconfiguring ESET. |
| 1891 that->eset_mitm_detected_ = true; |
| 1892 if (strcmp(common_name, |
| 1893 "Kaspersky Anti-Virus personal root certificate") == 0) { |
| 1894 // Kaspersky has an unknown intolerance to our HTTPS handshakes and so |
| 1895 // we detect and give a more helpful error message. |
| 1896 that->kaspersky_mitm_detected_ = true; |
| 1897 } |
| 1898 if (false_start && |
| 1899 strcmp(common_name, "ContentWatch Root Certificate Authority") == 0) { |
| 1900 // This is NetNanny. NetNanny are updating their product so we |
| 1901 // silently disable False Start for now. |
| 1902 rv = SSL_OptionSet(socket, SSL_ENABLE_FALSE_START, PR_FALSE); |
| 1903 DCHECK_EQ(SECSuccess, rv); |
| 1904 false_start = 0; |
| 1905 } |
| 1906 PORT_Free(common_name); |
| 1907 } |
| 1908 CERT_DestroyCertificate(cert); |
| 1909 } |
1878 | 1910 |
1879 // ESET anti-virus is capable of intercepting HTTPS connections on Windows. | 1911 if (false_start && !that->handshake_callback_called_) { |
1880 // However, it is False Start intolerant and causes the connections to hang | 1912 that->corked_ = true; |
1881 // forever. We detect ESET by the issuer of the leaf certificate and set a | 1913 that->uncork_timer_.Start( |
1882 // flag to return a specific error, giving the user instructions for | 1914 base::TimeDelta::FromMilliseconds(kCorkTimeoutMs), |
1883 // reconfiguring ESET. | 1915 that, &SSLClientSocketNSS::UncorkAfterTimeout); |
1884 CERTCertificate* cert = SSL_PeerCertificate(that->nss_fd_); | |
1885 if (cert) { | |
1886 char* common_name = CERT_GetCommonName(&cert->issuer); | |
1887 if (common_name) { | |
1888 if (strcmp(common_name, "ESET_RootSslCert") == 0) | |
1889 that->eset_mitm_detected_ = true; | |
1890 if (strcmp(common_name, | |
1891 "ContentWatch Root Certificate Authority") == 0) { | |
1892 // This is NetNanny. NetNanny are updating their product so we | |
1893 // silently disable False Start for now. | |
1894 rv = SSL_OptionSet(socket, SSL_ENABLE_FALSE_START, PR_FALSE); | |
1895 DCHECK_EQ(SECSuccess, rv); | |
1896 false_start = 0; | |
1897 } | |
1898 PORT_Free(common_name); | |
1899 } | |
1900 CERT_DestroyCertificate(cert); | |
1901 } | |
1902 | |
1903 if (false_start && !that->handshake_callback_called_) { | |
1904 that->corked_ = true; | |
1905 that->uncork_timer_.Start( | |
1906 base::TimeDelta::FromMilliseconds(kCorkTimeoutMs), | |
1907 that, &SSLClientSocketNSS::UncorkAfterTimeout); | |
1908 } | |
1909 } | 1916 } |
1910 #endif | 1917 #endif |
1911 | 1918 |
1912 // Tell NSS to not verify the certificate. | 1919 // Tell NSS to not verify the certificate. |
1913 return SECSuccess; | 1920 return SECSuccess; |
1914 } | 1921 } |
1915 | 1922 |
1916 #if defined(NSS_PLATFORM_CLIENT_AUTH) | 1923 #if defined(NSS_PLATFORM_CLIENT_AUTH) |
1917 // static | 1924 // static |
1918 // NSS calls this if a client certificate is needed. | 1925 // NSS calls this if a client certificate is needed. |
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2256 valid_thread_id_ = base::PlatformThread::CurrentId(); | 2263 valid_thread_id_ = base::PlatformThread::CurrentId(); |
2257 } | 2264 } |
2258 | 2265 |
2259 bool SSLClientSocketNSS::CalledOnValidThread() const { | 2266 bool SSLClientSocketNSS::CalledOnValidThread() const { |
2260 EnsureThreadIdAssigned(); | 2267 EnsureThreadIdAssigned(); |
2261 base::AutoLock auto_lock(lock_); | 2268 base::AutoLock auto_lock(lock_); |
2262 return valid_thread_id_ == base::PlatformThread::CurrentId(); | 2269 return valid_thread_id_ == base::PlatformThread::CurrentId(); |
2263 } | 2270 } |
2264 | 2271 |
2265 } // namespace net | 2272 } // namespace net |
OLD | NEW |