summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/network/ssl/qsslconfiguration.cpp3
-rw-r--r--src/network/ssl/qsslconfiguration_p.h2
-rw-r--r--src/network/ssl/qsslsocket.cpp15
-rw-r--r--src/network/ssl/qsslsocket_p.h2
-rw-r--r--tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/tst_qsslsocket_onDemandCertificates_member.cpp28
-rw-r--r--tests/manual/qnetworkreply/main.cpp43
-rw-r--r--tests/manual/qnetworkreply/qnetworkreply.pro2
7 files changed, 90 insertions, 5 deletions
diff --git a/src/network/ssl/qsslconfiguration.cpp b/src/network/ssl/qsslconfiguration.cpp
index 46aa1a1eb5..0ae67b3c1f 100644
--- a/src/network/ssl/qsslconfiguration.cpp
+++ b/src/network/ssl/qsslconfiguration.cpp
@@ -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;
}
/*!
diff --git a/src/network/ssl/qsslconfiguration_p.h b/src/network/ssl/qsslconfiguration_p.h
index 841641d6aa..3e6e43361d 100644
--- a/src/network/ssl/qsslconfiguration_p.h
+++ b/src/network/ssl/qsslconfiguration_p.h
@@ -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;
diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp
index 87ea975bec..cfc3c19bba 100644
--- a/src/network/ssl/qsslsocket.cpp
+++ b/src/network/ssl/qsslsocket.cpp
@@ -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;
}
/*!
@@ -2381,6 +2386,14 @@ QByteArray QSslSocketPrivate::peek(qint64 maxSize)
/*!
\internal
*/
+bool QSslSocketPrivate::rootCertOnDemandLoadingSupported()
+{
+ return s_loadRootCertsOnDemand;
+}
+
+/*!
+ \internal
+*/
QList<QByteArray> QSslSocketPrivate::unixRootCertDirectories()
{
return QList<QByteArray>() << "/etc/ssl/certs/" // (K)ubuntu, OpenSUSE, Mandriva, MeeGo ...
diff --git a/src/network/ssl/qsslsocket_p.h b/src/network/ssl/qsslsocket_p.h
index 3dc80ea22a..851dec5840 100644
--- a/src/network/ssl/qsslsocket_p.h
+++ b/src/network/ssl/qsslsocket_p.h
@@ -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();
diff --git a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/tst_qsslsocket_onDemandCertificates_member.cpp b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/tst_qsslsocket_onDemandCertificates_member.cpp
index bf6fde896b..eb04be10c8 100644
--- a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/tst_qsslsocket_onDemandCertificates_member.cpp
+++ b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/tst_qsslsocket_onDemandCertificates_member.cpp
@@ -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
diff --git a/tests/manual/qnetworkreply/main.cpp b/tests/manual/qnetworkreply/main.cpp
index b8b20ec4da..feb07b4c7d 100644
--- a/tests/manual/qnetworkreply/main.cpp
+++ b/tests/manual/qnetworkreply/main.cpp
@@ -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)
diff --git a/tests/manual/qnetworkreply/qnetworkreply.pro b/tests/manual/qnetworkreply/qnetworkreply.pro
index 3d98ee429f..64666103a0 100644
--- a/tests/manual/qnetworkreply/qnetworkreply.pro
+++ b/tests/manual/qnetworkreply/qnetworkreply.pro
@@ -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