Index: net/socket/ssl_client_socket_mac.cc |
diff --git a/net/socket/ssl_client_socket_mac.cc b/net/socket/ssl_client_socket_mac.cc |
index 5e1cf76436aa6777990898c3c29bf61d4a5ff686..1e9a96c6985ecebcf8cd018e5a9b0b77fff9b775 100644 |
--- a/net/socket/ssl_client_socket_mac.cc |
+++ b/net/socket/ssl_client_socket_mac.cc |
@@ -9,6 +9,7 @@ |
#include "base/string_util.h" |
#include "net/base/cert_verifier.h" |
#include "net/base/io_buffer.h" |
+#include "net/base/load_log.h" |
#include "net/base/net_errors.h" |
#include "net/base/ssl_info.h" |
@@ -326,108 +327,28 @@ SSLClientSocketMac::~SSLClientSocketMac() { |
Disconnect(); |
} |
-int SSLClientSocketMac::Connect(CompletionCallback* callback) { |
+int SSLClientSocketMac::Connect(CompletionCallback* callback, |
+ LoadLog* load_log) { |
DCHECK(transport_.get()); |
DCHECK(next_handshake_state_ == STATE_NONE); |
DCHECK(!user_connect_callback_); |
- OSStatus status = noErr; |
- |
- status = SSLNewContext(false, &ssl_context_); |
- if (status) |
- return NetErrorFromOSStatus(status); |
- |
- status = SSLSetProtocolVersionEnabled(ssl_context_, |
- kSSLProtocol2, |
- ssl_config_.ssl2_enabled); |
- if (status) |
- return NetErrorFromOSStatus(status); |
- |
- status = SSLSetProtocolVersionEnabled(ssl_context_, |
- kSSLProtocol3, |
- ssl_config_.ssl3_enabled); |
- if (status) |
- return NetErrorFromOSStatus(status); |
- |
- status = SSLSetProtocolVersionEnabled(ssl_context_, |
- kTLSProtocol1, |
- ssl_config_.tls1_enabled); |
- if (status) |
- return NetErrorFromOSStatus(status); |
- |
- status = SSLSetIOFuncs(ssl_context_, SSLReadCallback, SSLWriteCallback); |
- if (status) |
- return NetErrorFromOSStatus(status); |
- |
- status = SSLSetConnection(ssl_context_, this); |
- 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); |
- |
- // SSLSetSessionOption() was introduced in Mac OS X 10.5.7. It allows us |
- // to perform certificate validation during the handshake, which is |
- // required in order to properly enable session resumption. |
- // |
- // With the kSSLSessionOptionBreakOnServerAuth option set, SSLHandshake() |
- // will return errSSLServerAuthCompleted after receiving the server's |
- // Certificate during the handshake. That gives us an opportunity to verify |
- // the server certificate and then re-enter that handshake (assuming the |
- // certificate successfully validated). |
- // |
- // If SSLSetSessionOption() is not present, we do not enable session |
- // resumption, because in that case we are verifying the server's certificate |
- // after the handshake completes (but before any application data is |
- // exchanged). If we were to enable session resumption in this situation, |
- // the session would be cached before we verified the certificate, leaving |
- // the potential for a session in which the certificate failed to validate |
- // to still be able to be resumed. |
- CFBundleRef bundle = |
- CFBundleGetBundleWithIdentifier(CFSTR("com.apple.security")); |
- if (bundle) { |
- SSLSetSessionOptionFuncPtr ssl_set_session_options = |
- reinterpret_cast<SSLSetSessionOptionFuncPtr>( |
- CFBundleGetFunctionPointerForName(bundle, |
- CFSTR("SSLSetSessionOption"))); |
- if (ssl_set_session_options) { |
- status = ssl_set_session_options(ssl_context_, |
- kSSLSessionOptionBreakOnServerAuthFlag, |
- true); |
- if (status) |
- return NetErrorFromOSStatus(status); |
- |
- // Concatenate the hostname and peer address to use as the peer ID. To |
- // resume a session, we must connect to the same server on the same port |
- // using the same hostname (i.e., localhost and 127.0.0.1 are considered |
- // different peers, which puts us through certificate validation again |
- // and catches hostname/certificate name mismatches. |
- struct sockaddr_storage addr; |
- socklen_t addr_length = sizeof(struct sockaddr_storage); |
- memset(&addr, 0, sizeof(addr)); |
- if (!transport_->GetPeerName(reinterpret_cast<struct sockaddr*>(&addr), |
- &addr_length)) { |
- // Assemble the socket hostname and address into a single buffer. |
- std::vector<char> peer_id(hostname_.begin(), hostname_.end()); |
- peer_id.insert(peer_id.end(), reinterpret_cast<char*>(&addr), |
- reinterpret_cast<char*>(&addr) + addr_length); |
+ LoadLog::BeginEvent(load_log, LoadLog::TYPE_SSL_CONNECT); |
- // SSLSetPeerID() treats peer_id as a binary blob, and makes its |
- // own copy. |
- status = SSLSetPeerID(ssl_context_, &peer_id[0], peer_id.size()); |
- if (status) |
- return NetErrorFromOSStatus(status); |
- } |
- } |
+ int rv = InitializeSSLContext(); |
+ if (rv != OK) { |
+ LoadLog::EndEvent(load_log, LoadLog::TYPE_SSL_CONNECT); |
+ return rv; |
} |
next_handshake_state_ = STATE_HANDSHAKE_START; |
- int rv = DoHandshakeLoop(OK); |
- if (rv == ERR_IO_PENDING) |
+ rv = DoHandshakeLoop(OK); |
+ if (rv == ERR_IO_PENDING) { |
+ load_log_ = load_log; |
user_connect_callback_ = callback; |
+ } else { |
+ LoadLog::EndEvent(load_log, LoadLog::TYPE_SSL_CONNECT); |
+ } |
return rv; |
} |
@@ -535,6 +456,103 @@ void SSLClientSocketMac::GetSSLCertRequestInfo( |
// TODO(wtc): implement this. |
} |
+int SSLClientSocketMac::InitializeSSLContext() { |
+ OSStatus status = noErr; |
+ |
+ status = SSLNewContext(false, &ssl_context_); |
+ if (status) |
+ return NetErrorFromOSStatus(status); |
+ |
+ status = SSLSetProtocolVersionEnabled(ssl_context_, |
+ kSSLProtocol2, |
+ ssl_config_.ssl2_enabled); |
+ if (status) |
+ return NetErrorFromOSStatus(status); |
+ |
+ status = SSLSetProtocolVersionEnabled(ssl_context_, |
+ kSSLProtocol3, |
+ ssl_config_.ssl3_enabled); |
+ if (status) |
+ return NetErrorFromOSStatus(status); |
+ |
+ status = SSLSetProtocolVersionEnabled(ssl_context_, |
+ kTLSProtocol1, |
+ ssl_config_.tls1_enabled); |
+ if (status) |
+ return NetErrorFromOSStatus(status); |
+ |
+ status = SSLSetIOFuncs(ssl_context_, SSLReadCallback, SSLWriteCallback); |
+ if (status) |
+ return NetErrorFromOSStatus(status); |
+ |
+ status = SSLSetConnection(ssl_context_, this); |
+ 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); |
+ |
+ // SSLSetSessionOption() was introduced in Mac OS X 10.5.7. It allows us |
+ // to perform certificate validation during the handshake, which is |
+ // required in order to properly enable session resumption. |
+ // |
+ // With the kSSLSessionOptionBreakOnServerAuth option set, SSLHandshake() |
+ // will return errSSLServerAuthCompleted after receiving the server's |
+ // Certificate during the handshake. That gives us an opportunity to verify |
+ // the server certificate and then re-enter that handshake (assuming the |
+ // certificate successfully validated). |
+ // |
+ // If SSLSetSessionOption() is not present, we do not enable session |
+ // resumption, because in that case we are verifying the server's certificate |
+ // after the handshake completes (but before any application data is |
+ // exchanged). If we were to enable session resumption in this situation, |
+ // the session would be cached before we verified the certificate, leaving |
+ // the potential for a session in which the certificate failed to validate |
+ // to still be able to be resumed. |
+ CFBundleRef bundle = |
+ CFBundleGetBundleWithIdentifier(CFSTR("com.apple.security")); |
+ if (bundle) { |
+ SSLSetSessionOptionFuncPtr ssl_set_session_options = |
+ reinterpret_cast<SSLSetSessionOptionFuncPtr>( |
+ CFBundleGetFunctionPointerForName(bundle, |
+ CFSTR("SSLSetSessionOption"))); |
+ if (ssl_set_session_options) { |
+ status = ssl_set_session_options(ssl_context_, |
+ kSSLSessionOptionBreakOnServerAuthFlag, |
+ true); |
+ if (status) |
+ return NetErrorFromOSStatus(status); |
+ |
+ // Concatenate the hostname and peer address to use as the peer ID. To |
+ // resume a session, we must connect to the same server on the same port |
+ // using the same hostname (i.e., localhost and 127.0.0.1 are considered |
+ // different peers, which puts us through certificate validation again |
+ // and catches hostname/certificate name mismatches. |
+ struct sockaddr_storage addr; |
+ socklen_t addr_length = sizeof(struct sockaddr_storage); |
+ memset(&addr, 0, sizeof(addr)); |
+ if (!transport_->GetPeerName(reinterpret_cast<struct sockaddr*>(&addr), |
+ &addr_length)) { |
+ // Assemble the socket hostname and address into a single buffer. |
+ std::vector<char> peer_id(hostname_.begin(), hostname_.end()); |
+ peer_id.insert(peer_id.end(), reinterpret_cast<char*>(&addr), |
+ reinterpret_cast<char*>(&addr) + addr_length); |
+ |
+ // SSLSetPeerID() treats peer_id as a binary blob, and makes its |
+ // own copy. |
+ status = SSLSetPeerID(ssl_context_, &peer_id[0], peer_id.size()); |
+ if (status) |
+ return NetErrorFromOSStatus(status); |
+ } |
+ } |
+ } |
+ |
+ return OK; |
+} |
+ |
void SSLClientSocketMac::DoConnectCallback(int rv) { |
DCHECK(rv != ERR_IO_PENDING); |
DCHECK(user_connect_callback_); |
@@ -574,8 +592,11 @@ void SSLClientSocketMac::DoWriteCallback(int rv) { |
void SSLClientSocketMac::OnHandshakeIOComplete(int result) { |
DCHECK(next_handshake_state_ != STATE_NONE); |
int rv = DoHandshakeLoop(result); |
- if (rv != ERR_IO_PENDING) |
+ if (rv != ERR_IO_PENDING) { |
+ LoadLog::EndEvent(load_log_, LoadLog::TYPE_SSL_CONNECT); |
+ load_log_ = NULL; |
DoConnectCallback(rv); |
+ } |
} |
void SSLClientSocketMac::OnTransportReadComplete(int result) { |
@@ -589,8 +610,11 @@ void SSLClientSocketMac::OnTransportReadComplete(int result) { |
if (next_handshake_state_ != STATE_NONE) { |
int rv = DoHandshakeLoop(result); |
- if (rv != ERR_IO_PENDING) |
+ if (rv != ERR_IO_PENDING) { |
+ LoadLog::EndEvent(load_log_, LoadLog::TYPE_SSL_CONNECT); |
+ load_log_ = NULL; |
DoConnectCallback(rv); |
+ } |
return; |
} |
if (user_read_buf_) { |