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

Unified Diff: net/socket/ssl_client_socket_mac.cc

Issue 165191: Implement SSL certificate error handling on the Mac. If the user gives... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Upload before checkin Created 11 years, 4 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_mac.h ('k') | net/socket/ssl_client_socket_nss.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/socket/ssl_client_socket_mac.cc
===================================================================
--- net/socket/ssl_client_socket_mac.cc (revision 23320)
+++ net/socket/ssl_client_socket_mac.cc (working copy)
@@ -241,6 +241,24 @@
}
}
+// Returns the server's certificate. The caller must release a reference
+// to the return value when done. Returns NULL on failure.
+X509Certificate* GetServerCert(SSLContextRef ssl_context) {
+ CFArrayRef certs;
+ OSStatus status = SSLCopyPeerCertificates(ssl_context, &certs);
+ if (status != noErr)
+ return NULL;
+
+ DCHECK_GT(CFArrayGetCount(certs), 0);
+
+ SecCertificateRef server_cert = static_cast<SecCertificateRef>(
+ const_cast<void*>(CFArrayGetValueAtIndex(certs, 0)));
+ CFRetain(server_cert);
+ CFRelease(certs);
+ return X509Certificate::CreateFromHandle(
+ server_cert, X509Certificate::SOURCE_FROM_NETWORK);
+}
+
} // namespace
//-----------------------------------------------------------------------------
@@ -305,11 +323,24 @@
if (status)
return NetErrorFromOSStatus(status);
- status = SSLSetPeerDomainName(ssl_context_, hostname_.c_str(),
- hostname_.length());
- if (status)
- return NetErrorFromOSStatus(status);
+ if (ssl_config_.allowed_bad_certs.empty()) {
+ // We're going to use the default certificate verification that the system
+ // does, and accept its answer for the cert status.
+ status = SSLSetPeerDomainName(ssl_context_, hostname_.data(),
+ hostname_.length());
+ if (status)
+ return NetErrorFromOSStatus(status);
+ // TODO(wtc): for now, always check revocation.
+ server_cert_status_ = CERT_STATUS_REV_CHECKING_ENABLED;
+ } else {
+ // Disable certificate chain validation. We will only allow the certs in
+ // ssl_config_.allowed_bad_certs.
+ status = SSLSetEnableCertVerify(ssl_context_, false);
+ if (status)
+ return NetErrorFromOSStatus(status);
+ }
+
next_state_ = STATE_HANDSHAKE;
int rv = DoLoop(OK);
if (rv == ERR_IO_PENDING)
@@ -394,26 +425,14 @@
ssl_info->Reset();
// set cert
- CFArrayRef certs;
- OSStatus status = SSLCopyPeerCertificates(ssl_context_, &certs);
- if (!status) {
- DCHECK(CFArrayGetCount(certs) > 0);
+ ssl_info->cert = server_cert_;
- SecCertificateRef client_cert =
- static_cast<SecCertificateRef>(
- const_cast<void*>(CFArrayGetValueAtIndex(certs, 0)));
- CFRetain(client_cert);
- ssl_info->cert = X509Certificate::CreateFromHandle(
- client_cert, X509Certificate::SOURCE_FROM_NETWORK);
- CFRelease(certs);
- }
-
// update status
ssl_info->cert_status = server_cert_status_;
// security info
SSLCipherSuite suite;
- status = SSLGetNegotiatedCipher(ssl_context_, &suite);
+ OSStatus status = SSLGetNegotiatedCipher(ssl_context_, &suite);
if (!status)
ssl_info->security_bits = KeySizeOfCipherSuite(suite);
}
@@ -485,26 +504,36 @@
int SSLClientSocketMac::DoHandshake() {
OSStatus status = SSLHandshake(ssl_context_);
+ int net_error = NetErrorFromOSStatus(status);
- if (status == errSSLWouldBlock)
+ if (status == errSSLWouldBlock) {
next_state_ = STATE_HANDSHAKE;
+ } else if (status == noErr) {
+ completed_handshake_ = true; // We have a connection.
- if (status == noErr)
- completed_handshake_ = true;
+ server_cert_ = GetServerCert(ssl_context_);
+ DCHECK(server_cert_);
+ if (!ssl_config_.allowed_bad_certs.empty()) {
+ // Check server_cert_ because SecureTransport didn't verify it.
+ // TODO(wtc): If server_cert_ is not one of the allowed bad certificates,
+ // we should verify server_cert_ ourselves. Since we don't know how to
+ // do that yet, treat it as an invalid certificate.
+ net_error = ERR_CERT_INVALID;
+ server_cert_status_ |= CERT_STATUS_INVALID;
- int net_error = NetErrorFromOSStatus(status);
-
- // At this point we have a connection. For now, we're going to use the default
- // certificate verification that the system does, and accept its answer for
- // the cert status. In the future, we'll need to call SSLSetEnableCertVerify
- // to disable cert verification and do the verification ourselves. This allows
- // very fine-grained control over what we'll accept for certification.
- // TODO(avi): ditto
-
- // TODO(wtc): for now, always check revocation.
- server_cert_status_ = CERT_STATUS_REV_CHECKING_ENABLED;
- if (net_error)
+ for (size_t i = 0; i < ssl_config_.allowed_bad_certs.size(); ++i) {
+ if (server_cert_ == ssl_config_.allowed_bad_certs[i].cert) {
+ net_error = OK;
+ server_cert_status_ = ssl_config_.allowed_bad_certs[i].cert_status;
+ break;
+ }
+ }
+ }
+ } else if (IsCertStatusError(net_error)) {
+ server_cert_ = GetServerCert(ssl_context_);
+ DCHECK(server_cert_);
server_cert_status_ |= MapNetErrorToCertStatus(net_error);
+ }
return net_error;
}
« no previous file with comments | « net/socket/ssl_client_socket_mac.h ('k') | net/socket/ssl_client_socket_nss.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698