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 ebb31f2d6c11ce54ab8303b7c7c5ba3cd340ffa6..ee6cc79134b0a0e44a2a9ca4594d782fb40c4f21 100644 |
--- a/net/socket/ssl_client_socket_mac.cc |
+++ b/net/socket/ssl_client_socket_mac.cc |
@@ -98,6 +98,9 @@ namespace net { |
namespace { |
+// You can change this to LOG(WARNING) during development. |
+#define SSL_LOG LOG(INFO) << "SSL: " |
+ |
#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5 |
// Declarations needed to call the 10.5.7 and later SSLSetSessionOption() |
// function when building with the 10.5.0 SDK. |
@@ -549,6 +552,7 @@ void SSLClientSocketMac::Disconnect() { |
SSLClose(ssl_context_); |
SSLDisposeContext(ssl_context_); |
ssl_context_ = NULL; |
+ SSL_LOG << "----- Disposed SSLContext"; |
} |
// Shut down anything that may call us back. |
@@ -650,10 +654,22 @@ void SSLClientSocketMac::GetSSLInfo(SSLInfo* ssl_info) { |
void SSLClientSocketMac::GetSSLCertRequestInfo( |
SSLCertRequestInfo* cert_request_info) { |
// I'm being asked for available client certs (identities). |
+ |
+ CFArrayRef allowed_issuer_names = NULL; |
+ if (SSLCopyDistinguishedNames(ssl_context_, &allowed_issuer_names) == noErr && |
+ allowed_issuer_names != NULL) { |
+ SSL_LOG << "Server has " << CFArrayGetCount(allowed_issuer_names) |
+ << " allowed issuer names"; |
wtc
2010/03/16 00:42:48
Nit: please align "<<" with the first "<<" on the
|
+ CFRelease(allowed_issuer_names); |
+ // TODO(snej): Filter GetSSLClientCertificates using this array. |
+ } |
+ |
cert_request_info->host_and_port = hostname_; |
cert_request_info->client_certs.clear(); |
X509Certificate::GetSSLClientCertificates(hostname_, |
&cert_request_info->client_certs); |
+ SSL_LOG << "Asking user to choose between " |
+ << cert_request_info->client_certs.size() << " client certs..."; |
} |
SSLClientSocket::NextProtoStatus |
@@ -663,6 +679,7 @@ SSLClientSocketMac::GetNextProto(std::string* proto) { |
} |
int SSLClientSocketMac::InitializeSSLContext() { |
+ SSL_LOG << "----- InitializeSSLContext"; |
OSStatus status = noErr; |
status = SSLNewContext(false, &ssl_context_); |
@@ -739,10 +756,12 @@ int SSLClientSocketMac::InitializeSSLContext() { |
status = ssl_set_session_options(ssl_context_, |
kSSLSessionOptionBreakOnServerAuth, |
true); |
- if (!status) |
+ if (!status) { |
+ SSL_LOG << "Setting kSSLSessionOptionBreakOnCertRequested"; |
status = ssl_set_session_options(ssl_context_, |
kSSLSessionOptionBreakOnCertRequested, |
true); |
+ } |
if (status) |
return NetErrorFromOSStatus(status); |
@@ -765,9 +784,10 @@ int SSLClientSocketMac::InitializeSSLContext() { |
status = SSLSetPeerID(ssl_context_, peer_id.data(), peer_id.length()); |
if (status) |
return NetErrorFromOSStatus(status); |
- } else { |
+ } else if (ssl_config_.send_client_cert) { |
// If I have a cert, set it up-front, otherwise the server may try to get |
// it later by renegotiating, which SecureTransport doesn't support well. |
+ SSL_LOG << "Setting client cert in advance because send_client_cert is set"; |
status = SetClientCert(); |
if (status) |
return NetErrorFromOSStatus(status); |
@@ -903,27 +923,42 @@ int SSLClientSocketMac::DoHandshakeLoop(int last_io_result) { |
int SSLClientSocketMac::DoHandshakeStart() { |
OSStatus status = SSLHandshake(ssl_context_); |
- if (status == errSSLWouldBlock) |
- next_handshake_state_ = STATE_HANDSHAKE_START; |
- |
- if (status == noErr || status == errSSLServerAuthCompleted) { |
- // TODO(hawk): we verify the certificate chain even on resumed sessions |
- // so that we have the certificate status (valid, expired but overridden |
- // by the user, EV, etc.) available. Eliminate this step once we have |
- // a certificate validation result cache. |
- next_handshake_state_ = STATE_VERIFY_CERT; |
- if (status == errSSLServerAuthCompleted) { |
+ |
+ switch (status) { |
+ case errSSLWouldBlock: |
+ next_handshake_state_ = STATE_HANDSHAKE_START; |
+ break; |
+ |
+ case noErr: |
+ // TODO(hawk): we verify the certificate chain even on resumed sessions |
+ // so that we have the certificate status (valid, expired but overridden |
+ // by the user, EV, etc.) available. Eliminate this step once we have |
+ // a certificate validation result cache. (Also applies to the |
+ // errSSLServerAuthCompleted case below.) |
+ next_handshake_state_ = STATE_VERIFY_CERT; |
+ break; |
+ |
+ case errSSLServerAuthCompleted: |
// Override errSSLServerAuthCompleted as it's not actually an error, |
// but rather an indication that we're only half way through the |
// handshake. |
+ SSL_LOG << "Server auth completed (DoHandshakeStart)"; |
+ next_handshake_state_ = STATE_VERIFY_CERT; |
handshake_interrupted_ = true; |
status = noErr; |
- } |
- } |
+ break; |
- if (status == errSSLClosedGraceful) { |
- // The server unexpectedly closed on us. |
- return ERR_SSL_PROTOCOL_ERROR; |
+ case errSSLClientCertRequested: |
wtc
2010/03/16 00:42:48
IMPORTANT:
1. Please document that if we get errS
Jens Alfke
2010/03/16 18:50:10
No, because we always abort the connection in this
|
+ SSL_LOG << "Received client cert request in DoHandshakeStart"; |
+ // If we knew the client cert, we would have set it already in |
+ // InitializeSSLContext, instead of asking for this callback. |
+ // So tell the caller that we need a client cert. |
+ DCHECK(!ssl_config_.send_client_cert); |
+ return ERR_SSL_CLIENT_AUTH_CERT_NEEDED; |
+ |
+ case errSSLClosedGraceful: |
+ // The server unexpectedly closed on us. |
+ return ERR_SSL_PROTOCOL_ERROR; |
} |
int net_error = NetErrorFromOSStatus(status); |
@@ -941,6 +976,7 @@ int SSLClientSocketMac::DoVerifyCert() { |
if (!server_cert_) |
return ERR_UNEXPECTED; |
+ SSL_LOG << "DoVerifyCert..."; |
int flags = 0; |
if (ssl_config_.rev_checking_enabled) |
flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED; |
@@ -956,6 +992,7 @@ int SSLClientSocketMac::DoVerifyCertComplete(int result) { |
DCHECK(verifier_.get()); |
verifier_.reset(); |
+ SSL_LOG << "...DoVerifyCertComplete (result=" << result << ")"; |
if (IsCertificateError(result) && ssl_config_.IsAllowedBadCert(server_cert_)) |
result = OK; |
@@ -968,6 +1005,7 @@ int SSLClientSocketMac::DoVerifyCertComplete(int result) { |
} else { |
// If the session was resumed or session resumption was disabled, we're |
// done with the handshake. |
+ SSL_LOG << "Handshake finished! (DoVerifyCertComplete)"; |
completed_handshake_ = true; |
DCHECK(next_handshake_state_ == STATE_NONE); |
} |
@@ -981,6 +1019,7 @@ int SSLClientSocketMac::SetClientCert() { |
scoped_cftyperef<CFArrayRef> cert_refs( |
ssl_config_.client_cert->CreateClientCertificateChain()); |
+ SSL_LOG << "SSLSetCertificate(" << CFArrayGetCount(cert_refs) << " certs)"; |
OSStatus result = SSLSetCertificate(ssl_context_, cert_refs); |
if (result) |
LOG(ERROR) << "SSLSetCertificate returned OSStatus " << result; |
@@ -995,9 +1034,12 @@ int SSLClientSocketMac::DoHandshakeFinish() { |
next_handshake_state_ = STATE_HANDSHAKE_FINISH; |
break; |
case errSSLClientCertRequested: |
- status = SetClientCert(); |
- next_handshake_state_ = STATE_HANDSHAKE_FINISH; |
- break; |
+ SSL_LOG << "Server requested client cert (DoHandshakeFinish)"; |
+ // If we knew the client cert, we would have set it already in |
+ // InitializeSSLContext, instead of asking for this callback. |
+ // So tell the caller that we need a client cert. |
+ DCHECK(!ssl_config_.send_client_cert); |
+ return ERR_SSL_CLIENT_AUTH_CERT_NEEDED; |
case errSSLClosedGraceful: |
return ERR_SSL_PROTOCOL_ERROR; |
case errSSLClosedAbort: |
@@ -1007,15 +1049,18 @@ int SSLClientSocketMac::DoHandshakeFinish() { |
if (SSLGetClientCertificateState(ssl_context_, &client_state) == noErr && |
client_state > kSSLClientCertNone) { |
if (client_state == kSSLClientCertRequested && |
- !ssl_config_.send_client_cert) |
+ !ssl_config_.send_client_cert) { |
+ SSL_LOG << "Server requested SSL cert during handshake"; |
return ERR_SSL_CLIENT_AUTH_CERT_NEEDED; |
- LOG(WARNING) << "Server aborted SSL handshake; client_state=" << |
- client_state; |
+ } |
+ LOG(WARNING) << "Server aborted SSL handshake; client_state=" |
+ << client_state; |
return ERR_BAD_SSL_CLIENT_AUTH_CERT; |
} |
break; |
} |
case noErr: |
+ SSL_LOG << "Handshake finished! (DoHandshakeFinish)"; |
completed_handshake_ = true; |
DCHECK(next_handshake_state_ == STATE_NONE); |
break; |
@@ -1054,7 +1099,7 @@ int SSLClientSocketMac::DoPayloadRead() { |
// Server wants to renegotiate, probably to ask for a client cert, |
// but SecureTransport doesn't support renegotiation so we have to close. |
// Tell my caller the server wants a client cert so it can reconnect. |
- LOG(INFO) << "Server renegotiating for client cert; restarting..."; |
+ SSL_LOG << "Server renegotiating; assuming it wants a client cert..."; |
return ERR_SSL_CLIENT_AUTH_CERT_NEEDED; |
default: |