Index: net/socket/ssl_client_socket_mac.cc |
=================================================================== |
--- net/socket/ssl_client_socket_mac.cc (revision 71257) |
+++ net/socket/ssl_client_socket_mac.cc (working copy) |
@@ -11,9 +11,11 @@ |
#include <algorithm> |
+#include "base/lazy_instance.h" |
#include "base/mac/scoped_cftyperef.h" |
#include "base/singleton.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 +142,27 @@ |
}; |
#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) { |
@@ -1114,6 +1137,9 @@ |
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); |