diff options
author | Liang Qi <liang.qi@theqtcompany.com> | 2015-12-02 23:33:06 +0100 |
---|---|---|
committer | Liang Qi <liang.qi@theqtcompany.com> | 2015-12-02 23:33:06 +0100 |
commit | 72f5867f144cec8fc7848cbcc772683fe845652d (patch) | |
tree | 7513af27b59332bf111f406d304977adc8c8612e /src/network/ssl/qsslsocket_mac.cpp | |
parent | 13777097118c496391d4b9656b95097ac25e4a40 (diff) | |
parent | bf0af8b5a24de7e595929a64948a3548936aaaee (diff) |
Merge remote-tracking branch 'origin/5.6' into dev
Conflicts:
src/corelib/kernel/qcoreapplication.cpp
src/corelib/kernel/qeventdispatcher_blackberry.cpp
src/network/bearer/qnetworkconfiguration.cpp
src/plugins/bearer/blackberry/qbbengine.cpp
src/plugins/platforms/android/androidjnimain.cpp
src/plugins/platforms/android/qandroidplatformtheme.cpp
src/plugins/platforms/qnx/qqnxbpseventfilter.cpp
src/plugins/platforms/qnx/qqnxfiledialoghelper_bb10.cpp
src/plugins/platforms/qnx/qqnxinputcontext_imf.cpp
src/plugins/platforms/qnx/qqnxintegration.cpp
src/plugins/platforms/qnx/qqnxnavigatorbps.cpp
src/plugins/platforms/qnx/qqnxvirtualkeyboardbps.cpp
src/plugins/platforms/qnx/qqnxwindow.cpp
src/widgets/kernel/qwidgetwindow.cpp
src/widgets/styles/qwindowsvistastyle.cpp
src/widgets/styles/qwindowsxpstyle.cpp
src/widgets/widgets/qtoolbararealayout.cpp
tests/auto/corelib/global/qflags/qflags.pro
tests/auto/corelib/itemmodels/qitemmodel/modelstotest.cpp
tests/auto/corelib/tools/qversionnumber/qversionnumber.pro
tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp
Change-Id: I37be88c6c185bb85404823353e027a0a6acdbce4
Diffstat (limited to 'src/network/ssl/qsslsocket_mac.cpp')
-rw-r--r-- | src/network/ssl/qsslsocket_mac.cpp | 379 |
1 files changed, 293 insertions, 86 deletions
diff --git a/src/network/ssl/qsslsocket_mac.cpp b/src/network/ssl/qsslsocket_mac.cpp index 2af0264116..326686fad0 100644 --- a/src/network/ssl/qsslsocket_mac.cpp +++ b/src/network/ssl/qsslsocket_mac.cpp @@ -51,12 +51,291 @@ #include <algorithm> #include <cstddef> +#include <QtCore/private/qcore_mac_p.h> + #ifdef Q_OS_OSX #include <CoreServices/CoreServices.h> #endif QT_BEGIN_NAMESPACE +static SSLContextRef qt_createSecureTransportContext(QSslSocket::SslMode mode) +{ + const bool isServer = mode == QSslSocket::SslServerMode; + SSLContextRef context = Q_NULLPTR; + +#ifndef Q_OS_OSX + const SSLProtocolSide side = isServer ? kSSLServerSide : kSSLClientSide; + // We never use kSSLDatagramType, so it's kSSLStreamType unconditionally. + context = SSLCreateContext(Q_NULLPTR, side, kSSLStreamType); + if (!context) + qCWarning(lcSsl) << "SSLCreateContext failed"; +#else // Q_OS_OSX + +#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_8, __IPHONE_NA) + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_8) { + const SSLProtocolSide side = isServer ? kSSLServerSide : kSSLClientSide; + // We never use kSSLDatagramType, so it's kSSLStreamType unconditionally. + context = SSLCreateContext(Q_NULLPTR, side, kSSLStreamType); + if (!context) + qCWarning(lcSsl) << "SSLCreateContext failed"; + } else { +#else + { +#endif + const OSStatus errCode = SSLNewContext(isServer, &context); + if (errCode != noErr || !context) + qCWarning(lcSsl) << "SSLNewContext failed with error:" << errCode; + } +#endif // !Q_OS_OSX + + return context; +} + +static void qt_releaseSecureTransportContext(SSLContextRef context) +{ + if (!context) + return; + +#ifndef Q_OS_OSX + CFRelease(context); +#else + +#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_8, __IPHONE_NA) + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_8) { + CFRelease(context); + } else { +#else + { +#endif // QT_MAC_PLATFORM_... + const OSStatus errCode = SSLDisposeContext(context); + if (errCode != noErr) + qCWarning(lcSsl) << "SSLDisposeContext failed with error:" << errCode; + } +#endif // !Q_OS_OSX +} + +static bool qt_setSessionProtocol(SSLContextRef context, const QSslConfigurationPrivate &configuration, + QTcpSocket *plainSocket) +{ + Q_ASSERT(context); + +#ifndef QSSLSOCKET_DEBUG + Q_UNUSED(plainSocket) +#endif + + OSStatus err = noErr; + +#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_8, __IPHONE_5_0) + if (configuration.protocol == QSsl::SslV3) { + #ifdef QSSLSOCKET_DEBUG + qCDebug(lcSsl) << plainSocket << "requesting : SSLv3"; + #endif + err = SSLSetProtocolVersionMin(context, kSSLProtocol3); + if (err == noErr) + err = SSLSetProtocolVersionMax(context, kSSLProtocol3); + } else if (configuration.protocol == QSsl::TlsV1_0) { + #ifdef QSSLSOCKET_DEBUG + qCDebug(lcSsl) << plainSocket << "requesting : TLSv1.0"; + #endif + err = SSLSetProtocolVersionMin(context, kTLSProtocol1); + if (err == noErr) + err = SSLSetProtocolVersionMax(context, kTLSProtocol1); + } else if (configuration.protocol == QSsl::TlsV1_1) { + #ifdef QSSLSOCKET_DEBUG + qCDebug(lcSsl) << plainSocket << "requesting : TLSv1.1"; + #endif + err = SSLSetProtocolVersionMin(context, kTLSProtocol11); + if (err == noErr) + err = SSLSetProtocolVersionMax(context, kTLSProtocol11); + } else if (configuration.protocol == QSsl::TlsV1_2) { + #ifdef QSSLSOCKET_DEBUG + qCDebug(lcSsl) << plainSocket << "requesting : TLSv1.2"; + #endif + err = SSLSetProtocolVersionMin(context, kTLSProtocol12); + if (err == noErr) + err = SSLSetProtocolVersionMax(context, kTLSProtocol12); + } else if (configuration.protocol == QSsl::AnyProtocol) { + #ifdef QSSLSOCKET_DEBUG + qCDebug(lcSsl) << plainSocket << "requesting : any"; + #endif + // kSSLProtocol3, since kSSLProtocol2 is disabled: + err = SSLSetProtocolVersionMin(context, kSSLProtocol3); + if (err == noErr) + err = SSLSetProtocolVersionMax(context, kTLSProtocol12); + } else if (configuration.protocol == QSsl::TlsV1SslV3) { + #ifdef QSSLSOCKET_DEBUG + qCDebug(lcSsl) << plainSocket << "requesting : SSLv3 - TLSv1.2"; + #endif + err = SSLSetProtocolVersionMin(context, kSSLProtocol3); + if (err == noErr) + err = SSLSetProtocolVersionMax(context, kTLSProtocol12); + } else if (configuration.protocol == QSsl::SecureProtocols) { + #ifdef QSSLSOCKET_DEBUG + qCDebug(lcSsl) << plainSocket << "requesting : TLSv1 - TLSv1.2"; + #endif + err = SSLSetProtocolVersionMin(context, kTLSProtocol1); + if (err == noErr) + err = SSLSetProtocolVersionMax(context, kTLSProtocol12); + } else if (configuration.protocol == QSsl::TlsV1_0OrLater) { + #ifdef QSSLSOCKET_DEBUG + qCDebug(lcSsl) << plainSocket << "requesting : TLSv1 - TLSv1.2"; + #endif + err = SSLSetProtocolVersionMin(context, kTLSProtocol1); + if (err == noErr) + err = SSLSetProtocolVersionMax(context, kTLSProtocol12); + } else if (configuration.protocol == QSsl::TlsV1_1OrLater) { + #ifdef QSSLSOCKET_DEBUG + qCDebug(lcSsl) << plainSocket << "requesting : TLSv1.1 - TLSv1.2"; + #endif + err = SSLSetProtocolVersionMin(context, kTLSProtocol11); + if (err == noErr) + err = SSLSetProtocolVersionMax(context, kTLSProtocol12); + } else if (configuration.protocol == QSsl::TlsV1_2OrLater) { + #ifdef QSSLSOCKET_DEBUG + qCDebug(lcSsl) << plainSocket << "requesting : TLSv1.2"; + #endif + err = SSLSetProtocolVersionMin(context, kTLSProtocol12); + if (err == noErr) + err = SSLSetProtocolVersionMax(context, kTLSProtocol12); + } else { + #ifdef QSSLSOCKET_DEBUG + qCDebug(lcSsl) << plainSocket << "no protocol version found in the configuration"; + #endif + return false; + } +#endif + + return err == noErr; +} + +#ifdef Q_OS_OSX + +static bool qt_setSessionProtocolOSX(SSLContextRef context, const QSslConfigurationPrivate &configuration, + QTcpSocket *plainSocket) +{ + // This function works with (now) deprecated API that does not even exist on + // iOS but is the only API we have on OS X below 10.8 + + // Without SSLSetProtocolVersionMin/Max functions it's quite difficult + // to have the required result: + // If we use SSLSetProtocolVersion - any constant except the ones with 'Only' suffix - + // allows a negotiation and we can not set the lower limit. + // SSLSetProtocolVersionEnabled supports only a limited subset of constants, if you believe their docs: + // kSSLProtocol2 + // kSSLProtocol3 + // kTLSProtocol1 + // kSSLProtocolAll + // Here we can only have a look into the SecureTransport's code and hope that what we see there + // and what we have on 10.7 is similar: + // SSLSetProtocoLVersionEnabled actually accepts other constants also, + // called twice with two different protocols it sets a range, + // called once with a protocol (when all protocols were disabled) + // - only this protocol is enabled (without a lower limit negotiation). + + Q_ASSERT(context); + +#ifndef QSSLSOCKET_DEBUG + Q_UNUSED(plainSocket) +#endif + + OSStatus err = noErr; + + // First, disable ALL: + if (SSLSetProtocolVersionEnabled(context, kSSLProtocolAll, false) != noErr) + return false; + + if (configuration.protocol == QSsl::SslV3) { + #ifdef QSSLSOCKET_DEBUG + qCDebug(lcSsl) << plainSocket << "requesting : SSLv3"; + #endif + err = SSLSetProtocolVersion(context, kSSLProtocol3Only); + } else if (configuration.protocol == QSsl::TlsV1_0) { + #ifdef QSSLSOCKET_DEBUG + qCDebug(lcSsl) << plainSocket << "requesting : TLSv1.0"; + #endif + err = SSLSetProtocolVersion(context, kTLSProtocol1Only); + } else if (configuration.protocol == QSsl::TlsV1_1) { + #ifdef QSSLSOCKET_DEBUG + qCDebug(lcSsl) << plainSocket << "requesting : TLSv1.1"; + #endif + err = SSLSetProtocolVersionEnabled(context, kTLSProtocol11, true); + } else if (configuration.protocol == QSsl::TlsV1_2) { + #ifdef QSSLSOCKET_DEBUG + qCDebug(lcSsl) << plainSocket << "requesting : TLSv1.2"; + #endif + err = SSLSetProtocolVersionEnabled(context, kTLSProtocol12, true); + } else if (configuration.protocol == QSsl::AnyProtocol) { + #ifdef QSSLSOCKET_DEBUG + qCDebug(lcSsl) << plainSocket << "requesting : any"; + #endif + err = SSLSetProtocolVersionEnabled(context, kSSLProtocolAll, true); + } else if (configuration.protocol == QSsl::TlsV1SslV3) { + #ifdef QSSLSOCKET_DEBUG + qCDebug(lcSsl) << plainSocket << "requesting : SSLv3 - TLSv1.2"; + #endif + err = SSLSetProtocolVersionEnabled(context, kTLSProtocol12, true); + if (err == noErr) + err = SSLSetProtocolVersionEnabled(context, kSSLProtocol3, true); + } else if (configuration.protocol == QSsl::SecureProtocols) { + #ifdef QSSLSOCKET_DEBUG + qCDebug(lcSsl) << plainSocket << "requesting : TLSv1 - TLSv1.2"; + #endif + err = SSLSetProtocolVersionEnabled(context, kTLSProtocol12, true); + if (err == noErr) + err = SSLSetProtocolVersionEnabled(context, kTLSProtocol1, true); + } else if (configuration.protocol == QSsl::TlsV1_0OrLater) { + #ifdef QSSLSOCKET_DEBUG + qCDebug(lcSsl) << plainSocket << "requesting : TLSv1 - TLSv1.2"; + #endif + err = SSLSetProtocolVersionEnabled(context, kTLSProtocol12, true); + if (err == noErr) + err = SSLSetProtocolVersionEnabled(context, kTLSProtocol1, true); + } else if (configuration.protocol == QSsl::TlsV1_1OrLater) { + #ifdef QSSLSOCKET_DEBUG + qCDebug(lcSsl) << plainSocket << "requesting : TLSv1.1 - TLSv1.2"; + #endif + err = SSLSetProtocolVersionEnabled(context, kTLSProtocol12, true); + if (err == noErr) + err = SSLSetProtocolVersionEnabled(context, kTLSProtocol11, true); + } else if (configuration.protocol == QSsl::TlsV1_2OrLater) { + #ifdef QSSLSOCKET_DEBUG + qCDebug(lcSsl) << plainSocket << "requesting : TLSv1.2"; + #endif + err = SSLSetProtocolVersionEnabled(context, kTLSProtocol12, true); + } else { + #ifdef QSSLSOCKET_DEBUG + qCDebug(lcSsl) << plainSocket << "no protocol version found in the configuration"; + #endif + return false; + } + + return err == noErr; +} + +#endif // Q_OS_OSX + +QSecureTransportContext::QSecureTransportContext(SSLContextRef c) + : context(c) +{ +} + +QSecureTransportContext::~QSecureTransportContext() +{ + qt_releaseSecureTransportContext(context); +} + +QSecureTransportContext::operator SSLContextRef()const +{ + return context; +} + +void QSecureTransportContext::reset(SSLContextRef newContext) +{ + qt_releaseSecureTransportContext(context); + context = newContext; +} + Q_GLOBAL_STATIC_WITH_ARGS(QMutex, qt_securetransport_mutex, (QMutex::Recursive)) //#define QSSLSOCKET_DEBUG @@ -144,7 +423,7 @@ void QSslSocketPrivate::ensureInitialized() // from QSslCertificatePrivate's ctor. s_loadedCiphersAndCerts = true; - QCFType<SSLContextRef> context(SSLCreateContext(Q_NULLPTR, kSSLClientSide, kSSLStreamType)); + const QSecureTransportContext context(qt_createSecureTransportContext(QSslSocket::SslClientMode)); if (context) { QList<QSslCipher> ciphers; QList<QSslCipher> defaultCiphers; @@ -171,7 +450,6 @@ void QSslSocketPrivate::ensureInitialized() if (!s_loadRootCertsOnDemand) setDefaultCaCertificates(systemCaCertificates()); } else { - qCWarning(lcSsl) << "SSLCreateContext failed"; s_loadedCiphersAndCerts = false; } @@ -640,11 +918,7 @@ bool QSslSocketBackendPrivate::initSslContext() Q_ASSERT_X(!context, Q_FUNC_INFO, "invalid socket state, context is not null"); Q_ASSERT(plainSocket); - SSLProtocolSide side = kSSLClientSide; - if (mode == QSslSocket::SslServerMode) - side = kSSLServerSide; - - context = SSLCreateContext(Q_NULLPTR, side, kSSLStreamType); + context.reset(qt_createSecureTransportContext(mode)); if (!context) { setErrorAndEmit(QAbstractSocket::SslInternalError, "SSLCreateContext failed"); return false; @@ -740,7 +1014,7 @@ bool QSslSocketBackendPrivate::initSslContext() void QSslSocketBackendPrivate::destroySslContext() { - context = Q_NULLPTR; + context.reset(Q_NULLPTR); } static QByteArray _q_makePkcs12(const QList<QSslCertificate> &certs, const QSslKey &key, const QString &passPhrase); @@ -837,8 +1111,6 @@ bool QSslSocketBackendPrivate::setSessionProtocol() { Q_ASSERT_X(context, Q_FUNC_INFO, "invalid SSL context (null)"); - OSStatus err = noErr; - // QSsl::SslV2 == kSSLProtocol2 is disabled in secure transport and // always fails with errSSLIllegalParam: // if (version < MINIMUM_STREAM_VERSION || version > MAXIMUM_STREAM_VERSION) @@ -849,85 +1121,20 @@ bool QSslSocketBackendPrivate::setSessionProtocol() return false; } - if (configuration.protocol == QSsl::SslV3) { -#ifdef QSSLSOCKET_DEBUG - qCDebug(lcSsl) << plainSocket << "requesting : SSLv3"; -#endif - err = SSLSetProtocolVersionMin(context, kSSLProtocol3); - if (err == noErr) - err = SSLSetProtocolVersionMax(context, kSSLProtocol3); - } else if (configuration.protocol == QSsl::TlsV1_0) { -#ifdef QSSLSOCKET_DEBUG - qCDebug(lcSsl) << plainSocket << "requesting : TLSv1.0"; -#endif - err = SSLSetProtocolVersionMin(context, kTLSProtocol1); - if (err == noErr) - err = SSLSetProtocolVersionMax(context, kTLSProtocol1); - } else if (configuration.protocol == QSsl::TlsV1_1) { -#ifdef QSSLSOCKET_DEBUG - qCDebug(lcSsl) << plainSocket << "requesting : TLSv1.1"; -#endif - err = SSLSetProtocolVersionMin(context, kTLSProtocol11); - if (err == noErr) - err = SSLSetProtocolVersionMax(context, kTLSProtocol11); - } else if (configuration.protocol == QSsl::TlsV1_2) { -#ifdef QSSLSOCKET_DEBUG - qCDebug(lcSsl) << plainSocket << "requesting : TLSv1.2"; -#endif - err = SSLSetProtocolVersionMin(context, kTLSProtocol12); - if (err == noErr) - err = SSLSetProtocolVersionMax(context, kTLSProtocol12); - } else if (configuration.protocol == QSsl::AnyProtocol) { -#ifdef QSSLSOCKET_DEBUG - qCDebug(lcSsl) << plainSocket << "requesting : any"; -#endif - // kSSLProtocol3, since kSSLProtocol2 is disabled: - err = SSLSetProtocolVersionMin(context, kSSLProtocol3); - if (err == noErr) - err = SSLSetProtocolVersionMax(context, kTLSProtocol12); - } else if (configuration.protocol == QSsl::TlsV1SslV3) { -#ifdef QSSLSOCKET_DEBUG - qCDebug(lcSsl) << plainSocket << "requesting : SSLv3 - TLSv1.2"; -#endif - err = SSLSetProtocolVersionMin(context, kSSLProtocol3); - if (err == noErr) - err = SSLSetProtocolVersionMax(context, kTLSProtocol12); - } else if (configuration.protocol == QSsl::SecureProtocols) { -#ifdef QSSLSOCKET_DEBUG - qCDebug(lcSsl) << plainSocket << "requesting : TLSv1 - TLSv1.2"; -#endif - err = SSLSetProtocolVersionMin(context, kTLSProtocol1); - if (err == noErr) - err = SSLSetProtocolVersionMax(context, kTLSProtocol12); - } else if (configuration.protocol == QSsl::TlsV1_0OrLater) { -#ifdef QSSLSOCKET_DEBUG - qCDebug(lcSsl) << plainSocket << "requesting : TLSv1 - TLSv1.2"; -#endif - err = SSLSetProtocolVersionMin(context, kTLSProtocol1); - if (err == noErr) - err = SSLSetProtocolVersionMax(context, kTLSProtocol12); - } else if (configuration.protocol == QSsl::TlsV1_1OrLater) { -#ifdef QSSLSOCKET_DEBUG - qCDebug(lcSsl) << plainSocket << "requesting : TLSv1.1 - TLSv1.2"; -#endif - err = SSLSetProtocolVersionMin(context, kTLSProtocol11); - if (err == noErr) - err = SSLSetProtocolVersionMax(context, kTLSProtocol12); - } else if (configuration.protocol == QSsl::TlsV1_2OrLater) { -#ifdef QSSLSOCKET_DEBUG - qCDebug(lcSsl) << plainSocket << "requesting : TLSv1.2"; -#endif - err = SSLSetProtocolVersionMin(context, kTLSProtocol12); - if (err == noErr) - err = SSLSetProtocolVersionMax(context, kTLSProtocol12); +#ifndef Q_OS_OSX + return qt_setSessionProtocol(context, configuration, plainSocket); +#else + +#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_8, __IPHONE_NA) + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_8) { + return qt_setSessionProtocol(context, configuration, plainSocket); } else { -#ifdef QSSLSOCKET_DEBUG - qCDebug(lcSsl) << plainSocket << "no protocol version found in the configuration"; +#else + { #endif - return false; + return qt_setSessionProtocolOSX(context, configuration, plainSocket); } - - return err == noErr; +#endif } bool QSslSocketBackendPrivate::canIgnoreTrustVerificationFailure() const |