QSslConfiguration: toggle on demand loading of root certs properly
make sure we keep track of when we can load root certs and when we cannot (we cannot when the developer set the certs explicitly). This is implemented the same way for QSslSocket already, and needs to be duplicated because we have 2 methods for setting CA certificates: one in QSslSocket and one in QSslConfiguration. In addition, adapt the auto test which checks whether setting a default QSslConfiguration works: There is no way to set on demand loading through the API, so it should be enabled by default. Task-number: QTBUG-29103 Change-Id: I5146128aaa385dfcc0ad1e0ef81a92d9350ec5f2 Reviewed-by: Richard J. Moore <rich@kde.org>
This commit is contained in:
parent
786a6466e8
commit
ce35c0db0d
@ -181,6 +181,7 @@ bool QSslConfiguration::operator==(const QSslConfiguration &other) const
|
||||
d->protocol == other.d->protocol &&
|
||||
d->peerVerifyMode == other.d->peerVerifyMode &&
|
||||
d->peerVerifyDepth == other.d->peerVerifyDepth &&
|
||||
d->allowRootCertOnDemandLoading == other.d->allowRootCertOnDemandLoading &&
|
||||
d->sslOptions == other.d->sslOptions;
|
||||
}
|
||||
|
||||
@ -208,6 +209,7 @@ bool QSslConfiguration::isNull() const
|
||||
return (d->protocol == QSsl::SecureProtocols &&
|
||||
d->peerVerifyMode == QSslSocket::AutoVerifyPeer &&
|
||||
d->peerVerifyDepth == 0 &&
|
||||
d->allowRootCertOnDemandLoading == true &&
|
||||
d->caCertificates.count() == 0 &&
|
||||
d->ciphers.count() == 0 &&
|
||||
d->localCertificate.isNull() &&
|
||||
@ -519,6 +521,7 @@ QList<QSslCertificate> QSslConfiguration::caCertificates() const
|
||||
void QSslConfiguration::setCaCertificates(const QList<QSslCertificate> &certificates)
|
||||
{
|
||||
d->caCertificates = certificates;
|
||||
d->allowRootCertOnDemandLoading = false;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -83,6 +83,7 @@ public:
|
||||
: protocol(QSsl::SecureProtocols),
|
||||
peerVerifyMode(QSslSocket::AutoVerifyPeer),
|
||||
peerVerifyDepth(0),
|
||||
allowRootCertOnDemandLoading(true),
|
||||
sslOptions(QSslConfigurationPrivate::defaultSslOptions)
|
||||
{ }
|
||||
|
||||
@ -98,6 +99,7 @@ public:
|
||||
QSsl::SslProtocol protocol;
|
||||
QSslSocket::PeerVerifyMode peerVerifyMode;
|
||||
int peerVerifyDepth;
|
||||
bool allowRootCertOnDemandLoading;
|
||||
|
||||
QSsl::SslOptions sslOptions;
|
||||
|
||||
|
@ -903,7 +903,12 @@ void QSslSocket::setSslConfiguration(const QSslConfiguration &configuration)
|
||||
d->configuration.peerVerifyMode = configuration.peerVerifyMode();
|
||||
d->configuration.protocol = configuration.protocol();
|
||||
d->configuration.sslOptions = configuration.d->sslOptions;
|
||||
d->allowRootCertOnDemandLoading = false;
|
||||
|
||||
// if the CA certificates were set explicitly (either via
|
||||
// QSslConfiguration::setCaCertificates() or QSslSocket::setCaCertificates(),
|
||||
// we cannot load the certificates on demand
|
||||
if (!configuration.d->allowRootCertOnDemandLoading)
|
||||
d->allowRootCertOnDemandLoading = false;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -2378,6 +2383,14 @@ QByteArray QSslSocketPrivate::peek(qint64 maxSize)
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
bool QSslSocketPrivate::rootCertOnDemandLoadingSupported()
|
||||
{
|
||||
return s_loadRootCertsOnDemand;
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
|
@ -182,6 +182,8 @@ public:
|
||||
virtual QSslCipher sessionCipher() const = 0;
|
||||
virtual void continueHandshake() = 0;
|
||||
|
||||
Q_AUTOTEST_EXPORT static bool rootCertOnDemandLoadingSupported();
|
||||
|
||||
private:
|
||||
static bool ensureLibraryLoaded();
|
||||
static void ensureCiphersAndCertsLoaded();
|
||||
|
@ -46,7 +46,10 @@
|
||||
#include <QNetworkProxy>
|
||||
#include <QAuthenticator>
|
||||
|
||||
#ifdef QT_BUILD_INTERNAL
|
||||
#include "private/qhostinfo_p.h"
|
||||
#include "private/qsslsocket_p.h"
|
||||
#endif
|
||||
|
||||
#include "../../../network-settings.h"
|
||||
|
||||
@ -211,12 +214,31 @@ void tst_QSslSocket_onDemandCertificates_member::onDemandRootCertLoadingMemberMe
|
||||
socket3->connectToHostEncrypted(host, 443);
|
||||
QVERIFY(!socket3->waitForEncrypted());
|
||||
|
||||
// setting empty SSL configuration explicitly -> should not work
|
||||
// setting empty SSL configuration explicitly -> depends on on-demand loading
|
||||
QSslSocketPtr socket4 = newSocket();
|
||||
this->socket = socket4.data();
|
||||
socket4->setSslConfiguration(QSslConfiguration());
|
||||
QSslConfiguration conf;
|
||||
socket4->setSslConfiguration(conf);
|
||||
socket4->connectToHostEncrypted(host, 443);
|
||||
QVERIFY(!socket4->waitForEncrypted());
|
||||
#ifdef QT_BUILD_INTERNAL
|
||||
bool rootCertLoadingAllowed = QSslSocketPrivate::rootCertOnDemandLoadingSupported();
|
||||
#if defined(Q_OS_LINUX) || defined (Q_OS_BLACKBERRY)
|
||||
QCOMPARE(rootCertLoadingAllowed, true);
|
||||
#elif defined(Q_OS_MAC)
|
||||
QCOMPARE(rootCertLoadingAllowed, false);
|
||||
#endif // other platforms: undecided (Windows: depends on the version)
|
||||
// when we allow on demand loading, it is enabled by default,
|
||||
// so on Unix it will work without setting any certificates. Otherwise,
|
||||
// the configuration contains an empty set of certificates
|
||||
// and will fail.
|
||||
bool works;
|
||||
#if defined (Q_OS_WIN)
|
||||
works = false; // on Windows, this won't work even though we use on demand loading
|
||||
#else
|
||||
works = rootCertLoadingAllowed;
|
||||
#endif
|
||||
QCOMPARE(socket4->waitForEncrypted(), works);
|
||||
#endif // QT_BUILD_INTERNAL
|
||||
}
|
||||
|
||||
#endif // QT_NO_OPENSSL
|
||||
|
@ -46,8 +46,13 @@
|
||||
#include <QtNetwork/qnetworkreply.h>
|
||||
#include <QtNetwork/qnetworkrequest.h>
|
||||
#include <QtNetwork/qnetworkaccessmanager.h>
|
||||
#include <QtNetwork/qsslconfiguration.h>
|
||||
#include "../../auto/network-settings.h"
|
||||
|
||||
#ifdef QT_BUILD_INTERNAL
|
||||
#include "private/qsslsocket_p.h"
|
||||
#endif
|
||||
|
||||
#define BANDWIDTH_LIMIT_BYTES (1024*100)
|
||||
#define TIME_ESTIMATION_SECONDS (97)
|
||||
|
||||
@ -58,6 +63,8 @@ private slots:
|
||||
void initTestCase();
|
||||
void limiting_data();
|
||||
void limiting();
|
||||
void setSslConfiguration_data();
|
||||
void setSslConfiguration();
|
||||
};
|
||||
|
||||
QNetworkReply *reply;
|
||||
@ -129,6 +136,42 @@ void tst_qnetworkreply::limiting()
|
||||
QVERIFY(!QTestEventLoop::instance().timeout());
|
||||
}
|
||||
|
||||
void tst_qnetworkreply::setSslConfiguration_data()
|
||||
{
|
||||
QTest::addColumn<QUrl>("url");
|
||||
QTest::addColumn<bool>("works");
|
||||
|
||||
QTest::newRow("codereview.qt-project.org") << QUrl("https://codereview.qt-project.org") << true;
|
||||
QTest::newRow("test-server") << QUrl("https://" + QtNetworkSettings::serverName() + "/") << false;
|
||||
}
|
||||
|
||||
void tst_qnetworkreply::setSslConfiguration()
|
||||
{
|
||||
QFETCH(QUrl, url);
|
||||
QNetworkRequest request(url);
|
||||
QSslConfiguration conf = request.sslConfiguration();
|
||||
conf.setProtocol(QSsl::TlsV1_0); // TLS 1.0 will be used anyway, just make sure we change the configuration
|
||||
request.setSslConfiguration(conf);
|
||||
QNetworkAccessManager manager;
|
||||
reply = manager.get(request);
|
||||
QObject::connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
|
||||
QTestEventLoop::instance().enterLoop(15);
|
||||
QVERIFY(!QTestEventLoop::instance().timeout());
|
||||
#ifdef QT_BUILD_INTERNAL
|
||||
QFETCH(bool, works);
|
||||
bool rootCertLoadingAllowed = QSslSocketPrivate::rootCertOnDemandLoadingSupported();
|
||||
#if defined(Q_OS_LINUX) || defined (Q_OS_BLACKBERRY)
|
||||
QCOMPARE(rootCertLoadingAllowed, true);
|
||||
#elif defined(Q_OS_MAC)
|
||||
QCOMPARE(rootCertLoadingAllowed, false);
|
||||
#endif // other platforms: undecided (Windows: depends on the version)
|
||||
if (works) {
|
||||
QCOMPARE(reply->error(), QNetworkReply::NoError);
|
||||
} else {
|
||||
QCOMPARE(reply->error(), QNetworkReply::SslHandshakeFailedError);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_qnetworkreply)
|
||||
|
||||
|
@ -2,7 +2,7 @@ TEMPLATE = app
|
||||
TARGET = tst_qnetworkreply
|
||||
|
||||
QT -= gui
|
||||
QT += network testlib
|
||||
QT += core-private network network-private testlib
|
||||
|
||||
SOURCES += main.cpp
|
||||
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
|
||||
|
Loading…
Reference in New Issue
Block a user