diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/websockets/qwebsocket.cpp | 5 | ||||
-rw-r--r-- | src/websockets/qwebsocket_p.cpp | 46 | ||||
-rw-r--r-- | src/websockets/qwebsockethandshakeresponse.cpp | 32 |
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; |