summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/src/snippets/code/src_network_access_qnetworkreply.cpp10
-rw-r--r--doc/src/snippets/code/src_network_ssl_qsslsocket.cpp11
-rw-r--r--src/network/access/qhttpnetworkconnection.cpp24
-rw-r--r--src/network/access/qhttpnetworkconnection_p.h6
-rw-r--r--src/network/access/qhttpnetworkreply.cpp7
-rw-r--r--src/network/access/qhttpnetworkreply_p.h1
-rw-r--r--src/network/access/qnetworkaccessbackend.cpp6
-rw-r--r--src/network/access/qnetworkaccessbackend_p.h1
-rw-r--r--src/network/access/qnetworkaccessdebugpipebackend.cpp1
-rw-r--r--src/network/access/qnetworkaccesshttpbackend.cpp18
-rw-r--r--src/network/access/qnetworkaccesshttpbackend_p.h4
-rw-r--r--src/network/access/qnetworkreply.cpp34
-rw-r--r--src/network/access/qnetworkreply.h1
-rw-r--r--src/network/access/qnetworkreplyimpl.cpp6
-rw-r--r--src/network/access/qnetworkreplyimpl_p.h1
-rw-r--r--src/network/ssl/qsslsocket.cpp36
-rw-r--r--src/network/ssl/qsslsocket.h1
-rw-r--r--src/network/ssl/qsslsocket_openssl.cpp22
-rw-r--r--src/network/ssl/qsslsocket_p.h3
-rw-r--r--tests/auto/qnetworkreply/tst_qnetworkreply.cpp88
-rw-r--r--tests/auto/qsslsocket/tst_qsslsocket.cpp84
21 files changed, 348 insertions, 17 deletions
diff --git a/doc/src/snippets/code/src_network_access_qnetworkreply.cpp b/doc/src/snippets/code/src_network_access_qnetworkreply.cpp
new file mode 100644
index 0000000..78b388b
--- /dev/null
+++ b/doc/src/snippets/code/src_network_access_qnetworkreply.cpp
@@ -0,0 +1,10 @@
+//! [0]
+QList<QSslCertificate> cert = QSslCertificate::fromPath(QLatin1String("server-certificate.pem"));
+QSslError error(QSslError::SelfSignedCertificate, cert.at(0));
+QList<QSslError> expectedSslErrors;
+expectedSslErrors.append(error);
+
+QNetworkReply *reply = manager.get(QNetworkRequest(QUrl("https://server.tld/index.html")));
+reply->ignoreSslErrors(expectedSslErrors);
+// here connect signals etc.
+//! [0]
diff --git a/doc/src/snippets/code/src_network_ssl_qsslsocket.cpp b/doc/src/snippets/code/src_network_ssl_qsslsocket.cpp
index afffbab..7845e9b 100644
--- a/doc/src/snippets/code/src_network_ssl_qsslsocket.cpp
+++ b/doc/src/snippets/code/src_network_ssl_qsslsocket.cpp
@@ -54,3 +54,14 @@ socket->connectToHostEncrypted("imap", 993);
if (socket->waitForEncrypted(1000))
qDebug("Encrypted!");
//! [5]
+
+//! [6]
+QList<QSslCertificate> cert = QSslCertificate::fromPath(QLatin1String("server-certificate.pem"));
+QSslError error(QSslError::SelfSignedCertificate, cert.at(0));
+QList<QSslError> expectedSslErrors;
+expectedSslErrors.append(error);
+
+QSslSocket socket;
+socket.ignoreSslErrors(expectedSslErrors);
+socket.connectToHostEncrypted("server.tld", 443);
+//! [6]
diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp
index c661596..c824fac 100644
--- a/src/network/access/qhttpnetworkconnection.cpp
+++ b/src/network/access/qhttpnetworkconnection.cpp
@@ -340,8 +340,9 @@ bool QHttpNetworkConnectionPrivate::ensureConnection(QAbstractSocket *socket)
#ifndef QT_NO_OPENSSL
QSslSocket *sslSocket = qobject_cast<QSslSocket*>(socket);
sslSocket->connectToHostEncrypted(connectHost, connectPort);
- if (channels[index].ignoreSSLErrors)
+ if (channels[index].ignoreAllSslErrors)
sslSocket->ignoreSslErrors();
+ sslSocket->ignoreSslErrors(channels[index].ignoreSslErrorsList);
#else
emitReplyError(socket, channels[index].reply, QNetworkReply::ProtocolUnknownError);
#endif
@@ -1448,15 +1449,32 @@ void QHttpNetworkConnection::ignoreSslErrors(int channel)
if (channel == -1) { // ignore for all channels
for (int i = 0; i < d->channelCount; ++i) {
static_cast<QSslSocket *>(d->channels[i].socket)->ignoreSslErrors();
- d->channels[i].ignoreSSLErrors = true;
+ d->channels[i].ignoreAllSslErrors = true;
}
} else {
static_cast<QSslSocket *>(d->channels[channel].socket)->ignoreSslErrors();
- d->channels[channel].ignoreSSLErrors = true;
+ d->channels[channel].ignoreAllSslErrors = true;
}
}
+void QHttpNetworkConnection::ignoreSslErrors(const QList<QSslError> &errors, int channel)
+{
+ Q_D(QHttpNetworkConnection);
+ if (!d->encrypt)
+ return;
+
+ if (channel == -1) { // ignore for all channels
+ for (int i = 0; i < d->channelCount; ++i) {
+ static_cast<QSslSocket *>(d->channels[i].socket)->ignoreSslErrors(errors);
+ d->channels[i].ignoreSslErrorsList = errors;
+ }
+
+ } else {
+ static_cast<QSslSocket *>(d->channels[channel].socket)->ignoreSslErrors(errors);
+ d->channels[channel].ignoreSslErrorsList = errors;
+ }
+}
#endif //QT_NO_OPENSSL
diff --git a/src/network/access/qhttpnetworkconnection_p.h b/src/network/access/qhttpnetworkconnection_p.h
index 842a2f4..52a73a7 100644
--- a/src/network/access/qhttpnetworkconnection_p.h
+++ b/src/network/access/qhttpnetworkconnection_p.h
@@ -117,6 +117,7 @@ public:
#ifndef QT_NO_OPENSSL
void setSslConfiguration(const QSslConfiguration &config);
void ignoreSslErrors(int channel = -1);
+ void ignoreSslErrors(const QList<QSslError> &errors, int channel = -1);
Q_SIGNALS:
void sslErrors(const QList<QSslError> &errors);
@@ -241,13 +242,14 @@ public:
QAuthenticator authenticator;
QAuthenticator proxyAuthenticator;
#ifndef QT_NO_OPENSSL
- bool ignoreSSLErrors;
+ bool ignoreAllSslErrors;
+ QList<QSslError> ignoreSslErrorsList;
#endif
Channel() : socket(0), state(IdleState), reply(0), written(0), bytesTotal(0), resendCurrent(false),
lastStatus(0), pendingEncrypt(false), reconnectAttempts(2),
authMehtod(QAuthenticatorPrivate::None), proxyAuthMehtod(QAuthenticatorPrivate::None)
#ifndef QT_NO_OPENSSL
- , ignoreSSLErrors(false)
+ , ignoreAllSslErrors(false)
#endif
{}
};
diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp
index 2fe0d78..a623999 100644
--- a/src/network/access/qhttpnetworkreply.cpp
+++ b/src/network/access/qhttpnetworkreply.cpp
@@ -712,6 +712,13 @@ void QHttpNetworkReply::ignoreSslErrors()
d->connection->ignoreSslErrors();
}
+void QHttpNetworkReply::ignoreSslErrors(const QList<QSslError> &errors)
+{
+ Q_D(QHttpNetworkReply);
+ if (d->connection)
+ d->connection->ignoreSslErrors(errors);
+}
+
#endif //QT_NO_OPENSSL
diff --git a/src/network/access/qhttpnetworkreply_p.h b/src/network/access/qhttpnetworkreply_p.h
index fbbee12..575e824 100644
--- a/src/network/access/qhttpnetworkreply_p.h
+++ b/src/network/access/qhttpnetworkreply_p.h
@@ -131,6 +131,7 @@ public:
QSslConfiguration sslConfiguration() const;
void setSslConfiguration(const QSslConfiguration &config);
void ignoreSslErrors();
+ void ignoreSslErrors(const QList<QSslError> &errors);
Q_SIGNALS:
void sslErrors(const QList<QSslError> &errors);
diff --git a/src/network/access/qnetworkaccessbackend.cpp b/src/network/access/qnetworkaccessbackend.cpp
index 9e17b54..caaa38e 100644
--- a/src/network/access/qnetworkaccessbackend.cpp
+++ b/src/network/access/qnetworkaccessbackend.cpp
@@ -165,6 +165,12 @@ void QNetworkAccessBackend::ignoreSslErrors()
// do nothing
}
+void QNetworkAccessBackend::ignoreSslErrors(const QList<QSslError> &errors)
+{
+ Q_UNUSED(errors);
+ // do nothing
+}
+
void QNetworkAccessBackend::fetchSslConfiguration(QSslConfiguration &) const
{
// do nothing
diff --git a/src/network/access/qnetworkaccessbackend_p.h b/src/network/access/qnetworkaccessbackend_p.h
index 553b795..27da5bc 100644
--- a/src/network/access/qnetworkaccessbackend_p.h
+++ b/src/network/access/qnetworkaccessbackend_p.h
@@ -118,6 +118,7 @@ public:
virtual void downstreamReadyWrite();
virtual void copyFinished(QIODevice *);
virtual void ignoreSslErrors();
+ virtual void ignoreSslErrors(const QList<QSslError> &errors);
virtual void fetchSslConfiguration(QSslConfiguration &configuration) const;
virtual void setSslConfiguration(const QSslConfiguration &configuration);
diff --git a/src/network/access/qnetworkaccessdebugpipebackend.cpp b/src/network/access/qnetworkaccessdebugpipebackend.cpp
index 2b3c128..394e196 100644
--- a/src/network/access/qnetworkaccessdebugpipebackend.cpp
+++ b/src/network/access/qnetworkaccessdebugpipebackend.cpp
@@ -280,6 +280,7 @@ void QNetworkAccessDebugPipeBackend::socketConnected()
bool QNetworkAccessDebugPipeBackend::waitForDownstreamReadyRead(int ms)
{
+ Q_UNUSED(ms);
qCritical("QNetworkAccess: Debug pipe backend does not support waitForReadyRead()");
return false;
}
diff --git a/src/network/access/qnetworkaccesshttpbackend.cpp b/src/network/access/qnetworkaccesshttpbackend.cpp
index 9c36026..5c85735 100644
--- a/src/network/access/qnetworkaccesshttpbackend.cpp
+++ b/src/network/access/qnetworkaccesshttpbackend.cpp
@@ -294,7 +294,7 @@ public:
QNetworkAccessHttpBackend::QNetworkAccessHttpBackend()
: QNetworkAccessBackend(), httpReply(0), http(0), uploadDevice(0)
#ifndef QT_NO_OPENSSL
- , pendingSslConfiguration(0), pendingIgnoreSslErrors(false)
+ , pendingSslConfiguration(0), pendingIgnoreAllSslErrors(false)
#endif
{
}
@@ -521,8 +521,9 @@ void QNetworkAccessHttpBackend::postRequest()
#ifndef QT_NO_OPENSSL
if (pendingSslConfiguration)
httpReply->setSslConfiguration(*pendingSslConfiguration);
- if (pendingIgnoreSslErrors)
+ if (pendingIgnoreAllSslErrors)
httpReply->ignoreSslErrors();
+ httpReply->ignoreSslErrors(pendingIgnoreSslErrorsList);
#endif
connect(httpReply, SIGNAL(readyRead()), SLOT(replyReadyRead()));
@@ -883,7 +884,18 @@ void QNetworkAccessHttpBackend::ignoreSslErrors()
if (httpReply)
httpReply->ignoreSslErrors();
else
- pendingIgnoreSslErrors = true;
+ pendingIgnoreAllSslErrors = true;
+}
+
+void QNetworkAccessHttpBackend::ignoreSslErrors(const QList<QSslError> &errors)
+{
+ if (httpReply) {
+ httpReply->ignoreSslErrors(errors);
+ } else {
+ // the pending list is set if QNetworkReply::ignoreSslErrors(const QList<QSslError> &errors)
+ // is called before QNetworkAccessManager::get() (or post(), etc.)
+ pendingIgnoreSslErrorsList = errors;
+ }
}
void QNetworkAccessHttpBackend::fetchSslConfiguration(QSslConfiguration &config) const
diff --git a/src/network/access/qnetworkaccesshttpbackend_p.h b/src/network/access/qnetworkaccesshttpbackend_p.h
index dec69d0..968f4a5 100644
--- a/src/network/access/qnetworkaccesshttpbackend_p.h
+++ b/src/network/access/qnetworkaccesshttpbackend_p.h
@@ -85,6 +85,7 @@ public:
virtual void copyFinished(QIODevice *);
#ifndef QT_NO_OPENSSL
virtual void ignoreSslErrors();
+ virtual void ignoreSslErrors(const QList<QSslError> &errors);
virtual void fetchSslConfiguration(QSslConfiguration &configuration) const;
virtual void setSslConfiguration(const QSslConfiguration &configuration);
@@ -112,7 +113,8 @@ private:
#ifndef QT_NO_OPENSSL
QSslConfiguration *pendingSslConfiguration;
- bool pendingIgnoreSslErrors;
+ bool pendingIgnoreAllSslErrors;
+ QList<QSslError> pendingIgnoreSslErrorsList;
#endif
void disconnectFromHttp();
diff --git a/src/network/access/qnetworkreply.cpp b/src/network/access/qnetworkreply.cpp
index e807d29..3abf927 100644
--- a/src/network/access/qnetworkreply.cpp
+++ b/src/network/access/qnetworkreply.cpp
@@ -584,6 +584,38 @@ void QNetworkReply::setSslConfiguration(const QSslConfiguration &config)
qt_metacall(QMetaObject::InvokeMetaMethod, id, arr);
}
}
+
+/*!
+ \overload
+ \since 4.6
+
+ If this function is called, the SSL errors given in \a errors
+ will be ignored.
+
+ Note that you can set the expected certificate in the SSL error:
+ If, for instance, you want to issue a request to a server that uses
+ a self-signed certificate, consider the following snippet:
+
+ \snippet doc/src/snippets/code/src_network_access_qnetworkreply.cpp 0
+
+ Multiple calls to this function will replace the list of errors that
+ were passed in previous calls.
+ You can clear the list of errors you want to ignore by calling this
+ function with an empty list.
+
+ \sa sslConfiguration(), sslErrors(), QSslSocket::ignoreSslErrors()
+*/
+void QNetworkReply::ignoreSslErrors(const QList<QSslError> &errors)
+{
+ // do this cryptic trick, because we could not add a virtual method to this class later on
+ // since that breaks binary compatibility
+ int id = metaObject()->indexOfMethod("ignoreSslErrorsImplementation(QList<QSslError>)");
+ if (id != -1) {
+ QList<QSslError> copy(errors);
+ void *arr[] = { 0, &copy };
+ qt_metacall(QMetaObject::InvokeMetaMethod, id, arr);
+ }
+}
#endif
/*!
@@ -598,7 +630,7 @@ void QNetworkReply::setSslConfiguration(const QSslConfiguration &config)
sslErrors() signal, which indicates which errors were
found.
- \sa sslConfiguration(), sslErrors()
+ \sa sslConfiguration(), sslErrors(), QSslSocket::ignoreSslErrors()
*/
void QNetworkReply::ignoreSslErrors()
{
diff --git a/src/network/access/qnetworkreply.h b/src/network/access/qnetworkreply.h
index 30e89f1..679ab71 100644
--- a/src/network/access/qnetworkreply.h
+++ b/src/network/access/qnetworkreply.h
@@ -134,6 +134,7 @@ public:
#ifndef QT_NO_OPENSSL
QSslConfiguration sslConfiguration() const;
void setSslConfiguration(const QSslConfiguration &configuration);
+ void ignoreSslErrors(const QList<QSslError> &errors);
#endif
public Q_SLOTS:
diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp
index 1d4f70e..de7f8b4 100644
--- a/src/network/access/qnetworkreplyimpl.cpp
+++ b/src/network/access/qnetworkreplyimpl.cpp
@@ -659,6 +659,12 @@ void QNetworkReplyImpl::ignoreSslErrors()
d->backend->ignoreSslErrors();
}
+void QNetworkReplyImpl::ignoreSslErrorsImplementation(const QList<QSslError> &errors)
+{
+ Q_D(QNetworkReplyImpl);
+ if (d->backend)
+ d->backend->ignoreSslErrors(errors);
+}
#endif // QT_NO_OPENSSL
/*!
diff --git a/src/network/access/qnetworkreplyimpl_p.h b/src/network/access/qnetworkreplyimpl_p.h
index 83a8aca..fba8d34 100644
--- a/src/network/access/qnetworkreplyimpl_p.h
+++ b/src/network/access/qnetworkreplyimpl_p.h
@@ -89,6 +89,7 @@ public:
Q_INVOKABLE QSslConfiguration sslConfigurationImplementation() const;
Q_INVOKABLE void setSslConfigurationImplementation(const QSslConfiguration &configuration);
virtual void ignoreSslErrors();
+ Q_INVOKABLE virtual void ignoreSslErrorsImplementation(const QList<QSslError> &errors);
#endif
Q_DECLARE_PRIVATE(QNetworkReplyImpl)
diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp
index fc297e4..df0afe3 100644
--- a/src/network/ssl/qsslsocket.cpp
+++ b/src/network/ssl/qsslsocket.cpp
@@ -356,7 +356,7 @@ QSslSocket::~QSslSocket()
want to ignore the errors and continue connecting, you must call
ignoreSslErrors(), either from inside a slot function connected to
the sslErrors() signal, or prior to entering encrypted mode. If
- ignoreSslErrors is not called, the connection is dropped, signal
+ ignoreSslErrors() is not called, the connection is dropped, signal
disconnected() is emitted, and QSslSocket returns to the
UnconnectedState.
@@ -1592,7 +1592,33 @@ void QSslSocket::startServerEncryption()
void QSslSocket::ignoreSslErrors()
{
Q_D(QSslSocket);
- d->ignoreSslErrors = true;
+ d->ignoreAllSslErrors = true;
+}
+
+/*!
+ \overload
+ \since 4.6
+
+ This method tells QSslSocket to ignore only the errors given in \a
+ errors.
+
+ Note that you can set the expected certificate in the SSL error:
+ If, for instance, you want to connect to a server that uses
+ a self-signed certificate, consider the following snippet:
+
+ \snippet doc/src/snippets/code/src_network_ssl_qsslsocket.cpp 6
+
+ Multiple calls to this function will replace the list of errors that
+ were passed in previous calls.
+ You can clear the list of errors you want to ignore by calling this
+ function with an empty list.
+
+ \sa sslErrors()
+*/
+void QSslSocket::ignoreSslErrors(const QList<QSslError> &errors)
+{
+ Q_D(QSslSocket);
+ d->ignoreErrorsList = errors;
}
/*!
@@ -1732,7 +1758,11 @@ void QSslSocketPrivate::init()
mode = QSslSocket::UnencryptedMode;
autoStartHandshake = false;
connectionEncrypted = false;
- ignoreSslErrors = false;
+ ignoreAllSslErrors = false;
+
+ // we don't want to clear the ignoreErrorsList, so
+ // that it is possible setting it before connecting
+// ignoreErrorsList.clear();
readBuffer.clear();
writeBuffer.clear();
diff --git a/src/network/ssl/qsslsocket.h b/src/network/ssl/qsslsocket.h
index 785a083..cab0667 100644
--- a/src/network/ssl/qsslsocket.h
+++ b/src/network/ssl/qsslsocket.h
@@ -169,6 +169,7 @@ public:
QList<QSslError> sslErrors() const;
static bool supportsSsl();
+ void ignoreSslErrors(const QList<QSslError> &errors);
public Q_SLOTS:
void startClientEncryption();
diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp
index ea62a4d..130494e 100644
--- a/src/network/ssl/qsslsocket_openssl.cpp
+++ b/src/network/ssl/qsslsocket_openssl.cpp
@@ -839,7 +839,27 @@ bool QSslSocketBackendPrivate::startHandshake()
if (!errors.isEmpty()) {
sslErrors = errors;
emit q->sslErrors(errors);
- if (doVerifyPeer && !ignoreSslErrors) {
+
+ bool doEmitSslError;
+ if (!ignoreErrorsList.empty()) {
+ // check whether the errors we got are all in the list of expected errors
+ // (applies only if the method QSslSocket::ignoreSslErrors(const QList<QSslError> &errors)
+ // was called)
+ doEmitSslError = false;
+ for (int a = 0; a < errors.count(); a++) {
+ if (!ignoreErrorsList.contains(errors.at(a))) {
+ doEmitSslError = true;
+ break;
+ }
+ }
+ } else {
+ // if QSslSocket::ignoreSslErrors(const QList<QSslError> &errors) was not called and
+ // we get an SSL error, emit a signal unless we ignored all errors (by calling
+ // QSslSocket::ignoreSslErrors() )
+ doEmitSslError = !ignoreAllSslErrors;
+ }
+ // check whether we need to emit an SSL handshake error
+ if (doVerifyPeer && doEmitSslError) {
q->setErrorString(sslErrors.first().errorString());
q->setSocketError(QAbstractSocket::SslHandshakeFailedError);
emit q->error(QAbstractSocket::SslHandshakeFailedError);
diff --git a/src/network/ssl/qsslsocket_p.h b/src/network/ssl/qsslsocket_p.h
index dc8e4f5..8fd2154 100644
--- a/src/network/ssl/qsslsocket_p.h
+++ b/src/network/ssl/qsslsocket_p.h
@@ -79,7 +79,8 @@ public:
QSslSocket::SslMode mode;
bool autoStartHandshake;
bool connectionEncrypted;
- bool ignoreSslErrors;
+ bool ignoreAllSslErrors;
+ QList<QSslError> ignoreErrorsList;
bool* readyReadEmittedPointer;
QRingBuffer readBuffer;
diff --git a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp
index b67c727..788be1e 100644
--- a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp
+++ b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp
@@ -114,6 +114,7 @@ class tst_QNetworkReply: public QObject
MyCookieJar *cookieJar;
#ifndef QT_NO_OPENSSL
QSslConfiguration storedSslConfiguration;
+ QList<QSslError> storedExpectedSslErrors;
#endif
public:
@@ -126,9 +127,11 @@ public Q_SLOTS:
void gotError();
void authenticationRequired(QNetworkReply*,QAuthenticator*);
void proxyAuthenticationRequired(const QNetworkProxy &,QAuthenticator*);
+
#ifndef QT_NO_OPENSSL
void sslErrors(QNetworkReply*,const QList<QSslError> &);
void storeSslConfiguration();
+ void ignoreSslErrorListSlot(QNetworkReply *reply, const QList<QSslError> &);
#endif
protected Q_SLOTS:
@@ -247,6 +250,13 @@ private Q_SLOTS:
void httpConnectionCount();
void httpDownloadPerformance_data();
void httpDownloadPerformance();
+
+#ifndef QT_NO_OPENSSL
+ void ignoreSslErrorsList_data();
+ void ignoreSslErrorsList();
+ void ignoreSslErrorsListWithSlot_data();
+ void ignoreSslErrorsListWithSlot();
+#endif
};
QT_BEGIN_NAMESPACE
@@ -3540,7 +3550,7 @@ void tst_QNetworkReply::httpProxyCommands_data()
<< QUrl("http://0.0.0.0:4443/http-request")
<< QByteArray("HTTP/1.0 200 OK\r\nProxy-Connection: close\r\nContent-Length: 1\r\n\r\n1")
<< "GET http://0.0.0.0:4443/http-request HTTP/1.";
-#ifndef QT_NO_SSL
+#ifndef QT_NO_OPENSSL
QTest::newRow("https")
<< QUrl("https://0.0.0.0:4443/https-request")
<< QByteArray("HTTP/1.0 200 Connection Established\r\n\r\n")
@@ -3832,5 +3842,81 @@ void tst_QNetworkReply::httpDownloadPerformance()
delete reply;
}
+#ifndef QT_NO_OPENSSL
+void tst_QNetworkReply::ignoreSslErrorsList_data()
+{
+ QTest::addColumn<QString>("url");
+ QTest::addColumn<QList<QSslError> >("expectedSslErrors");
+ QTest::addColumn<QNetworkReply::NetworkError>("expectedNetworkError");
+
+ QList<QSslError> expectedSslErrors;
+ // apparently, because of some weird behaviour of SRCDIR, the file name below needs to start with a slash
+ QList<QSslCertificate> certs = QSslCertificate::fromPath(QLatin1String(SRCDIR "/../qsslsocket/certs/qt-test-server-cacert.pem"));
+ QSslError rightError(QSslError::SelfSignedCertificate, certs.at(0));
+ QSslError wrongError(QSslError::SelfSignedCertificate);
+
+ QTest::newRow("SSL-failure-empty-list") << "https://" + QtNetworkSettings::serverName() + "/index.html" << expectedSslErrors << QNetworkReply::SslHandshakeFailedError;
+ expectedSslErrors.append(wrongError);
+ QTest::newRow("SSL-failure-wrong-error") << "https://" + QtNetworkSettings::serverName() + "/index.html" << expectedSslErrors << QNetworkReply::SslHandshakeFailedError;
+ expectedSslErrors.append(rightError);
+ QTest::newRow("allErrorsInExpectedList1") << "https://" + QtNetworkSettings::serverName() + "/index.html" << expectedSslErrors << QNetworkReply::NoError;
+ expectedSslErrors.removeAll(wrongError);
+ QTest::newRow("allErrorsInExpectedList2") << "https://" + QtNetworkSettings::serverName() + "/index.html" << expectedSslErrors << QNetworkReply::NoError;
+ expectedSslErrors.removeAll(rightError);
+ QTest::newRow("SSL-failure-empty-list-again") << "https://" + QtNetworkSettings::serverName() + "/index.html" << expectedSslErrors << QNetworkReply::SslHandshakeFailedError;
+}
+
+void tst_QNetworkReply::ignoreSslErrorsList()
+{
+ QFETCH(QString, url);
+ QNetworkRequest request(url);
+ QNetworkReply *reply = manager.get(request);
+
+ QFETCH(QList<QSslError>, expectedSslErrors);
+ reply->ignoreSslErrors(expectedSslErrors);
+
+ connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
+ QTestEventLoop::instance().enterLoop(10);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+
+ QFETCH(QNetworkReply::NetworkError, expectedNetworkError);
+ QCOMPARE(reply->error(), expectedNetworkError);
+}
+
+void tst_QNetworkReply::ignoreSslErrorsListWithSlot_data()
+{
+ ignoreSslErrorsList_data();
+}
+
+// this is not a test, just a slot called in the test below
+void tst_QNetworkReply::ignoreSslErrorListSlot(QNetworkReply *reply, const QList<QSslError> &)
+{
+ reply->ignoreSslErrors(storedExpectedSslErrors);
+}
+
+// do the same as in ignoreSslErrorsList, but ignore the errors in the slot
+void tst_QNetworkReply::ignoreSslErrorsListWithSlot()
+{
+ QFETCH(QString, url);
+ QNetworkRequest request(url);
+ QNetworkReply *reply = manager.get(request);
+
+ QFETCH(QList<QSslError>, expectedSslErrors);
+ // store the errors to ignore them later in the slot connected below
+ storedExpectedSslErrors = expectedSslErrors;
+ connect(&manager, SIGNAL(sslErrors(QNetworkReply *, const QList<QSslError> &)),
+ this, SLOT(ignoreSslErrorListSlot(QNetworkReply *, const QList<QSslError> &)));
+
+
+ connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
+ QTestEventLoop::instance().enterLoop(10);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+
+ QFETCH(QNetworkReply::NetworkError, expectedNetworkError);
+ QCOMPARE(reply->error(), expectedNetworkError);
+}
+
+#endif // QT_NO_OPENSSL
+
QTEST_MAIN(tst_QNetworkReply)
#include "tst_qnetworkreply.moc"
diff --git a/tests/auto/qsslsocket/tst_qsslsocket.cpp b/tests/auto/qsslsocket/tst_qsslsocket.cpp
index bc9d1ca..23eee29 100644
--- a/tests/auto/qsslsocket/tst_qsslsocket.cpp
+++ b/tests/auto/qsslsocket/tst_qsslsocket.cpp
@@ -173,6 +173,10 @@ private slots:
void disconnectFromHostWhenConnecting();
void disconnectFromHostWhenConnected();
void resetProxy();
+ void ignoreSslErrorsList_data();
+ void ignoreSslErrorsList();
+ void ignoreSslErrorsListWithSlot_data();
+ void ignoreSslErrorsListWithSlot();
static void exitLoop()
{
@@ -194,9 +198,11 @@ protected slots:
if (errors.size() == 1 && errors.first().error() == QSslError::CertificateUntrusted)
socket->ignoreSslErrors();
}
+ void ignoreErrorListSlot(const QList<QSslError> &errors);
private:
QSslSocket *socket;
+ QList<QSslError> storedExpectedSslErrors;
#endif // QT_NO_OPENSSL
private:
static int loopLevel;
@@ -609,7 +615,7 @@ void tst_QSslSocket::connectToHostEncryptedWithVerificationPeerName()
QSslSocketPtr socket = newSocket();
this->socket = socket;
- socket->addCaCertificates(QLatin1String("certs/qt-test-server-cacert.pem"));
+ socket->addCaCertificates(QLatin1String(SRCDIR "certs/qt-test-server-cacert.pem"));
#ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND
connect(&socket, SIGNAL(sslErrors(QList<QSslError>)),
this, SLOT(untrustedWorkaroundSlot(QList<QSslError>)));
@@ -1537,6 +1543,82 @@ void tst_QSslSocket::resetProxy()
QVERIFY2(socket2.waitForConnected(10000), qPrintable(socket.errorString()));
}
+void tst_QSslSocket::ignoreSslErrorsList_data()
+{
+ QTest::addColumn<QList<QSslError> >("expectedSslErrors");
+ QTest::addColumn<int>("expectedSslErrorSignalCount");
+
+ // construct the list of errors that we will get with the SSL handshake and that we will ignore
+ QList<QSslError> expectedSslErrors;
+ // fromPath gives us a list of certs, but it actually only contains one
+ QList<QSslCertificate> certs = QSslCertificate::fromPath(QLatin1String(SRCDIR "certs/qt-test-server-cacert.pem"));
+ QSslError rightError(QSslError::SelfSignedCertificate, certs.at(0));
+ QSslError wrongError(QSslError::SelfSignedCertificate);
+
+
+ QTest::newRow("SSL-failure-empty-list") << expectedSslErrors << 1;
+ expectedSslErrors.append(wrongError);
+ QTest::newRow("SSL-failure-wrong-error") << expectedSslErrors << 1;
+ expectedSslErrors.append(rightError);
+ QTest::newRow("allErrorsInExpectedList1") << expectedSslErrors << 0;
+ expectedSslErrors.removeAll(wrongError);
+ QTest::newRow("allErrorsInExpectedList2") << expectedSslErrors << 0;
+ expectedSslErrors.removeAll(rightError);
+ QTest::newRow("SSL-failure-empty-list-again") << expectedSslErrors << 1;
+}
+
+void tst_QSslSocket::ignoreSslErrorsList()
+{
+ QSslSocket socket;
+ connect(&socket, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
+ this, SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
+
+// this->socket = &socket;
+ QSslCertificate cert;
+
+ QFETCH(QList<QSslError>, expectedSslErrors);
+ socket.ignoreSslErrors(expectedSslErrors);
+
+ QFETCH(int, expectedSslErrorSignalCount);
+ QSignalSpy sslErrorsSpy(&socket, SIGNAL(error(QAbstractSocket::SocketError)));
+
+ socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+
+ bool expectEncryptionSuccess = (expectedSslErrorSignalCount == 0);
+ QCOMPARE(socket.waitForEncrypted(10000), expectEncryptionSuccess);
+ QCOMPARE(sslErrorsSpy.count(), expectedSslErrorSignalCount);
+}
+
+void tst_QSslSocket::ignoreSslErrorsListWithSlot_data()
+{
+ ignoreSslErrorsList_data();
+}
+
+// this is not a test, just a slot called in the test below
+void tst_QSslSocket::ignoreErrorListSlot(const QList<QSslError> &)
+{
+ socket->ignoreSslErrors(storedExpectedSslErrors);
+}
+
+void tst_QSslSocket::ignoreSslErrorsListWithSlot()
+{
+ QSslSocket socket;
+ this->socket = &socket;
+
+ QFETCH(QList<QSslError>, expectedSslErrors);
+ // store the errors to ignore them later in the slot connected below
+ storedExpectedSslErrors = expectedSslErrors;
+ connect(&socket, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
+ this, SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
+ connect(&socket, SIGNAL(sslErrors(const QList<QSslError> &)),
+ this, SLOT(ignoreErrorListSlot(const QList<QSslError> &)));
+ socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+
+ QFETCH(int, expectedSslErrorSignalCount);
+ bool expectEncryptionSuccess = (expectedSslErrorSignalCount == 0);
+ QCOMPARE(socket.waitForEncrypted(10000), expectEncryptionSuccess);
+}
+
#endif // QT_NO_OPENSSL
QTEST_MAIN(tst_QSslSocket)