summaryrefslogtreecommitdiffstats
path: root/net/socket/ssl_client_socket_mac.cc
diff options
context:
space:
mode:
Diffstat (limited to 'net/socket/ssl_client_socket_mac.cc')
-rw-r--r--net/socket/ssl_client_socket_mac.cc214
1 files changed, 119 insertions, 95 deletions
diff --git a/net/socket/ssl_client_socket_mac.cc b/net/socket/ssl_client_socket_mac.cc
index 5e1cf76..1e9a96c 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_) {