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

Unified Diff: net/socket/ssl_client_socket_impl.cc

Issue 2350483002: Improve error pages on client certificate failures. (Closed)
Patch Set: curly quotes 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/socket/ssl_client_socket_impl.h ('k') | net/socket/ssl_client_socket_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/socket/ssl_client_socket_impl.cc
diff --git a/net/socket/ssl_client_socket_impl.cc b/net/socket/ssl_client_socket_impl.cc
index 117a574a1c03e8a6bade533ddb088d48809fdfe9..c60140b5d4fdd18220cd27b4f769d079060419a2 100644
--- a/net/socket/ssl_client_socket_impl.cc
+++ b/net/socket/ssl_client_socket_impl.cc
@@ -499,6 +499,7 @@ SSLClientSocketImpl::SSLClientSocketImpl(
negotiated_protocol_(kProtoUnknown),
channel_id_sent_(false),
certificate_verified_(false),
+ certificate_requested_(false),
signature_result_(kNoPendingResult),
transport_security_state_(context.transport_security_state),
policy_enforcer_(context.ct_policy_enforcer),
@@ -680,6 +681,7 @@ void SSLClientSocketImpl::Disconnect() {
tb_was_negotiated_ = false;
pending_session_ = nullptr;
certificate_verified_ = false;
+ certificate_requested_ = false;
channel_id_request_.Cancel();
signature_result_ = kNoPendingResult;
@@ -1135,7 +1137,7 @@ int SSLClientSocketImpl::DoHandshake() {
}
OpenSSLErrorInfo error_info;
- net_error = MapOpenSSLErrorWithDetails(ssl_error, err_tracer, &error_info);
+ net_error = MapLastOpenSSLError(ssl_error, err_tracer, &error_info);
if (net_error == ERR_IO_PENDING) {
// If not done, stay in this state
next_handshake_state_ = STATE_HANDSHAKE;
@@ -1537,7 +1539,7 @@ int SSLClientSocketImpl::DoPayloadRead() {
DCHECK_NE(kNoPendingResult, signature_result_);
pending_read_error_ = ERR_IO_PENDING;
} else {
- pending_read_error_ = MapOpenSSLErrorWithDetails(
+ pending_read_error_ = MapLastOpenSSLError(
pending_read_ssl_error_, err_tracer, &pending_read_error_info_);
}
@@ -1596,8 +1598,7 @@ int SSLClientSocketImpl::DoPayloadWrite() {
if (ssl_error == SSL_ERROR_WANT_PRIVATE_KEY_OPERATION)
return ERR_IO_PENDING;
OpenSSLErrorInfo error_info;
- int net_error =
- MapOpenSSLErrorWithDetails(ssl_error, err_tracer, &error_info);
+ int net_error = MapLastOpenSSLError(ssl_error, err_tracer, &error_info);
if (net_error != ERR_IO_PENDING) {
net_log_.AddEvent(
@@ -1821,6 +1822,7 @@ int SSLClientSocketImpl::ClientCertRequestCallback(SSL* ssl) {
DCHECK(ssl == ssl_);
net_log_.AddEvent(NetLogEventType::SSL_CLIENT_CERT_REQUESTED);
+ certificate_requested_ = true;
// Clear any currently configured certificates.
SSL_certs_clear(ssl_);
@@ -2288,4 +2290,36 @@ bool SSLClientSocketImpl::IsChannelIDEnabled() const {
return ssl_config_.channel_id_enabled && channel_id_service_;
}
+int SSLClientSocketImpl::MapLastOpenSSLError(
+ int ssl_error,
+ const crypto::OpenSSLErrStackTracer& tracer,
+ OpenSSLErrorInfo* info) {
+ int net_error = MapOpenSSLErrorWithDetails(ssl_error, tracer, info);
+
+ if (ssl_error == SSL_ERROR_SSL &&
+ ERR_GET_LIB(info->error_code) == ERR_LIB_SSL) {
+ // TLS does not provide an alert for missing client certificates, so most
+ // servers send a generic handshake_failure alert. Detect this case by
+ // checking if we have received a CertificateRequest but sent no
+ // certificate. See https://crbug.com/646567.
+ if (ERR_GET_REASON(info->error_code) ==
+ SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE &&
+ certificate_requested_ && ssl_config_.send_client_cert &&
+ !ssl_config_.client_cert) {
+ net_error = ERR_BAD_SSL_CLIENT_AUTH_CERT;
+ }
+
+ // Per spec, access_denied is only for client-certificate-based access
+ // control, but some buggy firewalls use it when blocking a page. To avoid a
+ // confusing error, map it to a generic protocol error if no
+ // CertificateRequest was sent. See https://crbug.com/630883.
+ if (ERR_GET_REASON(info->error_code) == SSL_R_TLSV1_ALERT_ACCESS_DENIED &&
+ !certificate_requested_) {
+ net_error = ERR_SSL_PROTOCOL_ERROR;
+ }
+ }
+
+ return net_error;
+}
+
} // namespace net
« no previous file with comments | « net/socket/ssl_client_socket_impl.h ('k') | net/socket/ssl_client_socket_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698