diff options
Diffstat (limited to 'net/socket/ssl_client_socket_mac.cc')
-rw-r--r-- | net/socket/ssl_client_socket_mac.cc | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/net/socket/ssl_client_socket_mac.cc b/net/socket/ssl_client_socket_mac.cc index 352b3b1..fa283ab 100644 --- a/net/socket/ssl_client_socket_mac.cc +++ b/net/socket/ssl_client_socket_mac.cc @@ -14,6 +14,7 @@ #include "base/lazy_instance.h" #include "base/mac/scoped_cftyperef.h" #include "base/string_util.h" +#include "base/sys_info.h" #include "net/base/address_list.h" #include "net/base/cert_verifier.h" #include "net/base/io_buffer.h" @@ -140,6 +141,27 @@ enum { }; #endif +// On OS X 10.5.x, SSLHandshake() is broken with respect to renegotiation +// handshakes, and the only way to advance the handshake state machine is +// to use SSLRead(), which transparently re-handshakes and then reads +// application data. Using SSLRead() to pump the handshake, rather than +// SSLHandshake(), is not presently implemented, so on 10.5.x, SSL +// renegotiation is disabled entirely. On 10.6.x, SSLHandshake() behaves as +// expected/documented, so renegotiation is supported. +struct RenegotiationBroken { + RenegotiationBroken() : broken(false) { + int32 major, minor, bugfix; + base::SysInfo::OperatingSystemVersionNumbers(&major, &minor, &bugfix); + if (major < 10 || (major == 10 && minor < 6)) + broken = true; + } + + bool broken; +}; + +base::LazyInstance<RenegotiationBroken> g_renegotiation_broken( + base::LINKER_INITIALIZED); + // For an explanation of the Mac OS X error codes, please refer to: // http://developer.apple.com/mac/library/documentation/Security/Reference/secureTransportRef/Reference/reference.html int NetErrorFromOSStatus(OSStatus status) { @@ -1119,6 +1141,9 @@ int SSLClientSocketMac::DoPayloadRead() { OSStatus status = SSLRead(ssl_context_, user_read_buf_->data(), user_read_buf_len_, &processed); if (status == errSSLWouldBlock && renegotiating_) { + if (g_renegotiation_broken.Get().broken) + return ERR_SSL_RENEGOTIATION_REQUESTED; + CHECK_EQ(static_cast<size_t>(0), processed); next_handshake_state_ = STATE_HANDSHAKE; return DoHandshakeLoop(OK); |