summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel.cpp7
-rw-r--r--src/network/ssl/qsslsocket_openssl.cpp20
-rw-r--r--tests/manual/qnetworkreply/main.cpp29
3 files changed, 44 insertions, 12 deletions
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
index d24fb159e2..9f63280bf8 100644
--- a/src/network/access/qhttpnetworkconnectionchannel.cpp
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
@@ -931,7 +931,8 @@ void QHttpNetworkConnectionChannel::_q_encrypted()
if (!protocolHandler) {
switch (sslSocket->sslConfiguration().nextProtocolNegotiationStatus()) {
- case QSslConfiguration::NextProtocolNegotiationNegotiated: {
+ case QSslConfiguration::NextProtocolNegotiationNegotiated: /* fall through */
+ case QSslConfiguration::NextProtocolNegotiationUnsupported: {
QByteArray nextProtocol = sslSocket->sslConfiguration().nextNegotiatedProtocol();
if (nextProtocol == QSslConfiguration::NextProtocolHttp1_1) {
// fall through to create a QHttpProtocolHandler
@@ -953,10 +954,6 @@ void QHttpNetworkConnectionChannel::_q_encrypted()
// re-queue requests from SPDY queue to HTTP queue, if any
requeueSpdyRequests();
break;
- case QSslConfiguration::NextProtocolNegotiationUnsupported:
- emitFinishedWithError(QNetworkReply::SslHandshakeFailedError,
- "chosen Next Protocol Negotiation value unsupported");
- break;
default:
emitFinishedWithError(QNetworkReply::SslHandshakeFailedError,
"detected unknown Next Protocol Negotiation protocol");
diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp
index 8833e3fdd8..0e1a3e53c9 100644
--- a/src/network/ssl/qsslsocket_openssl.cpp
+++ b/src/network/ssl/qsslsocket_openssl.cpp
@@ -1518,14 +1518,20 @@ void QSslSocketBackendPrivate::continueHandshake()
}
#if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
- const unsigned char *proto = 0;
- unsigned int proto_len = 0;
- q_SSL_get0_next_proto_negotiated(ssl, &proto, &proto_len);
- if (proto_len)
- configuration.nextNegotiatedProtocol = QByteArray(reinterpret_cast<const char *>(proto), proto_len);
- else
- configuration.nextNegotiatedProtocol.clear();
+
configuration.nextProtocolNegotiationStatus = sslContextPointer->npnContext().status;
+ if (sslContextPointer->npnContext().status == QSslConfiguration::NextProtocolNegotiationUnsupported) {
+ // we could not agree -> be conservative and use HTTP/1.1
+ configuration.nextNegotiatedProtocol = QByteArrayLiteral("http/1.1");
+ } else {
+ const unsigned char *proto = 0;
+ unsigned int proto_len = 0;
+ q_SSL_get0_next_proto_negotiated(ssl, &proto, &proto_len);
+ if (proto_len)
+ configuration.nextNegotiatedProtocol = QByteArray(reinterpret_cast<const char *>(proto), proto_len);
+ else
+ configuration.nextNegotiatedProtocol.clear();
+ }
#endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ...
connectionEncrypted = true;
diff --git a/tests/manual/qnetworkreply/main.cpp b/tests/manual/qnetworkreply/main.cpp
index 9d199c3755..08a9df1144 100644
--- a/tests/manual/qnetworkreply/main.cpp
+++ b/tests/manual/qnetworkreply/main.cpp
@@ -69,6 +69,7 @@ private slots:
void proxyAuthentication_data();
void proxyAuthentication();
void authentication();
+ void npnWithEmptyList(); // QTBUG-40714
protected slots:
void spdyReplyFinished(); // only used by spdyMultipleRequestsPerHost test
@@ -577,6 +578,34 @@ void tst_qnetworkreply::authentication()
QVERIFY(statusCode >= 200 && statusCode < 400);
}
+void tst_qnetworkreply::npnWithEmptyList() // QTBUG-40714
+{
+#if defined(QT_BUILD_INTERNAL) && !defined(QT_NO_SSL) && OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
+
+ // The server does not send a list of Next Protocols, so we test
+ // that we continue anyhow and it works
+
+ m_manager.clearAccessCache();
+
+ QUrl url(QStringLiteral("https://www.ossifrage.net/"));
+ QNetworkRequest request(url);
+ request.setAttribute(QNetworkRequest::SpdyAllowedAttribute, QVariant(true));
+ QNetworkReply *reply = m_manager.get(request);
+ QObject::connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
+
+ QTestEventLoop::instance().enterLoop(15);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+
+ int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
+ QVERIFY(statusCode == 200);
+
+ QCOMPARE(reply->sslConfiguration().nextProtocolNegotiationStatus(),
+ QSslConfiguration::NextProtocolNegotiationUnsupported);
+#else
+ QSKIP("Qt built withouth OpenSSL, or the OpenSSL version is too old");
+#endif // defined(QT_BUILD_INTERNAL) && !defined(QT_NO_SSL) ...
+}
+
QTEST_MAIN(tst_qnetworkreply)
#include "main.moc"