diff options
author | Mårten Nordheim <marten.nordheim@qt.io> | 2024-04-02 11:11:52 +0200 |
---|---|---|
committer | Mårten Nordheim <marten.nordheim@qt.io> | 2024-04-20 13:48:37 +0200 |
commit | 4f9387f2aee19e38f05cab76a71f0d067b8d80dd (patch) | |
tree | e70d921bc1ece767d4fc5a50cf7342b43374d1b4 /tests/auto/network/access | |
parent | 60bdf2b220151021e59baa372a050b9f72400b81 (diff) |
Http2: fix handling unsuppported authenticate challenge
When adding/fixing parts earlier it was missed that it was not handling
the _unsupported_ case, when authentication is not handled and there is
no resend. But there _is_ a challenge header.
Pick-to: 6.7 6.6 6.5
Fixes: QTBUG-123891
Change-Id: I21470df0ce2528bad3babffc6e9f19b7afd29d20
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Diffstat (limited to 'tests/auto/network/access')
-rw-r--r-- | tests/auto/network/access/http2/tst_http2.cpp | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/tests/auto/network/access/http2/tst_http2.cpp b/tests/auto/network/access/http2/tst_http2.cpp index b624f6e436..d9e82330b2 100644 --- a/tests/auto/network/access/http2/tst_http2.cpp +++ b/tests/auto/network/access/http2/tst_http2.cpp @@ -25,6 +25,7 @@ #include <QtCore/qobject.h> #include <QtCore/qthread.h> #include <QtCore/qurl.h> +#include <QtCore/qset.h> #include <cstdlib> #include <memory> @@ -95,6 +96,8 @@ private slots: void authenticationRequired_data(); void authenticationRequired(); + void unsupportedAuthenticateChallenge(); + void h2cAllowedAttribute_data(); void h2cAllowedAttribute(); @@ -1243,6 +1246,89 @@ void tst_Http2::authenticationRequired() QTRY_VERIFY(serverGotSettingsACK); } +void tst_Http2::unsupportedAuthenticateChallenge() +{ + clearHTTP2State(); + serverPort = 0; + + if (defaultConnectionType() == H2Type::h2c) + QSKIP("This test requires TLS with ALPN to work"); + + ServerPtr targetServer(newServer(defaultServerSettings, defaultConnectionType())); + QByteArray responseBody = "Hello"_ba; + targetServer->setResponseBody(responseBody); + targetServer->setAuthenticationHeader("Bearer realm=\"qt.io accounts\""); + + QMetaObject::invokeMethod(targetServer.data(), "startServer", Qt::QueuedConnection); + runEventLoop(); + + QVERIFY(serverPort != 0); + + nRequests = 1; + + QUrl url = requestUrl(defaultConnectionType()); + url.setPath("/index.html"); + QNetworkRequest request(url); + + QByteArray expectedBody = "Hello, World!"; + request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); + QScopedPointer<QNetworkReply> reply; + reply.reset(manager->post(request, expectedBody)); + + bool authenticationRequested = false; + connect(manager.get(), &QNetworkAccessManager::authenticationRequired, reply.get(), + [&](QNetworkReply *, QAuthenticator *auth) { + authenticationRequested = true; + }); + + bool finishedReceived = false; + connect(reply.get(), &QNetworkReply::finished, reply.get(), + [&]() { finishedReceived = true; }); + bool errorReceived = false; + connect(reply.get(), &QNetworkReply::errorOccurred, reply.get(), + [&]() { errorReceived = true; }); + + QSet<quint32> receivedDataOnStreams; + connect(targetServer.get(), &Http2Server::receivedDATAFrame, reply.get(), + [&receivedDataOnStreams](quint32 streamID, const QByteArray &body) { + Q_UNUSED(body); + receivedDataOnStreams.insert(streamID); + }); + + // Use queued connection so that the finished signal can be emitted and the + // isFinished property can be set. + connect(reply.get(), &QNetworkReply::errorOccurred, this, + &tst_Http2::replyFinishedWithError, Qt::QueuedConnection); + + // Since we're using self-signed certificates, ignore SSL errors: + reply->ignoreSslErrors(); + + runEventLoop(); + STOP_ON_FAILURE + QVERIFY2(reply->isFinished(), + "The reply should error out if authentication fails, or finish if it succeeds"); + + QCOMPARE(reply->error(), QNetworkReply::AuthenticationRequiredError); + QVERIFY(reply->isFinished()); + QVERIFY(errorReceived); + QVERIFY(finishedReceived); + QCOMPARE(receivedDataOnStreams.size(), 1); + QVERIFY(receivedDataOnStreams.contains(1)); // the original, failed, request + + QVERIFY(!authenticationRequested); + + // We should not have sent any authentication headers to the server, since + // we don't support the challenge. + const QByteArray reqAuthHeader = targetServer->requestAuthorizationHeader(); + QVERIFY(reqAuthHeader.isEmpty()); + + // In the `!success` case we need to wait for the server to emit this or it might cause issues + // in the next test running after this. In the `success` case we anyway expect it to have been + // received. + QTRY_VERIFY(serverGotSettingsACK); + +} + void tst_Http2::h2cAllowedAttribute_data() { QTest::addColumn<bool>("h2cAllowed"); |