#ifdef ANIDBUDPCLIENT_CLIENT_MISC_DEBUG
qDebug() << "ENCRYPED DATAGRAM = " << data;
#endif
- tmp = decrypt(tmp);
+ // If using encryption and the reply is possibly valid before encryption, process it without decrypting.
+ // This is mainly for server errors or cases where the session (and encryption) expires.
+ // TODO Drop out of encryption if this happens?
+ if (!possiblyValid(tmp))
+ tmp = decrypt(tmp);
+
+ if (tmp.isEmpty())
+ goto endLoop;
}
if (authCommand.compression() && tmp.mid(0, 2) == "00")
enqueueControlCommand(createReply(LogoutCommand()), force);
}
-#ifndef ANIDBUDPCLIENT_NO_ENCRYPT
QByteArray Client::encrypt(const QByteArray &data)
{
+#ifdef ANIDBUDPCLIENT_NO_ENCRYPT
+ Q_UNUSED(data);
+ m_error = EncryptionError;
+ m_errorString = tr("AniDBUDPClient built without encryption support");
+ emit connectionError();
+ return QByteArray();
+#else
QCA::init();
if (!QCA::isSupported("aes128-ecb"))
{
- qDebug() << "encryption failed due to no aes128-cbc";
+ m_error = EncryptionError;
+ m_errorString = tr("QCA missing required encryption plugins");
+ emit connectionError();
return QByteArray();
}
c.final(); // Should be empty as data is already padded
// QCA::deinit();
return ret;
+#endif
}
QByteArray Client::decrypt(const QByteArray &data)
{
+#ifdef ANIDBUDPCLIENT_NO_ENCRYPT
+ Q_UNUSED(data);
+ return QByteArray();
+#else
QCA::init();
if (!QCA::isSupported("aes128-ecb"))
{
- qDebug() << "encryption failed due to no aes128-cbc";
+ qDebug() << "decryption failed due to no aes128-cbc";
return QByteArray();
}
#endif
ret += p2;
+ if (ret.size() % 16 != 0)
+ {
+ // Should be a multiple of cipher block size.
+#ifdef ANIDBUDPCLIENT_CLIENT_ENCRYPT_DEBUG
+qDebug() << "Ciphertext not a multiple of cipher block size!!";
+#endif
+ return QByteArray();
+ }
+
// Remove padding (and only it)
char pad = ret[ret.size() - 1];
if (pad > 0 && pad < 16)
}
// QCA::deinit();
return ret;
-}
#endif
+}
+
+bool Client::possiblyValid(const QByteArray &reply) const
+{
+ QByteArray tag = reply.left(5);
+ if (sentCommands.contains(tag))
+ return true;
+ bool ok;
+ tag = reply.left(3);
+ tag.toInt(&ok);
+ if (ok)
+ return true;
+ return false;
+}
void Client::commandTimeout()
{
qDebug() << QString("ENCRYPTED datagram:\n\t%1")
.arg(datagram.constData());
#endif
+ if (datagram.isEmpty())
+ return;
}
socket->writeDatagram(datagram, m_hostAddress, m_hostPort);