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>
This commit is contained in:
parent
c27e1f498f
commit
0192630f55
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
@ -138,6 +138,7 @@ public:
|
||||
Q_SIGNALS:
|
||||
void encrypted();
|
||||
void sslErrors(const QList<QSslError> &errors);
|
||||
void preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator *authenticator);
|
||||
#endif
|
||||
|
||||
Q_SIGNALS:
|
||||
|
@ -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)
|
||||
|
@ -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 *);
|
||||
|
@ -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++;
|
||||
|
@ -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))
|
||||
|
@ -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;
|
||||
|
||||
|
@ -253,6 +253,28 @@ QNetworkReplyPrivate::QNetworkReplyPrivate()
|
||||
sslConfiguration(), ignoreSslErrors()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\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()
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user