[General] Add integrity checks to PacketPreInit

This commit is contained in:
Koncord 2018-07-03 02:21:36 +08:00
parent d999cc0d55
commit 45c7c3a0b6
2 changed files with 75 additions and 22 deletions

View file

@ -1,5 +1,5 @@
#include <components/openmw-mp/NetworkMessages.hpp>
#include <boost/foreach.hpp>
#include <components/openmw-mp/Log.hpp>
#include "PacketPreInit.hpp"
mwmp::PacketPreInit::PacketPreInit(RakNet::RakPeerInterface *peer) : BasePacket(peer)
@ -11,30 +11,80 @@ void mwmp::PacketPreInit::Packet(RakNet::BitStream *bs, bool send)
{
BasePacket::Packet(bs, send);
size_t size = checksums->size();
RW(size, send);
for (size_t i = 0; i < size; i++)
const RakNet::BitSize_t packetSize = bs->GetNumberOfBytesUsed();
uint32_t expectedPacketSize = BasePacket::headerSize() + sizeof(uint32_t);
if (!send && expectedPacketSize > packetSize)
{
LOG_MESSAGE(Log::LOG_ERROR, "Wrong packet size %d when expected %d", packetSize, expectedPacketSize);
packetValid = false;
return;
}
uint32_t numberOfChecksums = checksums->size();
RW(numberOfChecksums, send);
if (numberOfChecksums > maxPlugins)
{
LOG_MESSAGE(Log::LOG_ERROR, "Wrong number of checksums %d when maximum is %d", numberOfChecksums, maxPlugins);
packetValid = false;
return;
}
struct NAS
{
uint32_t hashN;
uint32_t strSize;
};
std::vector<NAS> NumberOfHashesAndStrSizes(numberOfChecksums);
PluginContainer::const_iterator checksumIt = checksums->begin();
for (auto &&nas : NumberOfHashesAndStrSizes)
{
PluginPair ppair;
if (send)
ppair = (*checksums)[i];
RW(ppair.first, send);
size_t hashSize = ppair.second.size();
RW(hashSize, send);
for (size_t j = 0; j < hashSize; j++)
{
unsigned hash;
if (send)
hash = ppair.second[j];
RW(hash, send);
if (!send)
ppair.second.push_back(hash);
nas.strSize = checksumIt->first.size();
nas.hashN = checksumIt++->second.size();
}
if (!send)
checksums->push_back(ppair);
RW(nas, send);
expectedPacketSize += nas.strSize + nas.hashN;
if (nas.strSize > pluginNameMaxLength)
LOG_MESSAGE(Log::LOG_ERROR, "Wrong string length %d when maximum length is %d",
nas.strSize,
pluginNameMaxLength);
else if (nas.hashN > maxHashes)
LOG_MESSAGE(Log::LOG_ERROR, "Wrong number of hashes %d when maximum is %d", nas.hashN, maxHashes);
else
continue;
packetValid = false;
return;
}
if (!send && expectedPacketSize == packetSize) // server accepted plugin list via sending "empty" packet
return;
if (!send && expectedPacketSize > packetSize)
{
LOG_MESSAGE(Log::LOG_ERROR, "Wrong packet size %d when expected %d", packetSize, expectedPacketSize);
packetValid = false;
return;
}
checksums->resize(numberOfChecksums);
auto numberOfHashesIt = NumberOfHashesAndStrSizes.cbegin();
for (auto &&checksum : *checksums)
{
RW(checksum.first, send, false, numberOfHashesIt->strSize);
checksum.second.resize(numberOfHashesIt->hashN);
for (auto &&hash : checksum.second)
RW(hash, send);
++numberOfHashesIt;
}
}

View file

@ -10,7 +10,7 @@ namespace mwmp
class PacketPreInit : public BasePacket
{
public:
typedef std::vector<unsigned> HashList;
typedef std::vector<uint32_t> HashList;
typedef std::pair<std::string, HashList> PluginPair;
typedef std::vector<PluginPair> PluginContainer;
@ -20,6 +20,9 @@ namespace mwmp
void setChecksums(PluginContainer *checksums);
private:
PluginContainer *checksums;
const static uint32_t maxPlugins = 256;
const static uint32_t pluginNameMaxLength = 256;
const static uint32_t maxHashes = 16;
};
}