From 4b7ff8e98c0208273a25d84e1f0322cad5bce2bf Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Thu, 13 Sep 2018 12:59:59 +0200 Subject: Protect HSTS code for no-feature-settings build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Under the hood we use QSettings to store HSTS policies. Qt configured with 'no feature settings' would fail to build then. For such builds, we fall back to in-memory only HSTS cache. Change-Id: I6df551d8c6c96d982080a51ce6b1bdce71d04b9f Reviewed-by: MÃ¥rten Nordheim Reviewed-by: Edward Welbourne --- src/network/access/access.pri | 14 ++++++++++---- src/network/access/qhsts.cpp | 19 ++++++++++++++++++- src/network/access/qhsts_p.h | 8 +++++--- src/network/access/qhstsstore_p.h | 2 ++ src/network/access/qnetworkaccessmanager.cpp | 13 +++++++++++++ src/network/access/qnetworkaccessmanager_p.h | 7 ++++++- 6 files changed, 54 insertions(+), 9 deletions(-) diff --git a/src/network/access/access.pri b/src/network/access/access.pri index a129beda15..ec0273377f 100644 --- a/src/network/access/access.pri +++ b/src/network/access/access.pri @@ -24,8 +24,7 @@ HEADERS += \ access/qabstractnetworkcache.h \ access/qnetworkfile_p.h \ access/qhsts_p.h \ - access/qhstspolicy.h \ - access/qhstsstore_p.h + access/qhstspolicy.h SOURCES += \ access/qnetworkaccessauthenticationmanager.cpp \ @@ -45,8 +44,7 @@ SOURCES += \ access/qabstractnetworkcache.cpp \ access/qnetworkfile.cpp \ access/qhsts.cpp \ - access/qhstspolicy.cpp \ - access/qhstsstore.cpp + access/qhstspolicy.cpp qtConfig(ftp) { HEADERS += \ @@ -66,6 +64,14 @@ qtConfig(networkdiskcache) { SOURCES += access/qnetworkdiskcache.cpp } +qtConfig(settings) { + HEADERS += \ + access/qhstsstore_p.h + + SOURCES += \ + access/qhstsstore.cpp +} + mac: LIBS_PRIVATE += -framework Security include($$PWD/../../3rdparty/zlib_dependency.pri) diff --git a/src/network/access/qhsts.cpp b/src/network/access/qhsts.cpp index 43a8a3663e..af913ca015 100644 --- a/src/network/access/qhsts.cpp +++ b/src/network/access/qhsts.cpp @@ -37,13 +37,16 @@ ** ****************************************************************************/ -#include "qhstsstore_p.h" #include "qhsts_p.h" #include "QtCore/private/qipaddress_p.h" #include "QtCore/qvector.h" #include "QtCore/qlist.h" +#if QT_CONFIG(settings) +#include "qhstsstore_p.h" +#endif // QT_CONFIG(settings) + QT_BEGIN_NAMESPACE static bool is_valid_domain_name(const QString &host) @@ -83,8 +86,10 @@ void QHstsCache::updateFromHeaders(const QList> &h QHstsHeaderParser parser; if (parser.parse(headers)) { updateKnownHost(url.host(), parser.expirationDate(), parser.includeSubDomains()); +#if QT_CONFIG(settings) if (hstsStore) hstsStore->synchronize(); +#endif // QT_CONFIG(settings) } } @@ -93,12 +98,14 @@ void QHstsCache::updateFromPolicies(const QVector &policies) for (const auto &policy : policies) updateKnownHost(policy.host(), policy.expiry(), policy.includesSubDomains()); +#if QT_CONFIG(settings) if (hstsStore && policies.size()) { // These policies are coming either from store or from QNAM's setter // function. As a result we can notice expired or new policies, time // to sync ... hstsStore->synchronize(); } +#endif // QT_CONFIG(settings) } void QHstsCache::updateKnownHost(const QUrl &url, const QDateTime &expires, @@ -108,8 +115,10 @@ void QHstsCache::updateKnownHost(const QUrl &url, const QDateTime &expires, return; updateKnownHost(url.host(), expires, includeSubDomains); +#if QT_CONFIG(settings) if (hstsStore) hstsStore->synchronize(); +#endif // QT_CONFIG(settings) } void QHstsCache::updateKnownHost(const QString &host, const QDateTime &expires, @@ -137,8 +146,10 @@ void QHstsCache::updateKnownHost(const QString &host, const QDateTime &expires, } knownHosts.insert(pos, {hostName, newPolicy}); +#if QT_CONFIG(settings) if (hstsStore) hstsStore->addToObserved(newPolicy); +#endif // QT_CONFIG(settings) return; } @@ -149,8 +160,10 @@ void QHstsCache::updateKnownHost(const QString &host, const QDateTime &expires, else return; +#if QT_CONFIG(settings) if (hstsStore) hstsStore->addToObserved(newPolicy); +#endif // QT_CONFIG(settings) } bool QHstsCache::isKnownHost(const QUrl &url) const @@ -187,10 +200,12 @@ bool QHstsCache::isKnownHost(const QUrl &url) const if (pos != knownHosts.end()) { if (pos->second.isExpired()) { knownHosts.erase(pos); +#if QT_CONFIG(settings) if (hstsStore) { // Inform our store that this policy has expired. hstsStore->addToObserved(pos->second); } +#endif // QT_CONFIG(settings) } else if (!superDomainMatch || pos->second.includesSubDomains()) { return true; } @@ -221,6 +236,7 @@ QVector QHstsCache::policies() const return values; } +#if QT_CONFIG(settings) void QHstsCache::setStore(QHstsStore *store) { // Caller retains ownership of store, which must outlive this cache. @@ -248,6 +264,7 @@ void QHstsCache::setStore(QHstsStore *store) updateFromPolicies(restored); } } +#endif // QT_CONFIG(settings) // The parser is quite simple: 'nextToken' knowns exactly what kind of tokens // are valid and it will return false if something else was found; then diff --git a/src/network/access/qhsts_p.h b/src/network/access/qhsts_p.h index bc8708341d..c219d9eab5 100644 --- a/src/network/access/qhsts_p.h +++ b/src/network/access/qhsts_p.h @@ -69,8 +69,6 @@ QT_BEGIN_NAMESPACE template class QList; template class QVector; -class QHstsStore; - class Q_AUTOTEST_EXPORT QHstsCache { public: @@ -85,7 +83,9 @@ public: QVector policies() const; - void setStore(QHstsStore *store); +#if QT_CONFIG(settings) + void setStore(class QHstsStore *store); +#endif // QT_CONFIG(settings) private: @@ -119,7 +119,9 @@ private: }; mutable std::map knownHosts; +#if QT_CONFIG(settings) QHstsStore *hstsStore = nullptr; +#endif // QT_CONFIG(settings) }; class Q_AUTOTEST_EXPORT QHstsHeaderParser diff --git a/src/network/access/qhstsstore_p.h b/src/network/access/qhstsstore_p.h index 13042839c4..e82596b250 100644 --- a/src/network/access/qhstsstore_p.h +++ b/src/network/access/qhstsstore_p.h @@ -53,6 +53,8 @@ #include +QT_REQUIRE_CONFIG(settings); + #include #include diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index 96e3f92db1..a2649fe77c 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -48,6 +48,10 @@ #include "qhstspolicy.h" #include "qhsts_p.h" +#if QT_CONFIG(settings) +#include "qhstsstore_p.h" +#endif // QT_CONFIG(settings) + #include "QtNetwork/qnetworksession.h" #include "QtNetwork/private/qsharednetworksession_p.h" @@ -760,9 +764,14 @@ bool QNetworkAccessManager::isStrictTransportSecurityEnabled() const void QNetworkAccessManager::enableStrictTransportSecurityStore(bool enabled, const QString &storeDir) { +#if QT_CONFIG(settings) Q_D(QNetworkAccessManager); d->stsStore.reset(enabled ? new QHstsStore(storeDir) : nullptr); d->stsCache.setStore(d->stsStore.data()); +#else + Q_UNUSED(enabled) Q_UNUSED(storeDir) + qWarning("HSTS permanent store requires the feature 'settings' enabled"); +#endif // QT_CONFIG(settings) } /*! @@ -776,8 +785,12 @@ void QNetworkAccessManager::enableStrictTransportSecurityStore(bool enabled, con bool QNetworkAccessManager::isStrictTransportSecurityStoreEnabled() const { +#if QT_CONFIG(settings) Q_D(const QNetworkAccessManager); return bool(d->stsStore.data()); +#else + return false; +#endif // QT_CONFIG(settings) } /*! diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h index ffed24a314..5cab4928e4 100644 --- a/src/network/access/qnetworkaccessmanager_p.h +++ b/src/network/access/qnetworkaccessmanager_p.h @@ -56,7 +56,6 @@ #include "qnetworkaccesscache_p.h" #include "qnetworkaccessbackend_p.h" #include "qnetworkrequest.h" -#include "qhstsstore_p.h" #include "qhsts_p.h" #include "private/qobject_p.h" #include "QtNetwork/qnetworkproxy.h" @@ -66,6 +65,10 @@ #include "QtNetwork/qnetworkconfigmanager.h" #endif +#if QT_CONFIG(settings) +#include "qhstsstore_p.h" +#endif // QT_CONFIG(settings) + QT_BEGIN_NAMESPACE class QAuthenticator; @@ -215,7 +218,9 @@ public: Q_AUTOTEST_EXPORT static void clearConnectionCache(QNetworkAccessManager *manager); QHstsCache stsCache; +#if QT_CONFIG(settings) QScopedPointer stsStore; +#endif // QT_CONFIG(settings) bool stsEnabled = false; #ifndef QT_NO_BEARERMANAGEMENT -- cgit v1.2.3