mirror of
https://github.com/moonlight-stream/moonlight-qt.git
synced 2026-10-12 03:24:00 +00:00
Improve handling of malformed XML responses
This commit is contained in:
+26
-28
@@ -109,7 +109,7 @@ NvHTTP::getCurrentGame(QString serverInfo)
|
|||||||
// has the semantics that its name would indicate. To contain the effects of this change as much
|
// has the semantics that its name would indicate. To contain the effects of this change as much
|
||||||
// as possible, we'll force the current game to zero if the server isn't in a streaming session.
|
// as possible, we'll force the current game to zero if the server isn't in a streaming session.
|
||||||
QString serverState = getXmlString(serverInfo, "state");
|
QString serverState = getXmlString(serverInfo, "state");
|
||||||
if (serverState != nullptr && serverState.endsWith("_SERVER_BUSY"))
|
if (serverState.endsWith("_SERVER_BUSY"))
|
||||||
{
|
{
|
||||||
return getXmlString(serverInfo, "currentgame").toInt();
|
return getXmlString(serverInfo, "currentgame").toInt();
|
||||||
}
|
}
|
||||||
@@ -269,14 +269,16 @@ NvHTTP::getDisplayModeList(QString serverInfo)
|
|||||||
if (name == QString("DisplayMode")) {
|
if (name == QString("DisplayMode")) {
|
||||||
modes.append(NvDisplayMode());
|
modes.append(NvDisplayMode());
|
||||||
}
|
}
|
||||||
else if (name == QString("Width")) {
|
else if (!modes.isEmpty()) {
|
||||||
modes.last().width = xmlReader.readElementText().toInt();
|
if (name == QString("Width")) {
|
||||||
}
|
modes.last().width = xmlReader.readElementText().toInt();
|
||||||
else if (name == QString("Height")) {
|
}
|
||||||
modes.last().height = xmlReader.readElementText().toInt();
|
else if (name == QString("Height")) {
|
||||||
}
|
modes.last().height = xmlReader.readElementText().toInt();
|
||||||
else if (name == QString("RefreshRate")) {
|
}
|
||||||
modes.last().refreshRate = xmlReader.readElementText().toInt();
|
else if (name == QString("RefreshRate")) {
|
||||||
|
modes.last().refreshRate = xmlReader.readElementText().toInt();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -307,17 +309,19 @@ NvHTTP::getAppList()
|
|||||||
}
|
}
|
||||||
apps.append(NvApp());
|
apps.append(NvApp());
|
||||||
}
|
}
|
||||||
else if (name == QString("AppTitle")) {
|
else if (!apps.isEmpty()) {
|
||||||
apps.last().name = xmlReader.readElementText();
|
if (name == QString("AppTitle")) {
|
||||||
}
|
apps.last().name = xmlReader.readElementText();
|
||||||
else if (name == QString("ID")) {
|
}
|
||||||
apps.last().id = xmlReader.readElementText().toInt();
|
else if (name == QString("ID")) {
|
||||||
}
|
apps.last().id = xmlReader.readElementText().toInt();
|
||||||
else if (name == QString("IsHdrSupported")) {
|
}
|
||||||
apps.last().hdrSupported = xmlReader.readElementText() == "1";
|
else if (name == QString("IsHdrSupported")) {
|
||||||
}
|
apps.last().hdrSupported = xmlReader.readElementText() == "1";
|
||||||
else if (name == QString("IsAppCollectorGame")) {
|
}
|
||||||
apps.last().isAppCollectorGame = xmlReader.readElementText() == "1";
|
else if (name == QString("IsAppCollectorGame")) {
|
||||||
|
apps.last().isAppCollectorGame = xmlReader.readElementText() == "1";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -383,13 +387,7 @@ QByteArray
|
|||||||
NvHTTP::getXmlStringFromHex(QString xml,
|
NvHTTP::getXmlStringFromHex(QString xml,
|
||||||
QString tagName)
|
QString tagName)
|
||||||
{
|
{
|
||||||
QString str = getXmlString(xml, tagName);
|
return QByteArray::fromHex(getXmlString(xml, tagName).toUtf8());
|
||||||
if (str == nullptr)
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return QByteArray::fromHex(str.toUtf8());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString
|
QString
|
||||||
@@ -411,7 +409,7 @@ NvHTTP::getXmlString(QString xml,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NvHTTP::handleSslErrors(QNetworkReply* reply, const QList<QSslError>& errors)
|
void NvHTTP::handleSslErrors(QNetworkReply* reply, const QList<QSslError>& errors)
|
||||||
|
|||||||
@@ -54,16 +54,18 @@ NvPairingManager::generateRandomBytes(int length)
|
|||||||
QByteArray
|
QByteArray
|
||||||
NvPairingManager::encrypt(const QByteArray& plaintext, const QByteArray& key)
|
NvPairingManager::encrypt(const QByteArray& plaintext, const QByteArray& key)
|
||||||
{
|
{
|
||||||
QByteArray ciphertext(plaintext.size(), 0);
|
if (plaintext.isEmpty()) {
|
||||||
EVP_CIPHER_CTX* cipher;
|
return QByteArray();
|
||||||
int ciphertextLen;
|
}
|
||||||
|
|
||||||
cipher = EVP_CIPHER_CTX_new();
|
EVP_CIPHER_CTX* cipher = EVP_CIPHER_CTX_new();
|
||||||
THROW_BAD_ALLOC_IF_NULL(cipher);
|
THROW_BAD_ALLOC_IF_NULL(cipher);
|
||||||
|
|
||||||
EVP_EncryptInit(cipher, EVP_aes_128_ecb(), reinterpret_cast<const unsigned char*>(key.data()), NULL);
|
EVP_EncryptInit(cipher, EVP_aes_128_ecb(), reinterpret_cast<const unsigned char*>(key.data()), NULL);
|
||||||
EVP_CIPHER_CTX_set_padding(cipher, 0);
|
EVP_CIPHER_CTX_set_padding(cipher, 0);
|
||||||
|
|
||||||
|
QByteArray ciphertext(plaintext.size(), 0);
|
||||||
|
int ciphertextLen;
|
||||||
EVP_EncryptUpdate(cipher,
|
EVP_EncryptUpdate(cipher,
|
||||||
reinterpret_cast<unsigned char*>(ciphertext.data()),
|
reinterpret_cast<unsigned char*>(ciphertext.data()),
|
||||||
&ciphertextLen,
|
&ciphertextLen,
|
||||||
@@ -79,16 +81,18 @@ NvPairingManager::encrypt(const QByteArray& plaintext, const QByteArray& key)
|
|||||||
QByteArray
|
QByteArray
|
||||||
NvPairingManager::decrypt(const QByteArray& ciphertext, const QByteArray& key)
|
NvPairingManager::decrypt(const QByteArray& ciphertext, const QByteArray& key)
|
||||||
{
|
{
|
||||||
QByteArray plaintext(ciphertext.size(), 0);
|
if (ciphertext.isEmpty()) {
|
||||||
EVP_CIPHER_CTX* cipher;
|
return QByteArray();
|
||||||
int plaintextLen;
|
}
|
||||||
|
|
||||||
cipher = EVP_CIPHER_CTX_new();
|
EVP_CIPHER_CTX* cipher = EVP_CIPHER_CTX_new();
|
||||||
THROW_BAD_ALLOC_IF_NULL(cipher);
|
THROW_BAD_ALLOC_IF_NULL(cipher);
|
||||||
|
|
||||||
EVP_DecryptInit(cipher, EVP_aes_128_ecb(), reinterpret_cast<const unsigned char*>(key.data()), NULL);
|
EVP_DecryptInit(cipher, EVP_aes_128_ecb(), reinterpret_cast<const unsigned char*>(key.data()), NULL);
|
||||||
EVP_CIPHER_CTX_set_padding(cipher, 0);
|
EVP_CIPHER_CTX_set_padding(cipher, 0);
|
||||||
|
|
||||||
|
QByteArray plaintext(ciphertext.size(), 0);
|
||||||
|
int plaintextLen;
|
||||||
EVP_DecryptUpdate(cipher,
|
EVP_DecryptUpdate(cipher,
|
||||||
reinterpret_cast<unsigned char*>(plaintext.data()),
|
reinterpret_cast<unsigned char*>(plaintext.data()),
|
||||||
&plaintextLen,
|
&plaintextLen,
|
||||||
@@ -239,8 +243,7 @@ NvPairingManager::pair(QString appVersion, QString pin, QSslCertificate& serverC
|
|||||||
}
|
}
|
||||||
|
|
||||||
QByteArray serverCertStr = NvHTTP::getXmlStringFromHex(getCert, "plaincert");
|
QByteArray serverCertStr = NvHTTP::getXmlStringFromHex(getCert, "plaincert");
|
||||||
if (serverCertStr == nullptr)
|
if (serverCertStr.isEmpty()) {
|
||||||
{
|
|
||||||
qCritical() << "Server likely already pairing";
|
qCritical() << "Server likely already pairing";
|
||||||
m_Http.openConnectionToString(m_Http.m_BaseUrlHttp, "unpair", nullptr, REQUEST_TIMEOUT_MS);
|
m_Http.openConnectionToString(m_Http.m_BaseUrlHttp, "unpair", nullptr, REQUEST_TIMEOUT_MS);
|
||||||
return PairState::ALREADY_IN_PROGRESS;
|
return PairState::ALREADY_IN_PROGRESS;
|
||||||
@@ -275,6 +278,12 @@ NvPairingManager::pair(QString appVersion, QString pin, QSslCertificate& serverC
|
|||||||
}
|
}
|
||||||
|
|
||||||
QByteArray challengeResponseData = decrypt(m_Http.getXmlStringFromHex(challengeXml, "challengeresponse"), aesKey);
|
QByteArray challengeResponseData = decrypt(m_Http.getXmlStringFromHex(challengeXml, "challengeresponse"), aesKey);
|
||||||
|
if (challengeResponseData.size() < hashLength) {
|
||||||
|
qCritical() << "Invalid challengeresponse at stage #2";
|
||||||
|
m_Http.openConnectionToString(m_Http.m_BaseUrlHttp, "unpair", nullptr, REQUEST_TIMEOUT_MS);
|
||||||
|
return PairState::FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
QByteArray clientSecretData = generateRandomBytes(16);
|
QByteArray clientSecretData = generateRandomBytes(16);
|
||||||
QByteArray challengeResponse;
|
QByteArray challengeResponse;
|
||||||
QByteArray serverResponse(challengeResponseData.data(), hashLength);
|
QByteArray serverResponse(challengeResponseData.data(), hashLength);
|
||||||
@@ -300,6 +309,12 @@ NvPairingManager::pair(QString appVersion, QString pin, QSslCertificate& serverC
|
|||||||
}
|
}
|
||||||
|
|
||||||
QByteArray pairingSecret = NvHTTP::getXmlStringFromHex(respXml, "pairingsecret");
|
QByteArray pairingSecret = NvHTTP::getXmlStringFromHex(respXml, "pairingsecret");
|
||||||
|
if (pairingSecret.size() <= 16) {
|
||||||
|
qCritical() << "Invalid pairingsecret at stage #3";
|
||||||
|
m_Http.openConnectionToString(m_Http.m_BaseUrlHttp, "unpair", nullptr, REQUEST_TIMEOUT_MS);
|
||||||
|
return PairState::FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
QByteArray serverSecret = pairingSecret.left(16);
|
QByteArray serverSecret = pairingSecret.left(16);
|
||||||
QByteArray serverSignature = pairingSecret.mid(16);
|
QByteArray serverSignature = pairingSecret.mid(16);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user