summaryrefslogtreecommitdiffstats
path: root/src/network
diff options
context:
space:
mode:
authorPaul Wicking <paul.wicking@qt.io>2019-02-01 13:33:25 +0100
committerPaul Wicking <paul.wicking@qt.io>2019-02-01 13:33:26 +0100
commit2bc362c9fa37455afbeb56e5f1852188ede3eab4 (patch)
treeb89e3c2c082a0285e8cd91733ddbc772fe4362a5 /src/network
parent5de981d3bc3df874f9df35a6899345f4f61fa951 (diff)
parent481db443d502c8ebc169b7256cb696428cf02199 (diff)
Merge dev into 5.13
Diffstat (limited to 'src/network')
-rw-r--r--src/network/access/qabstractnetworkcache.cpp4
-rw-r--r--src/network/kernel/qnetworkinterface_unix.cpp2
-rw-r--r--src/network/ssl/qpassworddigestor.cpp2
-rw-r--r--src/network/ssl/qsslsocket.cpp2
-rw-r--r--src/network/ssl/qsslsocket_schannel.cpp95
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