Index: net/socket/ssl_client_socket_mac.cc |
=================================================================== |
--- net/socket/ssl_client_socket_mac.cc (revision 58298) |
+++ net/socket/ssl_client_socket_mac.cc (working copy) |
@@ -802,17 +802,21 @@ |
if (status) |
return NetErrorFromOSStatus(status); |
+ // It is tricky to handle client cert request over renegotiation due to bugs |
+ // in Secure Transport. From Ken McLeod on apple-cdsa: |
+ // http://lists.apple.com/archives/apple-cdsa/2010/Feb/msg00058.html |
+ // A possible workaround would be to set the |
+ // kSSLSessionOptionBreakOnCertRequested option initially, then if you get |
+ // that status, ask for a client cert, abort the connection yourself and |
+ // retry it (this time calling SSLSetCertificate before the handshake |
+ // starts, and *not* setting the kSSLSessionOptionBreakOnCertRequested |
+ // option.) |
if (ssl_config_.send_client_cert) { |
- // Provide the client cert up-front if we have one, even though we'll get |
- // notified later when the server requests it, and set it again; this is |
- // seemingly redundant but works around a problem with SecureTransport |
- // and provides correct behavior on both 10.5 and 10.6: |
- // http://lists.apple.com/archives/apple-cdsa/2010/Feb/msg00058.html |
- // http://code.google.com/p/chromium/issues/detail?id=38905 |
SSL_LOG << "Setting client cert in advance because send_client_cert is set"; |
status = SetClientCert(); |
if (status) |
return NetErrorFromOSStatus(status); |
+ return OK; |
} |
status = EnableBreakOnAuth(true); |
@@ -1109,11 +1113,8 @@ |
break; |
case errSSLClientCertRequested: |
SSL_LOG << "Server requested client cert (DoHandshakeFinish)"; |
- if (!ssl_config_.send_client_cert) |
- return ERR_SSL_CLIENT_AUTH_CERT_NEEDED; |
- // (We already called SetClientCert during InitializeSSLContext.) |
- status = noErr; |
- next_handshake_state_ = STATE_HANDSHAKE_FINISH; |
+ DCHECK(!ssl_config_.send_client_cert); |
+ return ERR_SSL_CLIENT_AUTH_CERT_NEEDED; |
break; |
case errSSLClosedGraceful: |
return ERR_SSL_PROTOCOL_ERROR; |
@@ -1148,16 +1149,7 @@ |
} |
void SSLClientSocketMac::HandshakeFinished() { |
- // After the handshake's finished, disable breaking on server or client |
- // auth. Otherwise it might be triggered during a subsequent renegotiation, |
- // and SecureTransport doesn't handle that very well (there's usually no way |
- // to proceed without aborting the connection, at least not on 10.5.) |
SSL_LOG << "HandshakeFinished()"; |
- OSStatus status = EnableBreakOnAuth(false); |
- if (status != noErr) |
- SSL_LOG << "EnableBreakOnAuth failed: " << status; |
- // Note- this will actually always return an error, up through OS 10.6.3, |
- // because the option can't be changed after the context opens. |
} |
int SSLClientSocketMac::DoPayloadRead() { |
@@ -1187,14 +1179,7 @@ |
case errSSLClientCertRequested: |
// Server wants to renegotiate, probably to ask for a client cert, |
// but SecureTransport doesn't support renegotiation so we have to close. |
- if (ssl_config_.send_client_cert) { |
- // We already gave SecureTransport a client cert. At this point there's |
- // nothing we can do; the renegotiation will fail regardless, due to |
- // bugs in Apple's SecureTransport library. |
- SSL_LOG << "Server renegotiating (status=" << status |
- << "), but I've already set a client cert. Fatal error."; |
- return ERR_SSL_PROTOCOL_ERROR; |
- } |
+ DCHECK(!ssl_config_.send_client_cert); |
// Tell my caller the server wants a client cert so it can reconnect. |
SSL_LOG << "Server renegotiating; assuming it wants a client cert..."; |
return ERR_SSL_CLIENT_AUTH_CERT_NEEDED; |