diff options
author | Paul Wicking <paul.wicking@qt.io> | 2019-02-01 13:33:25 +0100 |
---|---|---|
committer | Paul Wicking <paul.wicking@qt.io> | 2019-02-01 13:33:26 +0100 |
commit | 2bc362c9fa37455afbeb56e5f1852188ede3eab4 (patch) | |
tree | b89e3c2c082a0285e8cd91733ddbc772fe4362a5 /src/network | |
parent | 5de981d3bc3df874f9df35a6899345f4f61fa951 (diff) | |
parent | 481db443d502c8ebc169b7256cb696428cf02199 (diff) |
Merge dev into 5.13
Change-Id: I8113c6d8735a151bd152e6096f8c8b8e63a05474
Diffstat (limited to 'src/network')
-rw-r--r-- | src/network/access/qabstractnetworkcache.cpp | 4 | ||||
-rw-r--r-- | src/network/kernel/qnetworkinterface_unix.cpp | 2 | ||||
-rw-r--r-- | src/network/ssl/qpassworddigestor.cpp | 2 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket.cpp | 2 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket_schannel.cpp | 95 |
5 files changed, 98 insertions, 7 deletions
diff --git a/src/network/access/qabstractnetworkcache.cpp b/src/network/access/qabstractnetworkcache.cpp index 1008b8e7f0..0b94dff61e 100644 --- a/src/network/access/qabstractnetworkcache.cpp +++ b/src/network/access/qabstractnetworkcache.cpp @@ -475,7 +475,7 @@ QAbstractNetworkCache::~QAbstractNetworkCache() the QIODevice when done with it. If there is no cache for \a url, the url is invalid, or if there - is an internal cache error 0 is returned. + is an internal cache error \nullptr is returned. In the base class this is a pure virtual function. @@ -496,7 +496,7 @@ QAbstractNetworkCache::~QAbstractNetworkCache() Returns the device that should be populated with the data for the cache item \a metaData. When all of the data has been written insert() should be called. If metaData is invalid or the url in - the metadata is invalid 0 is returned. + the metadata is invalid \nullptr is returned. The cache owns the device and will take care of deleting it when it is inserted or removed. diff --git a/src/network/kernel/qnetworkinterface_unix.cpp b/src/network/kernel/qnetworkinterface_unix.cpp index 8f290e5107..c28c5ea9e6 100644 --- a/src/network/kernel/qnetworkinterface_unix.cpp +++ b/src/network/kernel/qnetworkinterface_unix.cpp @@ -464,8 +464,10 @@ static QNetworkInterface::InterfaceType probeIfType(int socket, int iftype, stru case IFM_ETHER: return QNetworkInterface::Ethernet; +#ifdef IFM_FDDI case IFM_FDDI: return QNetworkInterface::Fddi; +#endif case IFM_IEEE80211: return QNetworkInterface::Ieee80211; diff --git a/src/network/ssl/qpassworddigestor.cpp b/src/network/ssl/qpassworddigestor.cpp index 127d94e849..706fa1de05 100644 --- a/src/network/ssl/qpassworddigestor.cpp +++ b/src/network/ssl/qpassworddigestor.cpp @@ -75,7 +75,7 @@ namespace QPasswordDigestor { \a salt must always be 8 bytes long! \note This function is provided for use with legacy applications and all - new applications are recommended to use \l {pbkdf2} {PBKDF2}. + new applications are recommended to use \l {deriveKeyPbkdf2} {PBKDF2}. \sa deriveKeyPbkdf2, QCryptographicHash, QCryptographicHash::hashLength */ diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp index 88398488a5..fc9a44f896 100644 --- a/src/network/ssl/qsslsocket.cpp +++ b/src/network/ssl/qsslsocket.cpp @@ -2891,8 +2891,6 @@ bool QSslSocketPrivate::isMatchingHostname(const QSslCertificate &cert, const QS if (QHostAddress(*it).isEqual(hostAddress, QHostAddress::StrictConversion)) return true; } - - return false; } const QString lowerPeerName = QString::fromLatin1(QUrl::toAce(peerName)); diff --git a/src/network/ssl/qsslsocket_schannel.cpp b/src/network/ssl/qsslsocket_schannel.cpp index 06bbc86469..965e9bf2f3 100644 --- a/src/network/ssl/qsslsocket_schannel.cpp +++ b/src/network/ssl/qsslsocket_schannel.cpp @@ -57,6 +57,11 @@ #include <security.h> #include <schnlsp.h> +#if NTDDI_VERSION >= NTDDI_WINBLUE && !defined(Q_CC_MINGW) +// ALPN = Application Layer Protocol Negotiation +#define SUPPORTS_ALPN 1 +#endif + // Not defined in MinGW #ifndef SECBUFFER_ALERT #define SECBUFFER_ALERT 17 @@ -391,6 +396,40 @@ Required const_reinterpret_cast(Actual *p) return Required(p); } +#ifdef SUPPORTS_ALPN +bool supportsAlpn() +{ + return QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows8_1; +} + +QByteArray createAlpnString(const QByteArrayList &nextAllowedProtocols) +{ + QByteArray alpnString; + if (!nextAllowedProtocols.isEmpty() && supportsAlpn()) { + const QByteArray names = [&nextAllowedProtocols]() { + QByteArray protocolString; + for (QByteArray proto : nextAllowedProtocols) { + if (proto.size() > 255) { + qCWarning(lcSsl) << "TLS ALPN extension" << proto + << "is too long and will be truncated to 255 characters."; + proto = proto.left(255); + } + protocolString += char(proto.length()) + proto; + } + return protocolString; + }(); + + const quint16 namesSize = names.size(); + const quint32 alpnId = SecApplicationProtocolNegotiationExt_ALPN; + const quint32 totalSize = sizeof(alpnId) + sizeof(namesSize) + namesSize; + alpnString = QByteArray::fromRawData(reinterpret_cast<const char *>(&totalSize), sizeof(totalSize)) + + QByteArray::fromRawData(reinterpret_cast<const char *>(&alpnId), sizeof(alpnId)) + + QByteArray::fromRawData(reinterpret_cast<const char *>(&namesSize), sizeof(namesSize)) + + names; + } + return alpnString; +} +#endif // SUPPORTS_ALPN } // anonymous namespace bool QSslSocketPrivate::s_loadRootCertsOnDemand = true; @@ -684,13 +723,28 @@ bool QSslSocketBackendPrivate::createContext() TimeStamp expiry; + SecBufferDesc alpnBufferDesc; + bool useAlpn = false; +#ifdef SUPPORTS_ALPN + configuration.nextProtocolNegotiationStatus = QSslConfiguration::NextProtocolNegotiationNone; + QByteArray alpnString = createAlpnString(configuration.nextAllowedProtocols); + useAlpn = !alpnString.isEmpty(); + SecBuffer alpnBuffers[1]; + alpnBuffers[0] = createSecBuffer(alpnString, SECBUFFER_APPLICATION_PROTOCOLS); + alpnBufferDesc = { + SECBUFFER_VERSION, + ARRAYSIZE(alpnBuffers), + alpnBuffers + }; +#endif + auto status = InitializeSecurityContext(&credentialHandle, // phCredential nullptr, // phContext const_reinterpret_cast<SEC_WCHAR *>(targetName().utf16()), // pszTargetName contextReq, // fContextReq 0, // Reserved1 0, // TargetDataRep (unused) - nullptr, // pInput (no input at the moment @future: alpn) + useAlpn ? &alpnBufferDesc : nullptr, // pInput 0, // Reserved2 &contextHandle, // phNewContext &outputBufferDesc, // pOutput @@ -725,7 +779,19 @@ bool QSslSocketBackendPrivate::acceptContext() SecBuffer inBuffers[2]; inBuffers[0] = createSecBuffer(intermediateBuffer, SECBUFFER_TOKEN); - inBuffers[1] = createSecBuffer(nullptr, 0, SECBUFFER_EMPTY); + +#ifdef SUPPORTS_ALPN + configuration.nextProtocolNegotiationStatus = QSslConfiguration::NextProtocolNegotiationNone; + // The string must be alive when we call AcceptSecurityContext + QByteArray alpnString = createAlpnString(configuration.nextAllowedProtocols); + if (!alpnString.isEmpty()) { + inBuffers[1] = createSecBuffer(alpnString, SECBUFFER_APPLICATION_PROTOCOLS); + } else +#endif + { + inBuffers[1] = createSecBuffer(nullptr, 0, SECBUFFER_EMPTY); + } + SecBufferDesc inputBufferDesc{ SECBUFFER_VERSION, ARRAYSIZE(inBuffers), @@ -931,6 +997,31 @@ bool QSslSocketBackendPrivate::verifyHandshake() SECPKG_ATTR_CONNECTION_INFO, &connectionInfo); CHECK_STATUS(status); + +#ifdef SUPPORTS_ALPN + if (!configuration.nextAllowedProtocols.isEmpty() && supportsAlpn()) { + SecPkgContext_ApplicationProtocol alpn; + status = QueryContextAttributes(&contextHandle, + SECPKG_ATTR_APPLICATION_PROTOCOL, + &alpn); + CHECK_STATUS(status); + if (alpn.ProtoNegoStatus == SecApplicationProtocolNegotiationStatus_Success) { + QByteArray negotiatedProto = QByteArray((const char *)alpn.ProtocolId, + alpn.ProtocolIdSize); + if (!configuration.nextAllowedProtocols.contains(negotiatedProto)) { + setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, + QSslSocket::tr("Unwanted protocol was negotiated")); + return false; + } + configuration.nextNegotiatedProtocol = negotiatedProto; + configuration.nextProtocolNegotiationStatus = QSslConfiguration::NextProtocolNegotiationNegotiated; + } else { + configuration.nextNegotiatedProtocol = ""; + configuration.nextProtocolNegotiationStatus = QSslConfiguration::NextProtocolNegotiationUnsupported; + } + } +#endif // supports ALPN + #undef CHECK_STATUS // Verify certificate |