| 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 |