aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/websockets/qwebsocket.cpp5
-rw-r--r--src/websockets/qwebsocket_p.cpp46
-rw-r--r--src/websockets/qwebsockethandshakeresponse.cpp32
3 files changed, 68 insertions, 15 deletions
diff --git a/src/websockets/qwebsocket.cpp b/src/websockets/qwebsocket.cpp
index f2a2b6a..0a0c420 100644
--- a/src/websockets/qwebsocket.cpp
+++ b/src/websockets/qwebsocket.cpp
@@ -255,6 +255,8 @@ QT_BEGIN_NAMESPACE
* The \a origin of the client is as specified \l {http://tools.ietf.org/html/rfc6454}{RFC 6454}.
* (The \a origin is not required for non-web browser clients
* (see \l {http://tools.ietf.org/html/rfc6455}{RFC 6455})).
+ * The \a origin may not contain new line characters, otherwise the connection will be
+ * aborted immediately during the handshake phase.
* \note Currently only V13 (\l {http://tools.ietf.org/html/rfc6455} {RFC 6455}) is supported
*/
QWebSocket::QWebSocket(const QString &origin,
@@ -373,6 +375,9 @@ void QWebSocket::close(QWebSocketProtocol::CloseCode closeCode, const QString &r
/*!
\brief Opens a websocket connection using the given \a url.
+
+ If the url contains newline characters (\\r\\n), then the error signal will be emitted
+ with QAbstractSocket::ConnectionRefusedError as error type.
*/
void QWebSocket::open(const QUrl &url)
{
diff --git a/src/websockets/qwebsocket_p.cpp b/src/websockets/qwebsocket_p.cpp
index 1c4baca..d54337f 100644
--- a/src/websockets/qwebsocket_p.cpp
+++ b/src/websockets/qwebsocket_p.cpp
@@ -330,8 +330,14 @@ void QWebSocketPrivate::close(QWebSocketProtocol::CloseCode closeCode, QString r
void QWebSocketPrivate::open(const QUrl &url, bool mask)
{
//just delete the old socket for the moment;
- //later, we can add more 'intelligent' handling by looking at the url
+ //later, we can add more 'intelligent' handling by looking at the URL
//m_pSocket.reset();
+ Q_Q(QWebSocket);
+ if (!url.isValid() || url.toString().contains(QStringLiteral("\r\n"))) {
+ setErrorString(QWebSocket::tr("Invalid URL."));
+ Q_EMIT q->error(QAbstractSocket::ConnectionRefusedError);
+ return;
+ }
QTcpSocket *pTcpSocket = m_pSocket.take();
if (pTcpSocket) {
releaseConnections(pTcpSocket);
@@ -339,14 +345,18 @@ void QWebSocketPrivate::open(const QUrl &url, bool mask)
}
//if (m_url != url)
if (Q_LIKELY(!m_pSocket)) {
- Q_Q(QWebSocket);
-
m_dataProcessor.clear();
m_isClosingHandshakeReceived = false;
m_isClosingHandshakeSent = false;
setRequestUrl(url);
QString resourceName = url.path();
+ if (resourceName.contains(QStringLiteral("\r\n"))) {
+ setRequestUrl(QUrl()); //clear requestUrl
+ setErrorString(QWebSocket::tr("Invalid resource name."));
+ Q_EMIT q->error(QAbstractSocket::ConnectionRefusedError);
+ return;
+ }
if (!url.query().isEmpty()) {
if (!resourceName.endsWith(QChar::fromLatin1('?'))) {
resourceName.append(QChar::fromLatin1('?'));
@@ -973,6 +983,11 @@ void QWebSocketPrivate::processStateChanged(QAbstractSocket::SocketState socketS
QString(),
QString(),
m_key);
+ if (handshake.isEmpty()) {
+ m_pSocket->abort();
+ Q_EMIT q->error(QAbstractSocket::ConnectionRefusedError);
+ return;
+ }
m_pSocket->write(handshake.toLatin1());
}
break;
@@ -1062,6 +1077,31 @@ QString QWebSocketPrivate::createHandShakeRequest(QString resourceName,
QByteArray key)
{
QStringList handshakeRequest;
+ if (resourceName.contains(QStringLiteral("\r\n"))) {
+ setErrorString(QWebSocket::tr("The resource name contains newlines. " \
+ "Possible attack detected."));
+ return QString();
+ }
+ if (host.contains(QStringLiteral("\r\n"))) {
+ setErrorString(QWebSocket::tr("The hostname contains newlines. " \
+ "Possible attack detected."));
+ return QString();
+ }
+ if (origin.contains(QStringLiteral("\r\n"))) {
+ setErrorString(QWebSocket::tr("The origin contains newlines. " \
+ "Possible attack detected."));
+ return QString();
+ }
+ if (extensions.contains(QStringLiteral("\r\n"))) {
+ setErrorString(QWebSocket::tr("The extensions attribute contains newlines. " \
+ "Possible attack detected."));
+ return QString();
+ }
+ if (protocols.contains(QStringLiteral("\r\n"))) {
+ setErrorString(QWebSocket::tr("The protocols attribute contains newlines. " \
+ "Possible attack detected."));
+ return QString();
+ }
handshakeRequest << QStringLiteral("GET ") % resourceName % QStringLiteral(" HTTP/1.1") <<
QStringLiteral("Host: ") % host <<
diff --git a/src/websockets/qwebsockethandshakeresponse.cpp b/src/websockets/qwebsockethandshakeresponse.cpp
index 37c0636..fd2ccd5 100644
--- a/src/websockets/qwebsockethandshakeresponse.cpp
+++ b/src/websockets/qwebsockethandshakeresponse.cpp
@@ -177,19 +177,27 @@ QString QWebSocketHandshakeResponse::getHandshakeResponse(
response << QStringLiteral("Sec-WebSocket-Extensions: ") % m_acceptedExtension;
}
QString origin = request.origin().trimmed();
- if (origin.isEmpty())
- origin = QStringLiteral("*");
- response << QStringLiteral("Server: ") % serverName <<
- QStringLiteral("Access-Control-Allow-Credentials: false") <<
- QStringLiteral("Access-Control-Allow-Methods: GET") <<
- QStringLiteral("Access-Control-Allow-Headers: content-type") <<
- QStringLiteral("Access-Control-Allow-Origin: ") % origin <<
- QStringLiteral("Date: ") %
- QDateTime::currentDateTimeUtc()
- .toString(QStringLiteral("ddd, dd MMM yyyy hh:mm:ss 'GMT'"));
+ if (origin.contains(QStringLiteral("\r\n")) ||
+ serverName.contains(QStringLiteral("\r\n"))) {
+ m_error = QWebSocketProtocol::CloseCodeAbnormalDisconnection;
+ m_errorString = tr("One of the headers contains a newline. " \
+ "Possible attack detected.");
+ m_canUpgrade = false;
+ } else {
+ if (origin.isEmpty())
+ origin = QStringLiteral("*");
+ response << QStringLiteral("Server: ") % serverName <<
+ QStringLiteral("Access-Control-Allow-Credentials: false") <<
+ QStringLiteral("Access-Control-Allow-Methods: GET") <<
+ QStringLiteral("Access-Control-Allow-Headers: content-type") <<
+ QStringLiteral("Access-Control-Allow-Origin: ") % origin <<
+ QStringLiteral("Date: ") %
+ QDateTime::currentDateTimeUtc()
+ .toString(QStringLiteral("ddd, dd MMM yyyy hh:mm:ss 'GMT'"));
- m_acceptedVersion = QWebSocketProtocol::currentVersion();
- m_canUpgrade = true;
+ m_acceptedVersion = QWebSocketProtocol::currentVersion();
+ m_canUpgrade = true;
+ }
}
} else {
m_error = QWebSocketProtocol::CloseCodeProtocolError;