Secure Transport backend - make it work on OS X 10.7

On OS X SSLCreateContext is quite recent - it requires OS X/SDK version
>= 10.8. Since SecureTransport back-end is the default one in Qt 5.6,
make it also work on OS X 10.7.

Change-Id: I364feff9dd95772fcea926494b2d4edaffd2dde1
Reviewed-by: Morten Johan Sørvig <morten.sorvig@theqtcompany.com>
This commit is contained in:
Timur Pocheptsov 2015-09-29 12:38:53 +02:00 committed by Morten Johan Sørvig
parent 5a48d1d164
commit 7cfc24f72a
2 changed files with 103 additions and 13 deletions

View File

@ -51,8 +51,91 @@
#include <algorithm> #include <algorithm>
#include <cstddef> #include <cstddef>
#include <QtCore/private/qcore_mac_p.h>
#ifdef Q_OS_OSX
#include <CoreServices/CoreServices.h>
#endif
QT_BEGIN_NAMESPACE 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
const OSStatus errCode = SSLDisposeContext(context);
if (errCode != noErr)
qCWarning(lcSsl) << "SSLDisposeContext failed with error:" << errCode;
}
#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)) Q_GLOBAL_STATIC_WITH_ARGS(QMutex, qt_securetransport_mutex, (QMutex::Recursive))
//#define QSSLSOCKET_DEBUG //#define QSSLSOCKET_DEBUG
@ -140,7 +223,7 @@ void QSslSocketPrivate::ensureInitialized()
// from QSslCertificatePrivate's ctor. // from QSslCertificatePrivate's ctor.
s_loadedCiphersAndCerts = true; s_loadedCiphersAndCerts = true;
QCFType<SSLContextRef> context(SSLCreateContext(Q_NULLPTR, kSSLClientSide, kSSLStreamType)); const QSecureTransportContext context(qt_createSecureTransportContext(QSslSocket::SslClientMode));
if (context) { if (context) {
QList<QSslCipher> ciphers; QList<QSslCipher> ciphers;
QList<QSslCipher> defaultCiphers; QList<QSslCipher> defaultCiphers;
@ -167,7 +250,6 @@ void QSslSocketPrivate::ensureInitialized()
if (!s_loadRootCertsOnDemand) if (!s_loadRootCertsOnDemand)
setDefaultCaCertificates(systemCaCertificates()); setDefaultCaCertificates(systemCaCertificates());
} else { } else {
qCWarning(lcSsl) << "SSLCreateContext failed";
s_loadedCiphersAndCerts = false; s_loadedCiphersAndCerts = false;
} }
@ -652,11 +734,7 @@ bool QSslSocketBackendPrivate::initSslContext()
Q_ASSERT_X(!context, Q_FUNC_INFO, "invalid socket state, context is not null"); Q_ASSERT_X(!context, Q_FUNC_INFO, "invalid socket state, context is not null");
Q_ASSERT(plainSocket); Q_ASSERT(plainSocket);
SSLProtocolSide side = kSSLClientSide; context.reset(qt_createSecureTransportContext(mode));
if (mode == QSslSocket::SslServerMode)
side = kSSLServerSide;
context = SSLCreateContext(Q_NULLPTR, side, kSSLStreamType);
if (!context) { if (!context) {
setError("SSLCreateContext failed", QAbstractSocket::SslInternalError); setError("SSLCreateContext failed", QAbstractSocket::SslInternalError);
return false; return false;
@ -752,7 +830,7 @@ bool QSslSocketBackendPrivate::initSslContext()
void QSslSocketBackendPrivate::destroySslContext() void QSslSocketBackendPrivate::destroySslContext()
{ {
context = Q_NULLPTR; context.reset(Q_NULLPTR);
} }
static QByteArray _q_makePkcs12(const QList<QSslCertificate> &certs, const QSslKey &key, const QString &passPhrase); static QByteArray _q_makePkcs12(const QList<QSslCertificate> &certs, const QSslKey &key, const QString &passPhrase);

View File

@ -45,8 +45,6 @@
// We mean it. // We mean it.
// //
#include <QtCore/private/qcore_mac_p.h>
#include <QtCore/qstring.h> #include <QtCore/qstring.h>
#include <QtCore/qglobal.h> #include <QtCore/qglobal.h>
#include <QtCore/qlist.h> #include <QtCore/qlist.h>
@ -59,6 +57,20 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QSecureTransportContext
{
public:
explicit QSecureTransportContext(SSLContextRef context);
~QSecureTransportContext();
operator SSLContextRef () const;
void reset(SSLContextRef newContext);
private:
SSLContextRef context;
Q_DISABLE_COPY(QSecureTransportContext);
};
class QSslSocketBackendPrivate : public QSslSocketPrivate class QSslSocketBackendPrivate : public QSslSocketPrivate
{ {
Q_DECLARE_PUBLIC(QSslSocket) Q_DECLARE_PUBLIC(QSslSocket)
@ -76,8 +88,8 @@ public:
void startServerEncryption() Q_DECL_OVERRIDE; void startServerEncryption() Q_DECL_OVERRIDE;
void transmit() Q_DECL_OVERRIDE; void transmit() Q_DECL_OVERRIDE;
static QList<QSslError> (verify)(QList<QSslCertificate> certificateChain, static QList<QSslError> verify(QList<QSslCertificate> certificateChain,
const QString &hostName); const QString &hostName);
static bool importPkcs12(QIODevice *device, static bool importPkcs12(QIODevice *device,
QSslKey *key, QSslCertificate *cert, QSslKey *key, QSslCertificate *cert,
@ -108,7 +120,7 @@ private:
void setError(const QString &errorString, void setError(const QString &errorString,
QAbstractSocket::SocketError errorCode); QAbstractSocket::SocketError errorCode);
mutable QCFType<SSLContextRef> context; QSecureTransportContext context;
Q_DISABLE_COPY(QSslSocketBackendPrivate); Q_DISABLE_COPY(QSslSocketBackendPrivate);
}; };