diff options
Diffstat (limited to 'src/network/access')
-rw-r--r-- | src/network/access/access.pri | 6 | ||||
-rw-r--r-- | src/network/access/qhsts.cpp | 180 | ||||
-rw-r--r-- | src/network/access/qhsts_p.h | 81 | ||||
-rw-r--r-- | src/network/access/qhstspolicy.cpp | 218 | ||||
-rw-r--r-- | src/network/access/qhstspolicy.h | 82 | ||||
-rw-r--r-- | src/network/access/qnetworkaccessmanager.cpp | 41 | ||||
-rw-r--r-- | src/network/access/qnetworkaccessmanager.h | 3 |
7 files changed, 457 insertions, 154 deletions
diff --git a/src/network/access/access.pri b/src/network/access/access.pri index 766d72590c..13d52ea44a 100644 --- a/src/network/access/access.pri +++ b/src/network/access/access.pri @@ -40,7 +40,8 @@ HEADERS += \ access/qhttpmultipart_p.h \ access/qnetworkfile_p.h \ access/qhttp2protocolhandler_p.h \ - access/qhsts_p.h + access/qhsts_p.h \ + access/qhstspolicy.h SOURCES += \ access/qftp.cpp \ @@ -74,7 +75,8 @@ SOURCES += \ access/qhttpmultipart.cpp \ access/qnetworkfile.cpp \ access/qhttp2protocolhandler.cpp \ - access/qhsts.cpp + access/qhsts.cpp \ + access/qhstspolicy.cpp mac: LIBS_PRIVATE += -framework Security diff --git a/src/network/access/qhsts.cpp b/src/network/access/qhsts.cpp index 2352c3e4f2..5e4f75b0ed 100644 --- a/src/network/access/qhsts.cpp +++ b/src/network/access/qhsts.cpp @@ -45,17 +45,8 @@ QT_BEGIN_NAMESPACE -static bool expired_policy(const QDateTime &expires) +static bool is_valid_domain_name(const QString &host) { - return !expires.isValid() || expires <= QDateTime::currentDateTimeUtc(); -} - -static bool has_valid_domain_name(const QUrl &url) -{ - if (!url.isValid()) - return false; - - const QString host(url.host()); if (!host.size()) return false; @@ -82,117 +73,106 @@ static bool has_valid_domain_name(const QUrl &url) return true; } -QHstsCache::QHstsCache() -{ - // Top-level domain without any label. - children.push_back(Domain()); -} - void QHstsCache::updateFromHeaders(const QList<QPair<QByteArray, QByteArray>> &headers, const QUrl &url) { - if (!has_valid_domain_name(url)) + if (!url.isValid()) return; QHstsHeaderParser parser; if (parser.parse(headers)) - updateKnownHost(url, parser.expirationDate(), parser.includeSubDomains()); + updateKnownHost(url.host(), parser.expirationDate(), parser.includeSubDomains()); +} + +void QHstsCache::updateFromPolicies(const QList<QHstsPolicy> &policies) +{ + for (const auto &policy : policies) + updateKnownHost(policy.host(), policy.expiry(), policy.includesSubDomains()); } -void QHstsCache::updateKnownHost(const QUrl &originalUrl, const QDateTime &expires, +void QHstsCache::updateKnownHost(const QUrl &url, const QDateTime &expires, bool includeSubDomains) { - if (!has_valid_domain_name(originalUrl)) + if (!url.isValid()) return; - // HSTS is a per-host policy, regardless of protocol, port or any of the other - // details in an URL; so we only want the host part. We still package this as - // a QUrl since this handles IDNA 2003 (RFC3490) for us, as required by - // HSTS (RFC6797, section 10). - QUrl url; - url.setHost(originalUrl.host()); - - // 1. Update our hosts: - QStringList labels(url.host().split(QLatin1Char('.'))); - std::reverse(labels.begin(), labels.end()); - - size_type domainIndex = 0; - for (int i = 0, e = labels.size(); i < e; ++i) { - Q_ASSERT(domainIndex < children.size()); - auto &subDomains = children[domainIndex].labels; - const auto &label = labels[i]; - auto pos = std::lower_bound(subDomains.begin(), subDomains.end(), label); - if (pos == subDomains.end() || pos->label != label) { - // A new, previously unknown host. - if (expired_policy(expires)) { - // Nothing to do at all - we did not know this host previously, - // we do not have to - since its policy expired. - return; - } - - pos = subDomains.insert(pos, label); - domainIndex = children.size(); - pos->domainIndex = domainIndex; - children.resize(children.size() + (e - i)); + updateKnownHost(url.host(), expires, includeSubDomains); +} - for (int j = i + 1; j < e; ++j) { - auto &newDomain = children[domainIndex]; - newDomain.labels.push_back(labels[j]); - newDomain.labels.back().domainIndex = ++domainIndex; - } +void QHstsCache::updateKnownHost(const QString &host, const QDateTime &expires, + bool includeSubDomains) +{ + if (!is_valid_domain_name(host)) + return; - break; + // HSTS is a per-host policy, regardless of protocol, port or any of the other + // details in an URL; so we only want the host part. QUrl::host handles + // IDNA 2003 (RFC3490) for us, as required by HSTS (RFC6797, section 10). + const HostName hostName(host); + const auto pos = knownHosts.find(hostName); + const QHstsPolicy newPolicy(expires, includeSubDomains, hostName.name); + if (pos == knownHosts.end()) { + // A new, previously unknown host. + if (newPolicy.isExpired()) { + // Nothing to do at all - we did not know this host previously, + // we do not have to - since its policy expired. + return; } - domainIndex = pos->domainIndex; + knownHosts.insert(pos, hostName, newPolicy); + return; } - Q_ASSERT(domainIndex > 0 && domainIndex < children.size()); - children[domainIndex].setHostPolicy(expires, includeSubDomains); + if (newPolicy.isExpired()) + knownHosts.erase(pos); + else + *pos = std::move(newPolicy); } -bool QHstsCache::isKnownHost(const QUrl &originalUrl) const +bool QHstsCache::isKnownHost(const QUrl &url) const { - if (!has_valid_domain_name(originalUrl)) + if (!url.isValid() || !is_valid_domain_name(url.host())) return false; - QUrl url; - url.setHost(originalUrl.host()); - - QStringList labels(url.host().split(QLatin1Char('.'))); - std::reverse(labels.begin(), labels.end()); + /* + RFC6797, 8.2. Known HSTS Host Domain Name Matching + + * Superdomain Match + If a label-for-label match between an entire Known HSTS Host's + domain name and a right-hand portion of the given domain name + is found, then this Known HSTS Host's domain name is a + superdomain match for the given domain name. There could be + multiple superdomain matches for a given domain name. + * Congruent Match + If a label-for-label match between a Known HSTS Host's domain + name and the given domain name is found -- i.e., there are no + further labels to compare -- then the given domain name + congruently matches this Known HSTS Host. + + We start from the congruent match, and then chop labels and dots and + proceed with superdomain match. While RFC6797 recommends to start from + superdomain, the result is the same - some valid policy will make a host + known. + */ + + bool superDomainMatch = false; + const QString hostNameAsString(url.host()); + HostName nameToTest(static_cast<QStringRef>(&hostNameAsString)); + while (nameToTest.fragment.size()) { + auto const pos = knownHosts.find(nameToTest); + if (pos != knownHosts.end()) { + if (pos.value().isExpired()) + knownHosts.erase(pos); + else if (!superDomainMatch || pos.value().includesSubDomains()) + return true; + } - Q_ASSERT(children.size()); - size_type domainIndex = 0; - for (int i = 0, e = labels.size(); i < e; ++i) { - Q_ASSERT(domainIndex < children.size()); - const auto &subDomains = children[domainIndex].labels; - auto pos = std::lower_bound(subDomains.begin(), subDomains.end(), labels[i]); - if (pos == subDomains.end() || pos->label != labels[i]) - return false; + const int dot = nameToTest.fragment.indexOf(QLatin1Char('.')); + if (dot == -1) + break; - Q_ASSERT(pos->domainIndex < children.size()); - domainIndex = pos->domainIndex; - auto &domain = children[domainIndex]; - if (domain.validateHostPolicy() && (i + 1 == e || domain.includeSubDomains)) { - /* - RFC6797, 8.2. Known HSTS Host Domain Name Matching - - * Superdomain Match - If a label-for-label match between an entire Known HSTS Host's - domain name and a right-hand portion of the given domain name - is found, then this Known HSTS Host's domain name is a - superdomain match for the given domain name. There could be - multiple superdomain matches for a given domain name. - * Congruent Match - If a label-for-label match between a Known HSTS Host's domain - name and the given domain name is found -- i.e., there are no - further labels to compare -- then the given domain name - congruently matches this Known HSTS Host. - */ - - return true; - } + nameToTest.fragment = nameToTest.fragment.mid(dot + 1); + superDomainMatch = true; } return false; @@ -200,10 +180,12 @@ bool QHstsCache::isKnownHost(const QUrl &originalUrl) const void QHstsCache::clear() { - children.resize(1); - children[0].labels.clear(); - // Top-level is never known: - Q_ASSERT(!children[0].isKnownHost); + knownHosts.clear(); +} + +QList<QHstsPolicy> QHstsCache::policies() const +{ + return knownHosts.values(); } // The parser is quite simple: 'nextToken' knowns exactly what kind of tokens diff --git a/src/network/access/qhsts_p.h b/src/network/access/qhsts_p.h index f3d5da9d23..5d95f39b96 100644 --- a/src/network/access/qhsts_p.h +++ b/src/network/access/qhsts_p.h @@ -51,17 +51,16 @@ // We mean it. // +#include <QtNetwork/qhstspolicy.h> + #include <QtCore/qbytearray.h> #include <QtCore/qdatetime.h> #include <QtCore/qstring.h> #include <QtCore/qglobal.h> -#include <QtCore/qvector.h> #include <QtCore/qlist.h> #include <QtCore/qpair.h> #include <QtCore/qurl.h> - -#include <algorithm> -#include <vector> +#include <QtCore/qmap.h> QT_BEGIN_NAMESPACE @@ -69,72 +68,48 @@ class Q_AUTOTEST_EXPORT QHstsCache { public: - QHstsCache(); - void updateFromHeaders(const QList<QPair<QByteArray, QByteArray>> &headers, const QUrl &url); + void updateFromPolicies(const QList<QHstsPolicy> &hosts); void updateKnownHost(const QUrl &url, const QDateTime &expires, bool includeSubDomains); bool isKnownHost(const QUrl &url) const; - void clear(); -private: - - using size_type = std::vector<int>::size_type; - - struct DomainLabel - { - DomainLabel(const QString &name = QString()) : label(name), domainIndex(0) {} + QList<QHstsPolicy> policies() const; - bool operator < (const DomainLabel &rhs) const - { return label < rhs.label; } +private: - QString label; - size_type domainIndex; - }; + void updateKnownHost(const QString &hostName, const QDateTime &expires, + bool includeSubDomains); - struct Domain + struct HostName { - void setHostPolicy(const QDateTime &expiration, bool subs) - { - expirationTime = expiration; - isKnownHost = expirationTime.isValid() - && expirationTime > QDateTime::currentDateTimeUtc(); - includeSubDomains = subs; - } + explicit HostName(const QString &n) : name(n) { } + explicit HostName(const QStringRef &r) : fragment(r) { } - bool validateHostPolicy() + bool operator < (const HostName &rhs) const { - if (!isKnownHost) - return false; - - if (expirationTime > QDateTime::currentDateTimeUtc()) - return true; - - isKnownHost = false; - includeSubDomains = false; - return false; + if (fragment.size()) { + if (rhs.fragment.size()) + return fragment < rhs.fragment; + return fragment < QStringRef(&rhs.name); + } + + if (rhs.fragment.size()) + return QStringRef(&name) < rhs.fragment; + return name < rhs.name; } - bool isKnownHost = false; - bool includeSubDomains = false; - QDateTime expirationTime; - std::vector<DomainLabel> labels; + // We use 'name' for a HostName object contained in our dictionary; + // we use 'fragment' only during lookup, when chopping the complete host + // name, removing subdomain names (such HostName object is 'transient', it + // must not outlive the original QString object. + QString name; + QStringRef fragment; }; - /* - Each Domain represents a DNS name or prefix thereof; each entry in its - std::vector<DomainLabel> labels pairs the next fragment of a DNS name - with the index into 'children' at which to find another Domain object. - The root Domain, children[0], has top-level-domain DomainLabel entries, - such as "com", "org" and "net"; the entry in 'children' at the index it - pairs with "com" is the Domain entry for .com; if that has "example" in - its labels, it'll be paired with the index of the entry in 'children' - that represents example.com; from which, in turn, we can find the - Domain object for www.example.com, and so on. - */ - mutable std::vector<Domain> children; + mutable QMap<HostName, QHstsPolicy> knownHosts; }; class Q_AUTOTEST_EXPORT QHstsHeaderParser diff --git a/src/network/access/qhstspolicy.cpp b/src/network/access/qhstspolicy.cpp new file mode 100644 index 0000000000..2cec587f4d --- /dev/null +++ b/src/network/access/qhstspolicy.cpp @@ -0,0 +1,218 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtNetwork module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qhstspolicy.h" + +#include <QtCore/qdatetime.h> +#include <QtCore/qstring.h> + +QT_BEGIN_NAMESPACE + +/*! + \class QHstsPolicy + \brief The QHstsPolicy class specifies that a host supports HTTP Strict Transport + Security policy (HSTS). + \since 5.9 + \ingroup network + \inmodule QtNetwork + + HSTS policy defines a period of time during which QNetworkAccessManager + should only access a host in a secure fashion. HSTS policy is defined by + RFC6797. + + You can set expiry time and host name for this policy, and control whether it + applies to subdomains, either in the constructor or by calling setExpiry(), + setHost() and setIncludesSubdomains(). + + \sa QNetworkAccessManager::enableStrictTransportSecurity() +*/ + +class QHstsPolicyPrivate +{ +public: + QUrl url; + QDateTime expiry; + bool includeSubDomains = false; + + bool operator == (const QHstsPolicyPrivate &other) const + { + return url.host() == other.url.host() && expiry == other.expiry + && includeSubDomains == other.includeSubDomains; + } +}; + +/*! + Constructs an invalid (expired) policy with empty host name and subdomains + not included. +*/ +QHstsPolicy::QHstsPolicy() : d(new QHstsPolicyPrivate) +{ +} + +/*! + Constructs QHstsPolicy with \a expiry (in UTC); \a includeSubDomains parameter + defines if this policy must also include subdomains, \a host data is interpreted + according to \a mode. + + \sa QUrl::setHost(), QUrl::ParsingMode +*/ +QHstsPolicy::QHstsPolicy(const QDateTime &expiry, bool includeSubDomains, const QString &host, + QUrl::ParsingMode mode) + : d(new QHstsPolicyPrivate) +{ + d->url.setHost(host, mode); + d->expiry = expiry; + d->includeSubDomains = includeSubDomains; +} + +/*! + Creates a copy of \a other object. +*/ +QHstsPolicy::QHstsPolicy(const QHstsPolicy &other) + : d(new QHstsPolicyPrivate(*other.d)) +{ +} + +/*! + Destructor. +*/ +QHstsPolicy::~QHstsPolicy() +{ +} + +/*! + Copy-assignment operator, makes a copy of \a other. +*/ +QHstsPolicy &QHstsPolicy::operator=(const QHstsPolicy &other) +{ + *d = *other.d; + return *this; +} + + +/*! + Move-assignment operator. +*/ +QHstsPolicy &QHstsPolicy::operator=(QHstsPolicy &&other) Q_DECL_NOTHROW +{ + qSwap(d, other.d); + return *this; +} + +/*! + Sets a host, \a host data is interpreted according to \a mode parameter. + + \sa host(), QUrl::setHost(), QUrl::ParsingMode +*/ +void QHstsPolicy::setHost(const QString &host, QUrl::ParsingMode mode) +{ + d->url.setHost(host, mode); +} + +/*! + Returns a host for a given policy, formatted according to \a options. + + \sa setHost(), QUrl::host(), QUrl::ComponentFormattingOptions +*/ +QString QHstsPolicy::host(QUrl::ComponentFormattingOptions options) const +{ + return d->url.host(options); +} + +/*! + Sets the expiration date for the policy (in UTC). + + \sa expiry() +*/ +void QHstsPolicy::setExpiry(const QDateTime &expiry) +{ + d->expiry = expiry; +} + +/*! + Returns the expiration date for the policy (in UTC). + + \sa setExpiry() +*/ +QDateTime QHstsPolicy::expiry() const +{ + return d->expiry; +} + +/*! + Includes or excludes subdomains for this policy. + + \sa includeSubdomains() +*/ +void QHstsPolicy::setIncludesSubDomains(bool include) +{ + d->includeSubDomains = include; +} + +/*! + Returns \c true if this policy also includes subdomains. + + \sa setIncludesSubDomains() + */ +bool QHstsPolicy::includesSubDomains() const +{ + return d->includeSubDomains; +} + +/*! + Returns \c true if the two policies have the same host and expriration date + while agreeing on whether to include or exclude subdomains. +*/ +bool QHstsPolicy::operator==(const QHstsPolicy &other) const +{ + return *d == *other.d; +} + +/*! + Return \c true if this policy has a valid expiration date and this date + is greater than QDateTime::currentGetDateTimeUtc(). + + \sa setExpiry(), expiry() +*/ +bool QHstsPolicy::isExpired() const +{ + return !d->expiry.isValid() || d->expiry <= QDateTime::currentDateTimeUtc(); +} + +QT_END_NAMESPACE diff --git a/src/network/access/qhstspolicy.h b/src/network/access/qhstspolicy.h new file mode 100644 index 0000000000..4260ac278c --- /dev/null +++ b/src/network/access/qhstspolicy.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtNetwork module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QHSTSPOLICY_H +#define QHSTSPOLICY_H + +#include <QtNetwork/qtnetworkglobal.h> + +#include <QtCore/qscopedpointer.h> +#include <QtCore/qurl.h> + +QT_BEGIN_NAMESPACE + +class QHstsPolicyPrivate; +class QDateTime; +class QString; +class Q_NETWORK_EXPORT QHstsPolicy +{ +public: + + QHstsPolicy(); + QHstsPolicy(const QDateTime &expiry, bool includeSubDomains, const QString &host, + QUrl::ParsingMode mode = QUrl::DecodedMode); + QHstsPolicy(const QHstsPolicy &rhs); + QHstsPolicy &operator=(const QHstsPolicy &rhs); + QHstsPolicy &operator=(QHstsPolicy &&rhs) Q_DECL_NOTHROW; + ~QHstsPolicy(); + + void setHost(const QString &host, QUrl::ParsingMode mode = QUrl::DecodedMode); + QString host(QUrl::ComponentFormattingOptions options = QUrl::FullyDecoded) const; + void setExpiry(const QDateTime &expiry); + QDateTime expiry() const; + void setIncludesSubDomains(bool include); + bool includesSubDomains() const; + + bool operator==(const QHstsPolicy &rhs) const; + bool isExpired() const; + +private: + + QScopedPointer<QHstsPolicyPrivate> d; +}; + +QT_END_NAMESPACE + +#endif // QHSTSPOLICY_H diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index 7aa8e61d26..19e9ecc265 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -45,6 +45,8 @@ #include "qnetworkcookie.h" #include "qnetworkcookiejar.h" #include "qabstractnetworkcache.h" +#include "qhstspolicy.h" +#include "qhsts_p.h" #include "QtNetwork/qnetworksession.h" #include "QtNetwork/private/qsharednetworksession_p.h" @@ -742,6 +744,45 @@ bool QNetworkAccessManager::strictTransportSecurityEnabled() const } /*! + \since 5.9 + + Adds HTTP Strict Transport Security policies into HSTS cache. + + \note An expired policy will remove a known host from the cache, if previously + present. + + \note While processing HTTP responses, QNetworkAccessManager can also update + the HSTS cache, removing or updating exitsting policies or introducing new + known hosts. The current implementation thus is server-driven, client code + can provide QNetworkAccessManager with previously known or discovered + policies, but this information can be overridden by "Strict-Transport-Security" + response headers. + + \sa addStrictTransportSecurityHosts(), QHstsPolicy +*/ + +void QNetworkAccessManager::addStrictTransportSecurityHosts(const QList<QHstsPolicy> &knownHosts) +{ + Q_D(QNetworkAccessManager); + d->stsCache.updateFromPolicies(knownHosts); +} + +/*! + \since 5.9 + + Returns the list of HTTP Strict Transport Security policies. This list can + differ from what was initially set via addStrictTransportSecurityHosts() if + HSTS cache was updated from a "Strict-Transport-Security" response header. + + \sa addStrictTransportSecurityHosts(), QHstsPolicy +*/ +QList<QHstsPolicy> QNetworkAccessManager::strictTransportSecurityHosts() const +{ + Q_D(const QNetworkAccessManager); + return d->stsCache.policies(); +} + +/*! Posts a request to obtain the network headers for \a request and returns a new QNetworkReply object which will contain such headers. diff --git a/src/network/access/qnetworkaccessmanager.h b/src/network/access/qnetworkaccessmanager.h index 143407fb25..52769627f3 100644 --- a/src/network/access/qnetworkaccessmanager.h +++ b/src/network/access/qnetworkaccessmanager.h @@ -61,6 +61,7 @@ class QNetworkReply; class QNetworkProxy; class QNetworkProxyFactory; class QSslError; +class QHstsPolicy; #ifndef QT_NO_BEARERMANAGEMENT class QNetworkConfiguration; #endif @@ -123,6 +124,8 @@ public: void enableStrictTransportSecurity(); void disableStrictTransportSecurity(); bool strictTransportSecurityEnabled() const; + void addStrictTransportSecurityHosts(const QList<QHstsPolicy> &knownHosts); + QList<QHstsPolicy> strictTransportSecurityHosts() const; QNetworkReply *head(const QNetworkRequest &request); QNetworkReply *get(const QNetworkRequest &request); |