summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorFranck Dude <enstone83@gmail.com>2019-12-14 23:41:30 +0100
committerFranck Dude <enstone83@gmail.com>2020-03-19 10:43:46 +0100
commited93680f34e92ad0383aa4e610bb65689118ca93 (patch)
treeaf3a3c9aa07a370d5923559538c8da6eceef4bf9 /tests
parent2437f81b0022f9524ca467e28c889d8683c464cf (diff)
downloadqtwebsockets-ed93680f34e92ad0383aa4e610bb65689118ca93.tar.gz
Add a public api to set max frame and message size (CVE-2018-21035)
This change allows the user to set a lower allowed frame/message size for reception. The purpose is to avoid an attacker to exhaust the virtual memory of the peer. Fixes CVE-2018-21035 [ChangeLog] Added public API to set the maximum frame size and message size Task-number: QTBUG-70693 Change-Id: I5dc5918badc99166afdcc8d9c6106247a9f8666f Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/websockets/qwebsocket/tst_qwebsocket.cpp90
-rw-r--r--tests/auto/websockets/websocketframe/tst_websocketframe.cpp2
2 files changed, 89 insertions, 3 deletions
diff --git a/tests/auto/websockets/qwebsocket/tst_qwebsocket.cpp b/tests/auto/websockets/qwebsocket/tst_qwebsocket.cpp
index 71e1262..aca3f40 100644
--- a/tests/auto/websockets/qwebsocket/tst_qwebsocket.cpp
+++ b/tests/auto/websockets/qwebsocket/tst_qwebsocket.cpp
@@ -39,7 +39,9 @@ class EchoServer : public QObject
{
Q_OBJECT
public:
- explicit EchoServer(QObject *parent = nullptr);
+ explicit EchoServer(QObject *parent = nullptr,
+ quint64 maxAllowedIncomingMessageSize = QWebSocket::maxIncomingMessageSize(),
+ quint64 maxAllowedIncomingFrameSize = QWebSocket::maxIncomingFrameSize());
~EchoServer();
QHostAddress hostAddress() const { return m_pWebSocketServer->serverAddress(); }
@@ -57,13 +59,17 @@ private Q_SLOTS:
private:
QWebSocketServer *m_pWebSocketServer;
+ quint64 m_maxAllowedIncomingMessageSize;
+ quint64 m_maxAllowedIncomingFrameSize;
QList<QWebSocket *> m_clients;
};
-EchoServer::EchoServer(QObject *parent) :
+EchoServer::EchoServer(QObject *parent, quint64 maxAllowedIncomingMessageSize, quint64 maxAllowedIncomingFrameSize) :
QObject(parent),
m_pWebSocketServer(new QWebSocketServer(QStringLiteral("Echo Server"),
QWebSocketServer::NonSecureMode, this)),
+ m_maxAllowedIncomingMessageSize(maxAllowedIncomingMessageSize),
+ m_maxAllowedIncomingFrameSize(maxAllowedIncomingFrameSize),
m_clients()
{
if (m_pWebSocketServer->listen(QHostAddress(QStringLiteral("127.0.0.1")))) {
@@ -82,6 +88,9 @@ void EchoServer::onNewConnection()
{
QWebSocket *pSocket = m_pWebSocketServer->nextPendingConnection();
+ pSocket->setMaxAllowedIncomingFrameSize(m_maxAllowedIncomingFrameSize);
+ pSocket->setMaxAllowedIncomingMessageSize(m_maxAllowedIncomingMessageSize);
+
Q_EMIT newConnection(pSocket->requestUrl());
Q_EMIT newConnection(pSocket->request());
@@ -144,6 +153,9 @@ private Q_SLOTS:
void tst_setProxy();
#endif
void overlongCloseReason();
+ void incomingMessageTooLong();
+ void incomingFrameTooLong();
+ void testingFrameAndMessageSizeApi();
};
tst_QWebSocket::tst_QWebSocket()
@@ -795,6 +807,80 @@ void tst_QWebSocket::overlongCloseReason()
QCOMPARE(socket.closeReason(), reason.leftRef(123));
QTRY_COMPARE(socketDisconnectedSpy.count(), 1);
}
+
+void tst_QWebSocket::incomingMessageTooLong()
+{
+//QTBUG-70693
+ quint64 maxAllowedIncomingMessageSize = 1024;
+ quint64 maxAllowedIncomingFrameSize = QWebSocket::maxIncomingFrameSize();
+
+ EchoServer echoServer(nullptr, maxAllowedIncomingMessageSize, maxAllowedIncomingFrameSize);
+
+ QWebSocket socket;
+
+ QSignalSpy socketConnectedSpy(&socket, &QWebSocket::connected);
+ QSignalSpy serverConnectedSpy(&echoServer, QOverload<QUrl>::of(&EchoServer::newConnection));
+ QSignalSpy socketDisconnectedSpy(&socket, &QWebSocket::disconnected);
+
+ QUrl url = QUrl(QStringLiteral("ws://") + echoServer.hostAddress().toString() +
+ QStringLiteral(":") + QString::number(echoServer.port()));
+ socket.open(url);
+ QTRY_COMPARE(socketConnectedSpy.count(), 1);
+ QTRY_COMPARE(serverConnectedSpy.count(), 1);
+
+ QString payload(maxAllowedIncomingMessageSize+1, 'a');
+ QCOMPARE(socket.sendTextMessage(payload), payload.size());
+
+ QTRY_COMPARE(socketDisconnectedSpy.count(), 1);
+ QCOMPARE(socket.closeCode(), QWebSocketProtocol::CloseCodeTooMuchData);
+}
+
+void tst_QWebSocket::incomingFrameTooLong()
+{
+//QTBUG-70693
+ quint64 maxAllowedIncomingMessageSize = QWebSocket::maxIncomingMessageSize();
+ quint64 maxAllowedIncomingFrameSize = 1024;
+
+ EchoServer echoServer(nullptr, maxAllowedIncomingMessageSize, maxAllowedIncomingFrameSize);
+
+ QWebSocket socket;
+ socket.setOutgoingFrameSize(maxAllowedIncomingFrameSize+1);
+
+ QSignalSpy socketConnectedSpy(&socket, &QWebSocket::connected);
+ QSignalSpy serverConnectedSpy(&echoServer, QOverload<QUrl>::of(&EchoServer::newConnection));
+ QSignalSpy socketDisconnectedSpy(&socket, &QWebSocket::disconnected);
+
+ QUrl url = QUrl(QStringLiteral("ws://") + echoServer.hostAddress().toString() +
+ QStringLiteral(":") + QString::number(echoServer.port()));
+ socket.open(url);
+ QTRY_COMPARE(socketConnectedSpy.count(), 1);
+ QTRY_COMPARE(serverConnectedSpy.count(), 1);
+
+ QString payload(maxAllowedIncomingFrameSize+1, 'a');
+ QCOMPARE(socket.sendTextMessage(payload), payload.size());
+
+ QTRY_COMPARE(socketDisconnectedSpy.count(), 1);
+ QCOMPARE(socket.closeCode(), QWebSocketProtocol::CloseCodeTooMuchData);
+}
+
+void tst_QWebSocket::testingFrameAndMessageSizeApi()
+{
+//requested by André Hartmann, QTBUG-70693
+ QWebSocket socket;
+
+ const quint64 outgoingFrameSize = 5;
+ socket.setOutgoingFrameSize(outgoingFrameSize);
+ QTRY_COMPARE(outgoingFrameSize, socket.outgoingFrameSize());
+
+ const quint64 maxAllowedIncomingFrameSize = 9;
+ socket.setMaxAllowedIncomingFrameSize(maxAllowedIncomingFrameSize);
+ QTRY_COMPARE(maxAllowedIncomingFrameSize, socket.maxAllowedIncomingFrameSize());
+
+ const quint64 maxAllowedIncomingMessageSize = 889;
+ socket.setMaxAllowedIncomingMessageSize(maxAllowedIncomingMessageSize);
+ QTRY_COMPARE(maxAllowedIncomingMessageSize, socket.maxAllowedIncomingMessageSize());
+}
+
#endif // QT_NO_NETWORKPROXY
QTEST_MAIN(tst_QWebSocket)
diff --git a/tests/auto/websockets/websocketframe/tst_websocketframe.cpp b/tests/auto/websockets/websocketframe/tst_websocketframe.cpp
index bbf0e5f..7046657 100644
--- a/tests/auto/websockets/websocketframe/tst_websocketframe.cpp
+++ b/tests/auto/websockets/websocketframe/tst_websocketframe.cpp
@@ -541,7 +541,7 @@ void tst_WebSocketFrame::tst_malformedFrames_data()
//too much data
{
const char bigpayloadIndicator = char(127);
- const quint64 payloadSize = MAX_FRAME_SIZE_IN_BYTES + 1;
+ const quint64 payloadSize = QWebSocketFrame::maxFrameSize() + 1;
uchar swapped[8] = {0};
qToBigEndian<quint64>(payloadSize, swapped);
QTest::newRow("Frame too big")