summaryrefslogtreecommitdiffstats
path: root/src/network
diff options
context:
space:
mode:
authorPeter Hartmann <peter.hartmann@trolltech.com>2009-07-02 09:32:49 (GMT)
committerPeter Hartmann <peter.hartmann@trolltech.com>2009-07-22 16:07:13 (GMT)
commit8e05fd54935be488165abe6762e69aabb9adf232 (patch)
treecbb6e29ccb10950233077f0d6e9cb8879bcf3727 /src/network
parentd63f3c4c3940b4293c8763d5bfc01ed430075efb (diff)
downloadQt-8e05fd54935be488165abe6762e69aabb9adf232.zip
Qt-8e05fd54935be488165abe6762e69aabb9adf232.tar.gz
Qt-8e05fd54935be488165abe6762e69aabb9adf232.tar.bz2
QNetworkReply: add possibility to ignore specific SSL errors
the same method was also added to QSslSocket. previously, it was only possible to ignore all SSL errors; now, it is also possible to only ignore specific SSL errors, given by a QList of QSslErrors. Moreover, it is possible to call this newly added method right after connecting, not just when we get the SSL error. Reviewed-by: Thiago Task-number: 257322
Diffstat (limited to 'src/network')
-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
17 files changed, 157 insertions, 15 deletions
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;