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

Unified Diff: net/socket/ssl_client_socket_mac.cc

Issue 174102: Enable SSLClientSocketTest unit tests on Mac OS X by implementing our own cer... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' 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
Index: net/socket/ssl_client_socket_mac.cc
===================================================================
--- net/socket/ssl_client_socket_mac.cc (revision 24466)
+++ net/socket/ssl_client_socket_mac.cc (working copy)
@@ -4,8 +4,10 @@
#include "net/socket/ssl_client_socket_mac.h"
+#include "base/scoped_cftyperef.h"
#include "base/singleton.h"
#include "base/string_util.h"
+#include "net/base/cert_verifier.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/base/ssl_info.h"
@@ -276,7 +278,6 @@
user_callback_(NULL),
next_state_(STATE_NONE),
next_io_state_(STATE_NONE),
- server_cert_status_(0),
completed_handshake_(false),
ssl_context_(NULL),
pending_send_error_(OK),
@@ -325,24 +326,12 @@
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);
+ // Disable certificate verification within Secure Transport; we'll
+ // be handling that ourselves.
+ status = SSLSetEnableCertVerify(ssl_context_, false);
+ 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)
@@ -430,7 +419,7 @@
ssl_info->cert = server_cert_;
// update status
- ssl_info->cert_status = server_cert_status_;
+ ssl_info->cert_status = server_cert_verify_result_.cert_status;
// security info
SSLCipherSuite suite;
@@ -483,6 +472,14 @@
// Do the SSL/TLS handshake.
rv = DoHandshake();
break;
+ case STATE_VERIFY_CERT:
+ // Kick off server certificate validation.
+ rv = DoVerifyCert();
+ break;
+ case STATE_VERIFY_CERT_COMPLETE:
+ // Check the results of the server certificate validation.
+ rv = DoVerifyCertComplete(rv);
+ break;
case STATE_READ_COMPLETE:
// A read off the network is complete; do the paperwork.
rv = DoReadComplete(rv);
@@ -506,40 +503,62 @@
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) {
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;
+ if (!server_cert_)
+ return ERR_UNEXPECTED;
+ next_state_ = STATE_VERIFY_CERT;
+ }
- 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 (IsCertificateError(net_error)) {
- server_cert_ = GetServerCert(ssl_context_);
- DCHECK(server_cert_);
- server_cert_status_ |= MapNetErrorToCertStatus(net_error);
+ return NetErrorFromOSStatus(status);
+}
+
+int SSLClientSocketMac::DoVerifyCert() {
+ next_state_ = STATE_VERIFY_CERT_COMPLETE;
+
+ if (!server_cert_)
+ return ERR_UNEXPECTED;
+
+ // Add each of the intermediate certificates in the server's chain to the
+ // server's X509Certificate object. This makes them available to
+ // X509Certificate::Verify() for chain building.
+ CFArrayRef certs;
+ OSStatus status = SSLCopyPeerCertificates(ssl_context_, &certs);
+ if (status != noErr || !certs)
+ return ERR_UNEXPECTED;
+ scoped_cftyperef<CFArrayRef> scoped_certs(certs);
+ CFIndex certs_length = CFArrayGetCount(certs);
+ for (CFIndex i = 1; i < certs_length; ++i) {
+ SecCertificateRef cert_ref = reinterpret_cast<SecCertificateRef>(
+ const_cast<void*>(CFArrayGetValueAtIndex(certs, i)));
+ server_cert_->AddIntermediateCertificate(cert_ref);
}
- return net_error;
+ // TODO(hawk): set flags based on the SSLConfig, once SSLConfig is
wtc 2009/08/27 00:14:18 Nit: the second "SSLConfig" should be "SSLConfigSe
+ // fully fleshed out on Mac OS X.
+ int flags = 0;
+ verifier_.reset(new CertVerifier);
+ return verifier_->Verify(server_cert_, hostname_, flags,
+ &server_cert_verify_result_, &io_callback_);
}
+int SSLClientSocketMac::DoVerifyCertComplete(int result) {
+ DCHECK(verifier_.get());
+ verifier_.reset();
+
+ if (IsCertificateError(result) && ssl_config_.IsAllowedBadCert(server_cert_))
+ result = OK;
+
+ completed_handshake_ = true;
+ DCHECK(next_state_ == STATE_NONE);
+
+ return result;
+}
+
int SSLClientSocketMac::DoReadComplete(int result) {
if (result < 0) {
read_io_buf_ = NULL;

Powered by Google App Engine
This is Rietveld 408576698