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 | |
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')
-rw-r--r-- | src/network/access/qhttpthreaddelegate.cpp | 4 | ||||
-rw-r--r-- | src/network/access/qnetworkreplyimpl.cpp | 6 | ||||
-rw-r--r-- | src/network/access/qspdyprotocolhandler.cpp | 22 | ||||
-rw-r--r-- | src/network/kernel/qdnslookup_android.cpp | 2 | ||||
-rw-r--r-- | src/network/kernel/qdnslookup_unix.cpp | 2 | ||||
-rw-r--r-- | src/network/kernel/qdnslookup_win.cpp | 4 | ||||
-rw-r--r-- | src/network/socket/qnativesocketengine.cpp | 36 | ||||
-rw-r--r-- | src/network/socket/qnativesocketengine_p.h | 12 | ||||
-rw-r--r-- | src/network/socket/qnativesocketengine_winrt.cpp | 35 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket_mac.cpp | 379 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket_mac_p.h | 22 |
11 files changed, 385 insertions, 139 deletions
diff --git a/src/network/access/qhttpthreaddelegate.cpp b/src/network/access/qhttpthreaddelegate.cpp index c07064fd94..b0e366d2f8 100644 --- a/src/network/access/qhttpthreaddelegate.cpp +++ b/src/network/access/qhttpthreaddelegate.cpp @@ -492,7 +492,7 @@ void QHttpThreadDelegate::finishedSlot() if (httpReply->statusCode() >= 400) { // it's an error reply QString msg = QLatin1String(QT_TRANSLATE_NOOP("QNetworkReply", - "Error downloading %1 - server replied: %2")); + "Error transferring %1 - server replied: %2")); msg = msg.arg(httpRequest.url().toString(), httpReply->reasonPhrase()); emit error(statusCodeFromHttp(httpReply->statusCode(), httpRequest.url()), msg); } @@ -518,7 +518,7 @@ void QHttpThreadDelegate::synchronousFinishedSlot() if (httpReply->statusCode() >= 400) { // it's an error reply QString msg = QLatin1String(QT_TRANSLATE_NOOP("QNetworkReply", - "Error downloading %1 - server replied: %2")); + "Error transferring %1 - server replied: %2")); incomingErrorDetail = msg.arg(httpRequest.url().toString(), httpReply->reasonPhrase()); incomingErrorCode = statusCodeFromHttp(httpReply->statusCode(), httpRequest.url()); } diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp index 12ecad5ff7..681c88e87b 100644 --- a/src/network/access/qnetworkreplyimpl.cpp +++ b/src/network/access/qnetworkreplyimpl.cpp @@ -127,8 +127,10 @@ void QNetworkReplyImplPrivate::_q_startOperation() return; } else { #ifndef QT_NO_BEARERMANAGEMENT - QObject::connect(session.data(), SIGNAL(stateChanged(QNetworkSession::State)), - q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)), Qt::QueuedConnection); + if (session) { + QObject::connect(session.data(), SIGNAL(stateChanged(QNetworkSession::State)), + q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)), Qt::QueuedConnection); + } #endif } diff --git a/src/network/access/qspdyprotocolhandler.cpp b/src/network/access/qspdyprotocolhandler.cpp index 7d2c0dfef2..5f9697ab92 100644 --- a/src/network/access/qspdyprotocolhandler.cpp +++ b/src/network/access/qspdyprotocolhandler.cpp @@ -452,7 +452,7 @@ bool QSpdyProtocolHandler::uncompressHeader(const QByteArray &input, QByteArray break; } default: { - qWarning() << Q_FUNC_INFO << "got unexpected zlib return value:" << zlibRet; + qWarning() << "got unexpected zlib return value:" << zlibRet; return false; } } @@ -688,7 +688,7 @@ bool QSpdyProtocolHandler::uploadData(qint32 streamID) Q_ASSERT(replyPrivate); if (reply->d_func()->state == QHttpNetworkReplyPrivate::SPDYHalfClosed || reply->d_func()->state == QHttpNetworkReplyPrivate::SPDYClosed) { - qWarning() << Q_FUNC_INFO << "Trying to upload to closed stream"; + qWarning("Trying to upload to closed stream"); return false; } @@ -843,7 +843,7 @@ void QSpdyProtocolHandler::handleControlFrame(const QByteArray &frameHeaders) // break; } default: - qWarning() << Q_FUNC_INFO << "cannot handle frame of type" << type; + qWarning() << "cannot handle frame of type" << type; } } @@ -887,13 +887,13 @@ void QSpdyProtocolHandler::parseHttpHeaders(char flags, const QByteArray &frameD QByteArray uncompressedHeader; if (!uncompressHeader(headerValuePairs, &uncompressedHeader)) { - qWarning() << Q_FUNC_INFO << "error reading header from SYN_REPLY message"; + qWarning("error reading header from SYN_REPLY message"); return; } qint32 headerCount = fourBytesToInt(uncompressedHeader.constData()); if (headerCount * 8 > uncompressedHeader.size()) { - qWarning() << Q_FUNC_INFO << "error parsing header from SYN_REPLY message"; + qWarning("error parsing header from SYN_REPLY message"); sendRST_STREAM(streamID, RST_STREAM_PROTOCOL_ERROR); return; } @@ -904,7 +904,7 @@ void QSpdyProtocolHandler::parseHttpHeaders(char flags, const QByteArray &frameD QByteArray name = uncompressedHeader.mid(readPointer, count); readPointer += count; if (readPointer > uncompressedHeader.size()) { - qWarning() << Q_FUNC_INFO << "error parsing header from SYN_REPLY message"; + qWarning("error parsing header from SYN_REPLY message"); sendRST_STREAM(streamID, RST_STREAM_PROTOCOL_ERROR); return; } @@ -913,7 +913,7 @@ void QSpdyProtocolHandler::parseHttpHeaders(char flags, const QByteArray &frameD QByteArray value = uncompressedHeader.mid(readPointer, count); readPointer += count; if (readPointer > uncompressedHeader.size()) { - qWarning() << Q_FUNC_INFO << "error parsing header from SYN_REPLY message"; + qWarning("error parsing header from SYN_REPLY message"); sendRST_STREAM(streamID, RST_STREAM_PROTOCOL_ERROR); return; } @@ -1014,7 +1014,7 @@ void QSpdyProtocolHandler::handleRST_STREAM(char /*flags*/, quint32 length, errorMessage = "server cannot process the frame because it is too large"; break; default: - qWarning() << Q_FUNC_INFO << "could not understand servers RST_STREAM status code"; + qWarning("could not understand servers RST_STREAM status code"); errorCode = QNetworkReply::ProtocolFailure; errorMessage = "got SPDY RST_STREAM message with unknown error code"; } @@ -1078,7 +1078,7 @@ void QSpdyProtocolHandler::handleSETTINGS(char flags, quint32 /*length*/, const break; } default: - qWarning() << Q_FUNC_INFO << "found unknown settings value" << value; + qWarning() << "found unknown settings value" << value; } } } @@ -1117,7 +1117,7 @@ void QSpdyProtocolHandler::handleGOAWAY(char /*flags*/, quint32 /*length*/, break; } default: - qWarning() << Q_FUNC_INFO << "unexpected status code" << statusCode; + qWarning() << "unexpected status code" << statusCode; errorCode = QNetworkReply::ProtocolUnknownError; } @@ -1252,7 +1252,7 @@ void QSpdyProtocolHandler::handleDataFrame(const QByteArray &frameHeaders) } if (flag_compress) { - qWarning() << Q_FUNC_INFO << "SPDY level compression is not supported"; + qWarning("SPDY level compression is not supported"); } if (flag_fin) { diff --git a/src/network/kernel/qdnslookup_android.cpp b/src/network/kernel/qdnslookup_android.cpp index b03c63c320..978da57609 100644 --- a/src/network/kernel/qdnslookup_android.cpp +++ b/src/network/kernel/qdnslookup_android.cpp @@ -41,7 +41,7 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN Q_UNUSED(requestName); Q_UNUSED(nameserver); Q_UNUSED(reply); - qWarning() << Q_FUNC_INFO << "Not yet supported on Android"; + qWarning("Not yet supported on Android"); reply->error = QDnsLookup::ResolverError; reply->errorString = tr("Not yet supported on Android"); return; diff --git a/src/network/kernel/qdnslookup_unix.cpp b/src/network/kernel/qdnslookup_unix.cpp index fa782dadf7..a5e97c4a93 100644 --- a/src/network/kernel/qdnslookup_unix.cpp +++ b/src/network/kernel/qdnslookup_unix.cpp @@ -166,7 +166,7 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN ns->sin6_addr.s6_addr[i] = ipv6Address[i]; } #else - qWarning() << Q_FUNC_INFO << "IPv6 addresses for nameservers is currently not supported"; + qWarning("IPv6 addresses for nameservers is currently not supported"); reply->error = QDnsLookup::ResolverError; reply->errorString = tr("IPv6 addresses for nameservers is currently not supported"); return; diff --git a/src/network/kernel/qdnslookup_win.cpp b/src/network/kernel/qdnslookup_win.cpp index 056a9c7a62..4a6c631983 100644 --- a/src/network/kernel/qdnslookup_win.cpp +++ b/src/network/kernel/qdnslookup_win.cpp @@ -60,9 +60,9 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN // For supoprting IPv6 nameserver addresses, we'll need to switch // from DnsQuey() to DnsQueryEx() as it supports passing an IPv6 // address in the nameserver list - qWarning() << Q_FUNC_INFO << "IPv6 addresses for nameservers is currently not supported"; + qWarning("IPv6 addresses for nameservers are currently not supported"); reply->error = QDnsLookup::ResolverError; - reply->errorString = tr("IPv6 addresses for nameservers is currently not supported"); + reply->errorString = tr("IPv6 addresses for nameservers are currently not supported"); return; } } diff --git a/src/network/socket/qnativesocketengine.cpp b/src/network/socket/qnativesocketengine.cpp index c11b889220..e86d3ad76e 100644 --- a/src/network/socket/qnativesocketengine.cpp +++ b/src/network/socket/qnativesocketengine.cpp @@ -672,6 +672,24 @@ int QNativeSocketEngine::accept() return d->nativeAccept(); } +/*! + Returns the number of bytes that are currently available for + reading. On error, -1 is returned. + + For UDP sockets, this function returns the accumulated size of all + pending datagrams, and it is therefore more useful for UDP sockets + to call hasPendingDatagrams() and pendingDatagramSize(). +*/ +qint64 QNativeSocketEngine::bytesAvailable() const +{ + Q_D(const QNativeSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::bytesAvailable(), -1); + Q_CHECK_NOT_STATE(QNativeSocketEngine::bytesAvailable(), QAbstractSocket::UnconnectedState, -1); + + return d->nativeBytesAvailable(); +} + +#ifndef QT_NO_UDPSOCKET #ifndef QT_NO_NETWORKINTERFACE /*! @@ -734,23 +752,6 @@ bool QNativeSocketEngine::setMulticastInterface(const QNetworkInterface &iface) #endif // QT_NO_NETWORKINTERFACE /*! - Returns the number of bytes that are currently available for - reading. On error, -1 is returned. - - For UDP sockets, this function returns the accumulated size of all - pending datagrams, and it is therefore more useful for UDP sockets - to call hasPendingDatagrams() and pendingDatagramSize(). -*/ -qint64 QNativeSocketEngine::bytesAvailable() const -{ - Q_D(const QNativeSocketEngine); - Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::bytesAvailable(), -1); - Q_CHECK_NOT_STATE(QNativeSocketEngine::bytesAvailable(), QAbstractSocket::UnconnectedState, -1); - - return d->nativeBytesAvailable(); -} - -/*! Returns \c true if there is at least one datagram pending. This function is only called by UDP sockets, where a datagram can have a size of 0. TCP sockets call bytesAvailable(). @@ -834,6 +835,7 @@ qint64 QNativeSocketEngine::writeDatagram(const char *data, qint64 size, const Q return d->nativeSendDatagram(data, size, header); } +#endif // QT_NO_UDPSOCKET /*! Writes a block of \a size bytes from \a data to the socket. diff --git a/src/network/socket/qnativesocketengine_p.h b/src/network/socket/qnativesocketengine_p.h index 5cc5e529fc..39e4d5e457 100644 --- a/src/network/socket/qnativesocketengine_p.h +++ b/src/network/socket/qnativesocketengine_p.h @@ -125,6 +125,12 @@ public: int accept() Q_DECL_OVERRIDE; void close() Q_DECL_OVERRIDE; + qint64 bytesAvailable() const Q_DECL_OVERRIDE; + + qint64 read(char *data, qint64 maxlen) Q_DECL_OVERRIDE; + qint64 write(const char *data, qint64 len) Q_DECL_OVERRIDE; + +#ifndef QT_NO_UDPSOCKET #ifndef QT_NO_NETWORKINTERFACE bool joinMulticastGroup(const QHostAddress &groupAddress, const QNetworkInterface &iface) Q_DECL_OVERRIDE; @@ -134,16 +140,12 @@ public: bool setMulticastInterface(const QNetworkInterface &iface) Q_DECL_OVERRIDE; #endif - qint64 bytesAvailable() const Q_DECL_OVERRIDE; - - qint64 read(char *data, qint64 maxlen) Q_DECL_OVERRIDE; - qint64 write(const char *data, qint64 len) Q_DECL_OVERRIDE; - qint64 readDatagram(char *data, qint64 maxlen, QIpPacketHeader * = 0, PacketHeaderOptions = WantNone) Q_DECL_OVERRIDE; qint64 writeDatagram(const char *data, qint64 len, const QIpPacketHeader &) Q_DECL_OVERRIDE; bool hasPendingDatagrams() const Q_DECL_OVERRIDE; qint64 pendingDatagramSize() const Q_DECL_OVERRIDE; +#endif // QT_NO_UDPSOCKET qint64 bytesToWrite() const Q_DECL_OVERRIDE; diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp index e9fa227733..173221dec0 100644 --- a/src/network/socket/qnativesocketengine_winrt.cpp +++ b/src/network/socket/qnativesocketengine_winrt.cpp @@ -78,6 +78,21 @@ typedef IAsyncOperationWithProgress<IBuffer *, UINT32> IAsyncBufferOperation; QT_BEGIN_NAMESPACE +static QByteArray socketDescription(const QAbstractSocketEngine *s) +{ + QByteArray result; + if (const QObject *o = s->parent()) { + const QString name = o->objectName(); + if (!name.isEmpty()) { + result += '"'; + result += name.toLocal8Bit(); + result += "\"/"; + } + result += o->metaObject()->className(); + } + return result; +} + // Common constructs #define Q_CHECK_VALID_SOCKETLAYER(function, returnValue) do { \ if (!isValid()) { \ @@ -275,8 +290,9 @@ bool QNativeSocketEngine::connectToHostByName(const QString &name, quint16 port) else if (d->socketType == QAbstractSocket::UdpSocket) hr = d->udpSocket()->ConnectAsync(remoteHost.Get(), portReference.Get(), &d->connectOp); if (hr == E_ACCESSDENIED) { - qErrnoWarning(hr, "QNativeSocketEngine::connectToHostByName: Unable to connect to host. \ - Please check your manifest capabilities."); + qErrnoWarning(hr, "QNativeSocketEngine::connectToHostByName: Unable to connect to host (%s:%hu/%s). " + "Please check your manifest capabilities.", + qPrintable(name), port, socketDescription(this).constData()); return false; } Q_ASSERT_SUCCEEDED(hr); @@ -328,7 +344,8 @@ bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port) hr = d->udpSocket()->BindEndpointAsync(hostAddress.Get(), portString.Get(), &op); } if (hr == E_ACCESSDENIED) { - qErrnoWarning(hr, "Unable to bind socket. Please check your manifest capabilities."); + qErrnoWarning(hr, "Unable to bind socket (%s:%hu/%s). Please check your manifest capabilities.", + qPrintable(address.toString()), port, socketDescription(this).constData()); return false; } Q_ASSERT_SUCCEEDED(hr); @@ -381,12 +398,14 @@ int QNativeSocketEngine::accept() ComPtr<IAsyncBufferOperation> op; hr = stream->ReadAsync(buffer.Get(), READ_BUFFER_SIZE, InputStreamOptions_Partial, &op); if (FAILED(hr)) { - qErrnoWarning(hr, "Faild to read from the socket buffer."); + qErrnoWarning(hr, "accept(): Failed to read from the socket buffer (%s).", + socketDescription(this).constData()); return -1; } hr = op->put_Completed(Callback<SocketReadCompletedHandler>(d, &QNativeSocketEnginePrivate::handleReadyRead).Get()); if (FAILED(hr)) { - qErrnoWarning(hr, "Failed to set socket read callback."); + qErrnoWarning(hr, "accept(): Failed to set socket read callback (%s).", + socketDescription(this).constData()); return -1; } d->currentConnections.append(socket); @@ -1272,12 +1291,14 @@ HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *async ComPtr<IAsyncBufferOperation> op; hr = stream->ReadAsync(buffer.Get(), bufferLength, InputStreamOptions_Partial, &op); if (FAILED(hr)) { - qErrnoWarning(hr, "Could not read into socket stream buffer."); + qErrnoWarning(hr, "handleReadyRead(): Could not read into socket stream buffer (%s).", + socketDescription(q).constData()); return S_OK; } hr = op->put_Completed(Callback<SocketReadCompletedHandler>(this, &QNativeSocketEnginePrivate::handleReadyRead).Get()); if (FAILED(hr)) { - qErrnoWarning(hr, "Failed to set socket read callback."); + qErrnoWarning(hr, "handleReadyRead(): Failed to set socket read callback (%s).", + socketDescription(q).constData()); return S_OK; } return S_OK; 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 diff --git a/src/network/ssl/qsslsocket_mac_p.h b/src/network/ssl/qsslsocket_mac_p.h index 414c155882..7a622db185 100644 --- a/src/network/ssl/qsslsocket_mac_p.h +++ b/src/network/ssl/qsslsocket_mac_p.h @@ -45,8 +45,6 @@ // We mean it. // -#include <QtCore/private/qcore_mac_p.h> - #include <QtCore/qstring.h> #include <QtCore/qglobal.h> #include <QtCore/qlist.h> @@ -59,6 +57,20 @@ 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 { Q_DECLARE_PUBLIC(QSslSocket) @@ -76,8 +88,8 @@ public: void startServerEncryption() Q_DECL_OVERRIDE; void transmit() Q_DECL_OVERRIDE; - static QList<QSslError> (verify)(QList<QSslCertificate> certificateChain, - const QString &hostName); + static QList<QSslError> verify(QList<QSslCertificate> certificateChain, + const QString &hostName); static bool importPkcs12(QIODevice *device, QSslKey *key, QSslCertificate *cert, @@ -101,7 +113,7 @@ private: bool checkSslErrors(); bool startHandshake(); - mutable QCFType<SSLContextRef> context; + QSecureTransportContext context; Q_DISABLE_COPY(QSslSocketBackendPrivate); }; |