From 45c7c3a0b626000fc0f106aacfbdbed27efbc498 Mon Sep 17 00:00:00 2001 From: Koncord Date: Tue, 3 Jul 2018 02:21:36 +0800 Subject: [PATCH] [General] Add integrity checks to PacketPreInit --- .../openmw-mp/Packets/PacketPreInit.cpp | 92 ++++++++++++++----- .../openmw-mp/Packets/PacketPreInit.hpp | 5 +- 2 files changed, 75 insertions(+), 22 deletions(-) diff --git a/components/openmw-mp/Packets/PacketPreInit.cpp b/components/openmw-mp/Packets/PacketPreInit.cpp index 5fd4433af..ad04c5280 100644 --- a/components/openmw-mp/Packets/PacketPreInit.cpp +++ b/components/openmw-mp/Packets/PacketPreInit.cpp @@ -1,5 +1,5 @@ #include -#include +#include #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 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; } } diff --git a/components/openmw-mp/Packets/PacketPreInit.hpp b/components/openmw-mp/Packets/PacketPreInit.hpp index 505992523..ebc59c225 100644 --- a/components/openmw-mp/Packets/PacketPreInit.hpp +++ b/components/openmw-mp/Packets/PacketPreInit.hpp @@ -10,7 +10,7 @@ namespace mwmp class PacketPreInit : public BasePacket { public: - typedef std::vector HashList; + typedef std::vector HashList; typedef std::pair PluginPair; typedef std::vector 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; }; }