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

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

Issue 2350483002: Improve error pages on client certificate failures. (Closed)
Patch Set: Created 4 years, 3 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "net/socket/ssl_client_socket_impl.h" 5 #include "net/socket/ssl_client_socket_impl.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <openssl/bio.h> 8 #include <openssl/bio.h>
9 #include <openssl/bytestring.h> 9 #include <openssl/bytestring.h>
10 #include <openssl/err.h> 10 #include <openssl/err.h>
(...skipping 497 matching lines...) Expand 10 before | Expand all | Expand 10 after
508 host_and_port_(host_and_port), 508 host_and_port_(host_and_port),
509 ssl_config_(ssl_config), 509 ssl_config_(ssl_config),
510 ssl_session_cache_shard_(context.ssl_session_cache_shard), 510 ssl_session_cache_shard_(context.ssl_session_cache_shard),
511 next_handshake_state_(STATE_NONE), 511 next_handshake_state_(STATE_NONE),
512 disconnected_(false), 512 disconnected_(false),
513 npn_status_(kNextProtoUnsupported), 513 npn_status_(kNextProtoUnsupported),
514 negotiated_protocol_(kProtoUnknown), 514 negotiated_protocol_(kProtoUnknown),
515 negotiation_extension_(kExtensionUnknown), 515 negotiation_extension_(kExtensionUnknown),
516 channel_id_sent_(false), 516 channel_id_sent_(false),
517 certificate_verified_(false), 517 certificate_verified_(false),
518 certificate_requested_(false),
518 signature_result_(kNoPendingResult), 519 signature_result_(kNoPendingResult),
519 transport_security_state_(context.transport_security_state), 520 transport_security_state_(context.transport_security_state),
520 policy_enforcer_(context.ct_policy_enforcer), 521 policy_enforcer_(context.ct_policy_enforcer),
521 pkp_bypassed_(false), 522 pkp_bypassed_(false),
522 net_log_(transport_->socket()->NetLog()), 523 net_log_(transport_->socket()->NetLog()),
523 weak_factory_(this) { 524 weak_factory_(this) {
524 CHECK(cert_verifier_); 525 CHECK(cert_verifier_);
525 CHECK(transport_security_state_); 526 CHECK(transport_security_state_);
526 CHECK(cert_transparency_verifier_); 527 CHECK(cert_transparency_verifier_);
527 CHECK(policy_enforcer_); 528 CHECK(policy_enforcer_);
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
693 694
694 start_cert_verification_time_ = base::TimeTicks(); 695 start_cert_verification_time_ = base::TimeTicks();
695 696
696 npn_status_ = kNextProtoUnsupported; 697 npn_status_ = kNextProtoUnsupported;
697 negotiated_protocol_ = kProtoUnknown; 698 negotiated_protocol_ = kProtoUnknown;
698 699
699 channel_id_sent_ = false; 700 channel_id_sent_ = false;
700 tb_was_negotiated_ = false; 701 tb_was_negotiated_ = false;
701 pending_session_ = nullptr; 702 pending_session_ = nullptr;
702 certificate_verified_ = false; 703 certificate_verified_ = false;
704 certificate_requested_ = false;
703 channel_id_request_.Cancel(); 705 channel_id_request_.Cancel();
704 706
705 signature_result_ = kNoPendingResult; 707 signature_result_ = kNoPendingResult;
706 signature_.clear(); 708 signature_.clear();
707 } 709 }
708 710
709 bool SSLClientSocketImpl::IsConnected() const { 711 bool SSLClientSocketImpl::IsConnected() const {
710 // If the handshake has not yet completed. 712 // If the handshake has not yet completed.
711 if (!completed_connect_) 713 if (!completed_connect_)
712 return false; 714 return false;
(...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after
1152 return ERR_SSL_CLIENT_AUTH_CERT_NEEDED; 1154 return ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
1153 } 1155 }
1154 if (ssl_error == SSL_ERROR_WANT_PRIVATE_KEY_OPERATION) { 1156 if (ssl_error == SSL_ERROR_WANT_PRIVATE_KEY_OPERATION) {
1155 DCHECK(ssl_config_.client_private_key); 1157 DCHECK(ssl_config_.client_private_key);
1156 DCHECK_NE(kNoPendingResult, signature_result_); 1158 DCHECK_NE(kNoPendingResult, signature_result_);
1157 next_handshake_state_ = STATE_HANDSHAKE; 1159 next_handshake_state_ = STATE_HANDSHAKE;
1158 return ERR_IO_PENDING; 1160 return ERR_IO_PENDING;
1159 } 1161 }
1160 1162
1161 OpenSSLErrorInfo error_info; 1163 OpenSSLErrorInfo error_info;
1162 net_error = MapOpenSSLErrorWithDetails(ssl_error, err_tracer, &error_info); 1164 net_error = MapLastOpenSSLError(ssl_error, err_tracer, &error_info);
1163 if (net_error == ERR_IO_PENDING) { 1165 if (net_error == ERR_IO_PENDING) {
1164 // If not done, stay in this state 1166 // If not done, stay in this state
1165 next_handshake_state_ = STATE_HANDSHAKE; 1167 next_handshake_state_ = STATE_HANDSHAKE;
1166 return ERR_IO_PENDING; 1168 return ERR_IO_PENDING;
1167 } 1169 }
1168 1170
1169 LOG(ERROR) << "handshake failed; returned " << rv << ", SSL error code " 1171 LOG(ERROR) << "handshake failed; returned " << rv << ", SSL error code "
1170 << ssl_error << ", net_error " << net_error; 1172 << ssl_error << ", net_error " << net_error;
1171 net_log_.AddEvent( 1173 net_log_.AddEvent(
1172 NetLogEventType::SSL_HANDSHAKE_ERROR, 1174 NetLogEventType::SSL_HANDSHAKE_ERROR,
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after
1563 pending_read_error_ = 0; 1565 pending_read_error_ = 0;
1564 } else if (pending_read_ssl_error_ == SSL_ERROR_WANT_X509_LOOKUP && 1566 } else if (pending_read_ssl_error_ == SSL_ERROR_WANT_X509_LOOKUP &&
1565 !ssl_config_.send_client_cert) { 1567 !ssl_config_.send_client_cert) {
1566 pending_read_error_ = ERR_SSL_CLIENT_AUTH_CERT_NEEDED; 1568 pending_read_error_ = ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
1567 } else if (pending_read_ssl_error_ == 1569 } else if (pending_read_ssl_error_ ==
1568 SSL_ERROR_WANT_PRIVATE_KEY_OPERATION) { 1570 SSL_ERROR_WANT_PRIVATE_KEY_OPERATION) {
1569 DCHECK(ssl_config_.client_private_key); 1571 DCHECK(ssl_config_.client_private_key);
1570 DCHECK_NE(kNoPendingResult, signature_result_); 1572 DCHECK_NE(kNoPendingResult, signature_result_);
1571 pending_read_error_ = ERR_IO_PENDING; 1573 pending_read_error_ = ERR_IO_PENDING;
1572 } else { 1574 } else {
1573 pending_read_error_ = MapOpenSSLErrorWithDetails( 1575 pending_read_error_ = MapLastOpenSSLError(
1574 pending_read_ssl_error_, err_tracer, &pending_read_error_info_); 1576 pending_read_ssl_error_, err_tracer, &pending_read_error_info_);
1575 } 1577 }
1576 1578
1577 // Many servers do not reliably send a close_notify alert when shutting down 1579 // Many servers do not reliably send a close_notify alert when shutting down
1578 // a connection, and instead terminate the TCP connection. This is reported 1580 // a connection, and instead terminate the TCP connection. This is reported
1579 // as ERR_CONNECTION_CLOSED. Because of this, map the unclean shutdown to a 1581 // as ERR_CONNECTION_CLOSED. Because of this, map the unclean shutdown to a
1580 // graceful EOF, instead of treating it as an error as it should be. 1582 // graceful EOF, instead of treating it as an error as it should be.
1581 if (pending_read_error_ == ERR_CONNECTION_CLOSED) 1583 if (pending_read_error_ == ERR_CONNECTION_CLOSED)
1582 pending_read_error_ = 0; 1584 pending_read_error_ = 0;
1583 } 1585 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1622 if (rv >= 0) { 1624 if (rv >= 0) {
1623 net_log_.AddByteTransferEvent(NetLogEventType::SSL_SOCKET_BYTES_SENT, rv, 1625 net_log_.AddByteTransferEvent(NetLogEventType::SSL_SOCKET_BYTES_SENT, rv,
1624 user_write_buf_->data()); 1626 user_write_buf_->data());
1625 return rv; 1627 return rv;
1626 } 1628 }
1627 1629
1628 int ssl_error = SSL_get_error(ssl_, rv); 1630 int ssl_error = SSL_get_error(ssl_, rv);
1629 if (ssl_error == SSL_ERROR_WANT_PRIVATE_KEY_OPERATION) 1631 if (ssl_error == SSL_ERROR_WANT_PRIVATE_KEY_OPERATION)
1630 return ERR_IO_PENDING; 1632 return ERR_IO_PENDING;
1631 OpenSSLErrorInfo error_info; 1633 OpenSSLErrorInfo error_info;
1632 int net_error = 1634 int net_error = MapLastOpenSSLError(ssl_error, err_tracer, &error_info);
1633 MapOpenSSLErrorWithDetails(ssl_error, err_tracer, &error_info);
1634 1635
1635 if (net_error != ERR_IO_PENDING) { 1636 if (net_error != ERR_IO_PENDING) {
1636 net_log_.AddEvent( 1637 net_log_.AddEvent(
1637 NetLogEventType::SSL_WRITE_ERROR, 1638 NetLogEventType::SSL_WRITE_ERROR,
1638 CreateNetLogOpenSSLErrorCallback(net_error, ssl_error, error_info)); 1639 CreateNetLogOpenSSLErrorCallback(net_error, ssl_error, error_info));
1639 } 1640 }
1640 return net_error; 1641 return net_error;
1641 } 1642 }
1642 1643
1643 void SSLClientSocketImpl::PumpReadWriteEvents() { 1644 void SSLClientSocketImpl::PumpReadWriteEvents() {
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
1847 return ERR_CERTIFICATE_TRANSPARENCY_REQUIRED; 1848 return ERR_CERTIFICATE_TRANSPARENCY_REQUIRED;
1848 } 1849 }
1849 1850
1850 return OK; 1851 return OK;
1851 } 1852 }
1852 1853
1853 int SSLClientSocketImpl::ClientCertRequestCallback(SSL* ssl) { 1854 int SSLClientSocketImpl::ClientCertRequestCallback(SSL* ssl) {
1854 DCHECK(ssl == ssl_); 1855 DCHECK(ssl == ssl_);
1855 1856
1856 net_log_.AddEvent(NetLogEventType::SSL_CLIENT_CERT_REQUESTED); 1857 net_log_.AddEvent(NetLogEventType::SSL_CLIENT_CERT_REQUESTED);
1858 certificate_requested_ = true;
1857 1859
1858 // Clear any currently configured certificates. 1860 // Clear any currently configured certificates.
1859 SSL_certs_clear(ssl_); 1861 SSL_certs_clear(ssl_);
1860 1862
1861 #if defined(OS_IOS) 1863 #if defined(OS_IOS)
1862 // TODO(droger): Support client auth on iOS. See http://crbug.com/145954). 1864 // TODO(droger): Support client auth on iOS. See http://crbug.com/145954).
1863 LOG(WARNING) << "Client auth is not supported"; 1865 LOG(WARNING) << "Client auth is not supported";
1864 #else // !defined(OS_IOS) 1866 #else // !defined(OS_IOS)
1865 if (!ssl_config_.send_client_cert) { 1867 if (!ssl_config_.send_client_cert) {
1866 // First pass: we know that a client certificate is needed, but we do not 1868 // First pass: we know that a client certificate is needed, but we do not
(...skipping 514 matching lines...) Expand 10 before | Expand all | Expand 10 after
2381 supported = CLIENT_ONLY; 2383 supported = CLIENT_ONLY;
2382 } 2384 }
2383 UMA_HISTOGRAM_ENUMERATION("DomainBoundCerts.Support", supported, 2385 UMA_HISTOGRAM_ENUMERATION("DomainBoundCerts.Support", supported,
2384 CHANNEL_ID_USAGE_MAX); 2386 CHANNEL_ID_USAGE_MAX);
2385 } 2387 }
2386 2388
2387 bool SSLClientSocketImpl::IsChannelIDEnabled() const { 2389 bool SSLClientSocketImpl::IsChannelIDEnabled() const {
2388 return ssl_config_.channel_id_enabled && channel_id_service_; 2390 return ssl_config_.channel_id_enabled && channel_id_service_;
2389 } 2391 }
2390 2392
2393 int SSLClientSocketImpl::MapLastOpenSSLError(
2394 int ssl_error,
2395 const crypto::OpenSSLErrStackTracer& tracer,
2396 OpenSSLErrorInfo* info) {
2397 int net_error = MapOpenSSLErrorWithDetails(ssl_error, tracer, info);
2398
2399 if (ssl_error == SSL_ERROR_SSL &&
2400 ERR_GET_LIB(info->error_code) == ERR_LIB_SSL) {
2401 // TLS does not provide an alert for missing client certificates, so most
2402 // servers send a generic handshake_failure alert. Detect this case by
2403 // checking if we have received a CertificateRequest but sent no
2404 // certificate. See https://crbug.com/646567.
2405 if (ERR_GET_REASON(info->error_code) ==
2406 SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE &&
2407 certificate_requested_ && ssl_config_.send_client_cert &&
2408 !ssl_config_.client_cert) {
2409 net_error = ERR_BAD_SSL_CLIENT_AUTH_CERT;
2410 }
2411
2412 // Per spec, access_denied is only for client-certificate-based access
2413 // control, but some buggy firewalls use it when blocking a page. To avoid a
2414 // confusing error, map it to a generic protocol error if no
2415 // CertificateRequest was sent. See https://crbug.com/630883.
2416 if (ERR_GET_REASON(info->error_code) == SSL_R_TLSV1_ALERT_ACCESS_DENIED &&
2417 !certificate_requested_) {
2418 net_error = ERR_SSL_PROTOCOL_ERROR;
2419 }
2420 }
2421
2422 return net_error;
2423 }
2424
2391 } // namespace net 2425 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698