summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/network/ssl/qsslsocket.cpp35
-rw-r--r--src/network/ssl/qsslsocket_p.h3
-rw-r--r--tests/auto/qsslsocket/tst_qsslsocket.cpp127
3 files changed, 165 insertions, 0 deletions
diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp
index f89b9b3545..7fc36c8523 100644
--- a/src/network/ssl/qsslsocket.cpp
+++ b/src/network/ssl/qsslsocket.cpp
@@ -2246,6 +2246,41 @@ void QSslSocketPrivate::_q_flushReadBuffer()
/*!
\internal
*/
+qint64 QSslSocketPrivate::peek(char *data, qint64 maxSize)
+{
+ if (mode == QSslSocket::UnencryptedMode && !autoStartHandshake) {
+ if (plainSocket)
+ return plainSocket->peek(data, maxSize);
+ else
+ return -1;
+ } else {
+ QByteArray tmp;
+ tmp = readBuffer.peek(maxSize);
+ memcpy(data, tmp.data(), tmp.length());
+ return tmp.length();
+ }
+}
+
+/*!
+ \internal
+*/
+QByteArray QSslSocketPrivate::peek(qint64 maxSize)
+{
+ if (mode == QSslSocket::UnencryptedMode && !autoStartHandshake) {
+ if (plainSocket)
+ return plainSocket->peek(maxSize);
+ else
+ return QByteArray();
+ } else {
+ QByteArray tmp;
+ tmp = readBuffer.peek(maxSize);
+ return tmp;
+ }
+}
+
+/*!
+ \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 606352b0ba..58515c9f04 100644
--- a/src/network/ssl/qsslsocket_p.h
+++ b/src/network/ssl/qsslsocket_p.h
@@ -159,6 +159,9 @@ public:
void _q_flushWriteBuffer();
void _q_flushReadBuffer();
+ virtual qint64 peek(char *data, qint64 maxSize);
+ virtual QByteArray peek(qint64 maxSize);
+
// Platform specific functions
virtual void startClientEncryption() = 0;
virtual void startServerEncryption() = 0;
diff --git a/tests/auto/qsslsocket/tst_qsslsocket.cpp b/tests/auto/qsslsocket/tst_qsslsocket.cpp
index 961e4da306..cf4d04e07c 100644
--- a/tests/auto/qsslsocket/tst_qsslsocket.cpp
+++ b/tests/auto/qsslsocket/tst_qsslsocket.cpp
@@ -190,6 +190,7 @@ private slots:
void readFromClosedSocket();
void writeBigChunk();
void blacklistedCertificates();
+ void qtbug18498_peek();
void setEmptyDefaultConfiguration();
static void exitLoop()
@@ -2032,6 +2033,132 @@ void tst_QSslSocket::blacklistedCertificates()
QCOMPARE(sslErrors.at(0).error(), QSslError::CertificateBlacklisted);
}
+class WebSocket : public QSslSocket
+{
+ Q_OBJECT
+public:
+ explicit WebSocket(int socketDescriptor,
+ const QString &keyFile = SRCDIR "certs/fluke.key",
+ const QString &certFile = SRCDIR "certs/fluke.cert");
+
+protected slots:
+ void onReadyReadFirstBytes(void);
+
+private:
+ void _startServerEncryption(void);
+
+ QString m_keyFile;
+ QString m_certFile;
+
+private:
+ Q_DISABLE_COPY(WebSocket)
+};
+
+WebSocket::WebSocket (int socketDescriptor, const QString &keyFile, const QString &certFile)
+ : m_keyFile(keyFile),
+ m_certFile(certFile)
+{
+ QVERIFY(setSocketDescriptor(socketDescriptor, QAbstractSocket::ConnectedState, QIODevice::ReadWrite | QIODevice::Unbuffered));
+ connect (this, SIGNAL(readyRead()), this, SLOT(onReadyReadFirstBytes()));
+}
+
+void WebSocket::_startServerEncryption (void)
+{
+ QFile file(m_keyFile);
+ QVERIFY(file.open(QIODevice::ReadOnly));
+ QSslKey key(file.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
+ QVERIFY(!key.isNull());
+ setPrivateKey(key);
+
+ QList<QSslCertificate> localCert = QSslCertificate::fromPath(m_certFile);
+ QVERIFY(!localCert.isEmpty());
+ QVERIFY(localCert.first().handle());
+ setLocalCertificate(localCert.first());
+
+ QVERIFY(!peerAddress().isNull());
+ QVERIFY(peerPort() != 0);
+ QVERIFY(!localAddress().isNull());
+ QVERIFY(localPort() != 0);
+
+ setProtocol(QSsl::AnyProtocol);
+ setPeerVerifyMode(QSslSocket::VerifyNone);
+ ignoreSslErrors();
+ startServerEncryption();
+}
+
+void WebSocket::onReadyReadFirstBytes (void)
+{
+ peek(1);
+ disconnect(this,SIGNAL(readyRead()), this, SLOT(onReadyReadFirstBytes()));
+ _startServerEncryption();
+}
+
+class SslServer4 : public QTcpServer
+{
+ Q_OBJECT
+public:
+ SslServer4() : socket(0) {}
+ WebSocket *socket;
+
+protected:
+ void incomingConnection(int socketDescriptor)
+ {
+ socket = new WebSocket(socketDescriptor);
+ }
+};
+
+void tst_QSslSocket::qtbug18498_peek()
+{
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy)
+ return;
+
+ SslServer4 server;
+ QSslSocket *client = new QSslSocket(this);
+
+ QVERIFY(server.listen(QHostAddress::LocalHost));
+ client->connectToHost("127.0.0.1", server.serverPort());
+ QVERIFY(client->waitForConnected(5000));
+ QVERIFY(server.waitForNewConnection(0));
+ client->setObjectName("client");
+ client->ignoreSslErrors();
+
+ connect(client, SIGNAL(encrypted()), this, SLOT(exitLoop()));
+ connect(client, SIGNAL(disconnected()), this, SLOT(exitLoop()));
+
+ client->startClientEncryption();
+ WebSocket *serversocket = server.socket;
+ QVERIFY(serversocket);
+ serversocket->setObjectName("server");
+
+ enterLoop(1);
+ QVERIFY(!timeout());
+ QVERIFY(serversocket->isEncrypted());
+ QVERIFY(client->isEncrypted());
+
+ QByteArray data("abc123");
+ client->write(data.data());
+
+ connect(serversocket, SIGNAL(readyRead()), this, SLOT(exitLoop()));
+ enterLoop(1);
+ QVERIFY(!timeout());
+
+ QByteArray peek1_data;
+ peek1_data.reserve(data.size());
+ QByteArray peek2_data;
+ QByteArray read_data;
+
+ int lngth = serversocket->peek(peek1_data.data(), 10);
+ peek1_data.resize(lngth);
+
+ peek2_data = serversocket->peek(10);
+ read_data = serversocket->readAll();
+
+ QCOMPARE(peek1_data, data);
+ QCOMPARE(peek2_data, data);
+ QCOMPARE(read_data, data);
+}
+
void tst_QSslSocket::setEmptyDefaultConfiguration()
{
// used to produce a crash in QSslConfigurationPrivate::deepCopyDefaultConfiguration, QTBUG-13265