Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(542)

Side by Side Diff: net/socket/ssl_client_socket_nss.cc

Issue 7275027: Detect Kaspersky SSL MITM and give a helpful error message. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: ... Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/socket/ssl_client_socket_nss.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « net/socket/ssl_client_socket_nss.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698