summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/network/access/qhttpnetworkconnection.cpp11
-rw-r--r--src/network/access/qnetworkreplyhttpimpl.cpp28
2 files changed, 31 insertions, 8 deletions
diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp
index 327eaf91bc..fd3cbbe36e 100644
--- a/src/network/access/qhttpnetworkconnection.cpp
+++ b/src/network/access/qhttpnetworkconnection.cpp
@@ -552,12 +552,11 @@ QUrl QHttpNetworkConnectionPrivate::parseRedirectResponse(QAbstractSocket *socke
if (redirectUrl.scheme() == QLatin1String("http") || redirectUrl.scheme() == QLatin1String("https")) {
switch (reply->request().redirectsPolicy()) {
case QNetworkRequest::NoLessSafeRedirectsPolicy:
- // Check if we're doing an unsecure redirect (https -> http)
- if (priorUrl.scheme() == QLatin1String("https")
- && redirectUrl.scheme() == QLatin1String("http")) {
- emitReplyError(socket, reply, QNetworkReply::InsecureRedirectError);
- return QUrl();
- }
+ // Here we could handle https->http redirects as InsecureProtocolError.
+ // However, if HSTS is enabled and redirectUrl.host() is a known STS
+ // host, then we'll replace its scheme and this won't downgrade protocol,
+ // after all. We cannot access QNAM's STS cache from here, so delegate
+ // this check to QNetworkReplyHttpImpl.
break;
case QNetworkRequest::SameOriginRedirectsPolicy:
if (priorUrl.host() != redirectUrl.host()
diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp
index 7d863ef53c..ece08acc6b 100644
--- a/src/network/access/qnetworkreplyhttpimpl.cpp
+++ b/src/network/access/qnetworkreplyhttpimpl.cpp
@@ -1135,16 +1135,40 @@ void QNetworkReplyHttpImplPrivate::onRedirected(const QUrl &redirectUrl, int htt
if (isFinished)
return;
+ const QString schemeBefore(url.scheme());
if (httpRequest.isFollowRedirects()) // update the reply's url as it could've changed
url = redirectUrl;
- redirectRequest = createRedirectRequest(originalRequest, redirectUrl, maxRedirectsRemaining);
+ if (managerPrivate->stsEnabled && managerPrivate->stsCache.isKnownHost(url)) {
+ // RFC6797, 8.3:
+ // The UA MUST replace the URI scheme with "https" [RFC2818],
+ // and if the URI contains an explicit port component of "80",
+ // then the UA MUST convert the port component to be "443", or
+ // if the URI contains an explicit port component that is not
+ // equal to "80", the port component value MUST be preserved;
+ // otherwise, if the URI does not contain an explicit port
+ // component, the UA MUST NOT add one.
+ url.setScheme(QLatin1String("https"));
+ if (url.port() == 80)
+ url.setPort(443);
+ }
+
+ const bool isLessSafe = schemeBefore == QLatin1String("https")
+ && url.scheme() == QLatin1String("http");
+ if (httpRequest.redirectsPolicy() == QNetworkRequest::NoLessSafeRedirectsPolicy
+ && isLessSafe) {
+ error(QNetworkReply::InsecureRedirectError,
+ QCoreApplication::translate("QHttp", "Insecure redirect"));
+ return;
+ }
+
+ redirectRequest = createRedirectRequest(originalRequest, url, maxRedirectsRemaining);
operation = getRedirectOperation(operation, httpStatus);
if (httpRequest.redirectsPolicy() != QNetworkRequest::UserVerifiedRedirectsPolicy)
followRedirect();
- emit q->redirected(redirectUrl);
+ emit q->redirected(url);
}
void QNetworkReplyHttpImplPrivate::followRedirect()