summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGiuseppe D'Angelo <giuseppe.dangelo@kdab.com>2014-11-07 11:13:12 +0100
committerGiuseppe D'Angelo <giuseppe.dangelo@kdab.com>2015-01-23 14:27:25 +0100
commit0192630f55bb62bd7cf3a1dc29c6c0624ca7759c (patch)
tree0f393f763adcc038241f9f1200c4ae99b8fa0a4c
parentc27e1f498f933406aebc1334482da6761fe6de8c (diff)
QNetworkAccessManager: introduce support for TLS PSK
Expose the same kind of TLS PSK client support we already have set in place for QSslSocket. [ChangeLog][QtNetwork][QNetworkAccessManager] It is now possible to use TLS PSK ciphersuites when using HTTPS (or similar protocols working over SSL). Change-Id: I56a048e9f4f841f886758c781af2867d18538a3e Reviewed-by: Richard J. Moore <rich@kde.org>
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel.cpp26
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel_p.h1
-rw-r--r--src/network/access/qhttpnetworkreply_p.h1
-rw-r--r--src/network/access/qhttpthreaddelegate.cpp10
-rw-r--r--src/network/access/qhttpthreaddelegate_p.h2
-rw-r--r--src/network/access/qnetworkaccessmanager.cpp37
-rw-r--r--src/network/access/qnetworkaccessmanager.h3
-rw-r--r--src/network/access/qnetworkaccessmanager_p.h1
-rw-r--r--src/network/access/qnetworkreply.cpp22
-rw-r--r--src/network/access/qnetworkreply.h2
-rw-r--r--src/network/access/qnetworkreplyhttpimpl.cpp9
-rw-r--r--src/network/access/qnetworkreplyhttpimpl_p.h2
12 files changed, 116 insertions, 0 deletions
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
index d24fb159e2..d2a13220b9 100644
--- a/src/network/access/qhttpnetworkconnectionchannel.cpp
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
@@ -147,6 +147,9 @@ void QHttpNetworkConnectionChannel::init()
QObject::connect(sslSocket, SIGNAL(sslErrors(QList<QSslError>)),
this, SLOT(_q_sslErrors(QList<QSslError>)),
Qt::DirectConnection);
+ QObject::connect(sslSocket, SIGNAL(preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator*)),
+ this, SLOT(_q_preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator*)),
+ Qt::DirectConnection);
QObject::connect(sslSocket, SIGNAL(encryptedBytesWritten(qint64)),
this, SLOT(_q_encryptedBytesWritten(qint64)),
Qt::DirectConnection);
@@ -1035,6 +1038,29 @@ void QHttpNetworkConnectionChannel::_q_sslErrors(const QList<QSslError> &errors)
connection->d_func()->resumeConnection();
}
+void QHttpNetworkConnectionChannel::_q_preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator *authenticator)
+{
+ connection->d_func()->pauseConnection();
+
+ if (pendingEncrypt && !reply)
+ connection->d_func()->dequeueRequest(socket);
+
+ if (connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP) {
+ if (reply)
+ emit reply->preSharedKeyAuthenticationRequired(authenticator);
+ } else {
+ QList<HttpMessagePair> spdyPairs = spdyRequestsToSend.values();
+ for (int a = 0; a < spdyPairs.count(); ++a) {
+ // emit SSL errors for all replies
+ QHttpNetworkReply *currentReply = spdyPairs.at(a).second;
+ Q_ASSERT(currentReply);
+ emit currentReply->preSharedKeyAuthenticationRequired(authenticator);
+ }
+ }
+
+ connection->d_func()->resumeConnection();
+}
+
void QHttpNetworkConnectionChannel::_q_encryptedBytesWritten(qint64 bytes)
{
Q_UNUSED(bytes);
diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h
index 692c0e6a94..05331dc196 100644
--- a/src/network/access/qhttpnetworkconnectionchannel_p.h
+++ b/src/network/access/qhttpnetworkconnectionchannel_p.h
@@ -189,6 +189,7 @@ public:
#ifndef QT_NO_SSL
void _q_encrypted(); // start sending request (https)
void _q_sslErrors(const QList<QSslError> &errors); // ssl errors from the socket
+ void _q_preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator*); // tls-psk auth necessary
void _q_encryptedBytesWritten(qint64 bytes); // proceed sending
#endif
diff --git a/src/network/access/qhttpnetworkreply_p.h b/src/network/access/qhttpnetworkreply_p.h
index 7a13358a4b..5c772b5912 100644
--- a/src/network/access/qhttpnetworkreply_p.h
+++ b/src/network/access/qhttpnetworkreply_p.h
@@ -138,6 +138,7 @@ public:
Q_SIGNALS:
void encrypted();
void sslErrors(const QList<QSslError> &errors);
+ void preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator *authenticator);
#endif
Q_SIGNALS:
diff --git a/src/network/access/qhttpthreaddelegate.cpp b/src/network/access/qhttpthreaddelegate.cpp
index e31f23c18c..c8c7be43fa 100644
--- a/src/network/access/qhttpthreaddelegate.cpp
+++ b/src/network/access/qhttpthreaddelegate.cpp
@@ -371,6 +371,8 @@ void QHttpThreadDelegate::startRequest()
#ifndef QT_NO_SSL
connect(httpReply,SIGNAL(encrypted()), this, SLOT(encryptedSlot()));
connect(httpReply,SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(sslErrorsSlot(QList<QSslError>)));
+ connect(httpReply,SIGNAL(preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator*)),
+ this, SLOT(preSharedKeyAuthenticationRequiredSlot(QSslPreSharedKeyAuthenticator*)));
#endif
// In the asynchronous HTTP case we can just forward those signals
@@ -675,6 +677,14 @@ void QHttpThreadDelegate::sslErrorsSlot(const QList<QSslError> &errors)
if (!specificErrors.isEmpty())
httpReply->ignoreSslErrors(specificErrors);
}
+
+void QHttpThreadDelegate::preSharedKeyAuthenticationRequiredSlot(QSslPreSharedKeyAuthenticator *authenticator)
+{
+ if (!httpReply)
+ return;
+
+ emit preSharedKeyAuthenticationRequired(authenticator);
+}
#endif
void QHttpThreadDelegate::synchronousAuthenticationRequiredSlot(const QHttpNetworkRequest &request, QAuthenticator *a)
diff --git a/src/network/access/qhttpthreaddelegate_p.h b/src/network/access/qhttpthreaddelegate_p.h
index b1367fec0c..0ace0e6418 100644
--- a/src/network/access/qhttpthreaddelegate_p.h
+++ b/src/network/access/qhttpthreaddelegate_p.h
@@ -131,6 +131,7 @@ signals:
void encrypted();
void sslErrors(const QList<QSslError> &, bool *, QList<QSslError> *);
void sslConfigurationChanged(const QSslConfiguration);
+ void preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator *);
#endif
void downloadMetaData(QList<QPair<QByteArray,QByteArray> >, int, QString, bool,
QSharedPointer<char>, qint64, bool);
@@ -161,6 +162,7 @@ protected slots:
#ifndef QT_NO_SSL
void encryptedSlot();
void sslErrorsSlot(const QList<QSslError> &errors);
+ void preSharedKeyAuthenticationRequiredSlot(QSslPreSharedKeyAuthenticator *authenticator);
#endif
void synchronousAuthenticationRequiredSlot(const QHttpNetworkRequest &request, QAuthenticator *);
diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp
index 52d56fb071..c661854a3a 100644
--- a/src/network/access/qnetworkaccessmanager.cpp
+++ b/src/network/access/qnetworkaccessmanager.cpp
@@ -416,6 +416,29 @@ static void ensureInitialized()
QNetworkReply::sslConfiguration(), QNetworkReply::ignoreSslErrors()
*/
+/*!
+ \fn void QNetworkAccessManager::preSharedKeyAuthenticationRequired(QNetworkReply *reply, QSslPreSharedKeyAuthenticator *authenticator)
+ \since 5.5
+
+ This signal is emitted if the SSL/TLS handshake negotiates a PSK
+ ciphersuite, and therefore a PSK authentication is then required.
+ The \a reply object is the QNetworkReply that is negotiating
+ such ciphersuites.
+
+ When using PSK, the client must send to the server a valid identity and a
+ valid pre shared key, in order for the SSL handshake to continue.
+ Applications can provide this information in a slot connected to this
+ signal, by filling in the passed \a authenticator object according to their
+ needs.
+
+ \note Ignoring this signal, or failing to provide the required credentials,
+ will cause the handshake to fail, and therefore the connection to be aborted.
+
+ \note The \a authenticator object is owned by the reply and must not be
+ deleted by the application.
+
+ \sa QSslPreSharedKeyAuthenticator
+*/
/*!
Constructs a QNetworkAccessManager object that is the center of
@@ -434,6 +457,7 @@ QNetworkAccessManager::QNetworkAccessManager(QObject *parent)
#ifndef QT_NO_SSL
qRegisterMetaType<QList<QSslError> >();
qRegisterMetaType<QSslConfiguration>();
+ qRegisterMetaType<QSslPreSharedKeyAuthenticator *>();
#endif
qRegisterMetaType<QList<QPair<QByteArray,QByteArray> > >();
#ifndef QT_NO_HTTP
@@ -1328,6 +1352,18 @@ void QNetworkAccessManagerPrivate::_q_replySslErrors(const QList<QSslError> &err
#endif
}
+void QNetworkAccessManagerPrivate::_q_replyPreSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator *authenticator)
+{
+#ifndef QT_NO_SSL
+ Q_Q(QNetworkAccessManager);
+ QNetworkReply *reply = qobject_cast<QNetworkReply *>(q->sender());
+ if (reply)
+ emit q->preSharedKeyAuthenticationRequired(reply, authenticator);
+#else
+ Q_UNUSED(authenticator);
+#endif
+}
+
QNetworkReply *QNetworkAccessManagerPrivate::postProcess(QNetworkReply *reply)
{
Q_Q(QNetworkAccessManager);
@@ -1338,6 +1374,7 @@ QNetworkReply *QNetworkAccessManagerPrivate::postProcess(QNetworkReply *reply)
* avoid getting a connection error. */
q->connect(reply, SIGNAL(encrypted()), SLOT(_q_replyEncrypted()));
q->connect(reply, SIGNAL(sslErrors(QList<QSslError>)), SLOT(_q_replySslErrors(QList<QSslError>)));
+ q->connect(reply, SIGNAL(preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator*)), SLOT(_q_replyPreSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator*)));
#endif
#ifndef QT_NO_BEARERMANAGEMENT
activeReplyCount++;
diff --git a/src/network/access/qnetworkaccessmanager.h b/src/network/access/qnetworkaccessmanager.h
index 9241ff36fb..581ed3cec3 100644
--- a/src/network/access/qnetworkaccessmanager.h
+++ b/src/network/access/qnetworkaccessmanager.h
@@ -37,6 +37,7 @@
#include <QtCore/QObject>
#ifndef QT_NO_SSL
#include <QtNetwork/QSslConfiguration>
+#include <QtNetwork/QSslPreSharedKeyAuthenticator>
#endif
QT_BEGIN_NAMESPACE
@@ -145,6 +146,7 @@ Q_SIGNALS:
#ifndef QT_NO_SSL
void encrypted(QNetworkReply *reply);
void sslErrors(QNetworkReply *reply, const QList<QSslError> &errors);
+ void preSharedKeyAuthenticationRequired(QNetworkReply *reply, QSslPreSharedKeyAuthenticator *authenticator);
#endif
#ifndef QT_NO_BEARERMANAGEMENT
@@ -169,6 +171,7 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_replyFinished())
Q_PRIVATE_SLOT(d_func(), void _q_replyEncrypted())
Q_PRIVATE_SLOT(d_func(), void _q_replySslErrors(QList<QSslError>))
+ Q_PRIVATE_SLOT(d_func(), void _q_replyPreSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator*))
#ifndef QT_NO_BEARERMANAGEMENT
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionClosed())
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionStateChanged(QNetworkSession::State))
diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h
index f75884da38..0a839242ef 100644
--- a/src/network/access/qnetworkaccessmanager_p.h
+++ b/src/network/access/qnetworkaccessmanager_p.h
@@ -91,6 +91,7 @@ public:
void _q_replyFinished();
void _q_replyEncrypted();
void _q_replySslErrors(const QList<QSslError> &errors);
+ void _q_replyPreSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator *authenticator);
QNetworkReply *postProcess(QNetworkReply *reply);
void createCookieJar() const;
diff --git a/src/network/access/qnetworkreply.cpp b/src/network/access/qnetworkreply.cpp
index 1710af723f..67407cd500 100644
--- a/src/network/access/qnetworkreply.cpp
+++ b/src/network/access/qnetworkreply.cpp
@@ -254,6 +254,28 @@ QNetworkReplyPrivate::QNetworkReplyPrivate()
*/
/*!
+ \fn void QNetworkReply::preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator *authenticator)
+ \since 5.5
+
+ This signal is emitted if the SSL/TLS handshake negotiates a PSK
+ ciphersuite, and therefore a PSK authentication is then required.
+
+ When using PSK, the client must send to the server a valid identity and a
+ valid pre shared key, in order for the SSL handshake to continue.
+ Applications can provide this information in a slot connected to this
+ signal, by filling in the passed \a authenticator object according to their
+ needs.
+
+ \note Ignoring this signal, or failing to provide the required credentials,
+ will cause the handshake to fail, and therefore the connection to be aborted.
+
+ \note The \a authenticator object is owned by the reply and must not be
+ deleted by the application.
+
+ \sa QSslPreSharedKeyAuthenticator
+*/
+
+/*!
\fn void QNetworkReply::metaDataChanged()
\omit FIXME: Update name? \endomit
diff --git a/src/network/access/qnetworkreply.h b/src/network/access/qnetworkreply.h
index 453116ea0e..a354577cd5 100644
--- a/src/network/access/qnetworkreply.h
+++ b/src/network/access/qnetworkreply.h
@@ -49,6 +49,7 @@ class QVariant;
class QAuthenticator;
class QSslConfiguration;
class QSslError;
+class QSslPreSharedKeyAuthenticator;
class QNetworkReplyPrivate;
class Q_NETWORK_EXPORT QNetworkReply: public QIODevice
@@ -150,6 +151,7 @@ Q_SIGNALS:
#ifndef QT_NO_SSL
void encrypted();
void sslErrors(const QList<QSslError> &errors);
+ void preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator *authenticator);
#endif
void uploadProgress(qint64 bytesSent, qint64 bytesTotal);
diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp
index e7c1b61d4d..e82f3fe833 100644
--- a/src/network/access/qnetworkreplyhttpimpl.cpp
+++ b/src/network/access/qnetworkreplyhttpimpl.cpp
@@ -844,6 +844,9 @@ void QNetworkReplyHttpImplPrivate::postRequest()
QObject::connect(delegate, SIGNAL(sslErrors(QList<QSslError>,bool*,QList<QSslError>*)),
q, SLOT(replySslErrors(QList<QSslError>,bool*,QList<QSslError>*)),
Qt::BlockingQueuedConnection);
+ QObject::connect(delegate, SIGNAL(preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator*)),
+ q, SLOT(replyPreSharedKeyAuthenticationRequiredSlot(QSslPreSharedKeyAuthenticator*)),
+ Qt::BlockingQueuedConnection);
#endif
// This signal we will use to start the request.
QObject::connect(q, SIGNAL(startHttpRequest()), delegate, SLOT(startRequest()));
@@ -1263,6 +1266,12 @@ void QNetworkReplyHttpImplPrivate::replySslConfigurationChanged(const QSslConfig
// Receiving the used SSL configuration from the HTTP thread
this->sslConfiguration = sslConfiguration;
}
+
+void QNetworkReplyHttpImplPrivate::replyPreSharedKeyAuthenticationRequiredSlot(QSslPreSharedKeyAuthenticator *authenticator)
+{
+ Q_Q(QNetworkReplyHttpImpl);
+ emit q->preSharedKeyAuthenticationRequired(authenticator);
+}
#endif
// Coming from QNonContiguousByteDeviceThreadForwardImpl in HTTP thread
diff --git a/src/network/access/qnetworkreplyhttpimpl_p.h b/src/network/access/qnetworkreplyhttpimpl_p.h
index 73349f4e7a..d0d97c74ad 100644
--- a/src/network/access/qnetworkreplyhttpimpl_p.h
+++ b/src/network/access/qnetworkreplyhttpimpl_p.h
@@ -113,6 +113,7 @@ public:
Q_PRIVATE_SLOT(d_func(), void replyEncrypted())
Q_PRIVATE_SLOT(d_func(), void replySslErrors(const QList<QSslError> &, bool *, QList<QSslError> *))
Q_PRIVATE_SLOT(d_func(), void replySslConfigurationChanged(const QSslConfiguration&))
+ Q_PRIVATE_SLOT(d_func(), void replyPreSharedKeyAuthenticationRequiredSlot(QSslPreSharedKeyAuthenticator *))
#endif
#ifndef QT_NO_NETWORKPROXY
Q_PRIVATE_SLOT(d_func(), void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *auth))
@@ -275,6 +276,7 @@ public:
void replyEncrypted();
void replySslErrors(const QList<QSslError> &, bool *, QList<QSslError> *);
void replySslConfigurationChanged(const QSslConfiguration&);
+ void replyPreSharedKeyAuthenticationRequiredSlot(QSslPreSharedKeyAuthenticator *);
#endif
#ifndef QT_NO_NETWORKPROXY
void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *auth);