Skip to content

Commit

Permalink
Protect HSTS code for no-feature-settings build
Browse files Browse the repository at this point in the history
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 <[email protected]>
Reviewed-by: Edward Welbourne <[email protected]>
  • Loading branch information
Timur Pocheptsov committed Sep 24, 2018
1 parent 4fc4f7b commit 4b7ff8e
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 9 deletions.
14 changes: 10 additions & 4 deletions src/network/access/access.pri
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand All @@ -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 += \
Expand All @@ -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)
Expand Down
19 changes: 18 additions & 1 deletion src/network/access/qhsts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -83,8 +86,10 @@ void QHstsCache::updateFromHeaders(const QList<QPair<QByteArray, QByteArray>> &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)
}
}

Expand All @@ -93,12 +98,14 @@ void QHstsCache::updateFromPolicies(const QVector<QHstsPolicy> &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,
Expand All @@ -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,
Expand Down Expand Up @@ -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;
}

Expand All @@ -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
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -221,6 +236,7 @@ QVector<QHstsPolicy> QHstsCache::policies() const
return values;
}

#if QT_CONFIG(settings)
void QHstsCache::setStore(QHstsStore *store)
{
// Caller retains ownership of store, which must outlive this cache.
Expand Down Expand Up @@ -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
Expand Down
8 changes: 5 additions & 3 deletions src/network/access/qhsts_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,6 @@ QT_BEGIN_NAMESPACE
template<typename T> class QList;
template <typename T> class QVector;

class QHstsStore;

class Q_AUTOTEST_EXPORT QHstsCache
{
public:
Expand All @@ -85,7 +83,9 @@ class Q_AUTOTEST_EXPORT QHstsCache

QVector<QHstsPolicy> policies() const;

void setStore(QHstsStore *store);
#if QT_CONFIG(settings)
void setStore(class QHstsStore *store);
#endif // QT_CONFIG(settings)

private:

Expand Down Expand Up @@ -119,7 +119,9 @@ class Q_AUTOTEST_EXPORT QHstsCache
};

mutable std::map<HostName, QHstsPolicy> knownHosts;
#if QT_CONFIG(settings)
QHstsStore *hstsStore = nullptr;
#endif // QT_CONFIG(settings)
};

class Q_AUTOTEST_EXPORT QHstsHeaderParser
Expand Down
2 changes: 2 additions & 0 deletions src/network/access/qhstsstore_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@

#include <QtNetwork/private/qtnetworkglobal_p.h>

QT_REQUIRE_CONFIG(settings);

#include <QtCore/qsettings.h>
#include <QtCore/qvector.h>

Expand Down
13 changes: 13 additions & 0 deletions src/network/access/qnetworkaccessmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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)
}

/*!
Expand All @@ -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)
}

/*!
Expand Down
7 changes: 6 additions & 1 deletion src/network/access/qnetworkaccessmanager_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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;
Expand Down Expand Up @@ -215,7 +218,9 @@ class QNetworkAccessManagerPrivate: public QObjectPrivate
Q_AUTOTEST_EXPORT static void clearConnectionCache(QNetworkAccessManager *manager);

QHstsCache stsCache;
#if QT_CONFIG(settings)
QScopedPointer<QHstsStore> stsStore;
#endif // QT_CONFIG(settings)
bool stsEnabled = false;

#ifndef QT_NO_BEARERMANAGEMENT
Expand Down

0 comments on commit 4b7ff8e

Please sign in to comment.