From da876cc8f3c5aaca4c19d6d34f9ce12af61604b4 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Sat, 21 Jul 2018 14:31:34 +0100 Subject: [PATCH] ResourcePacksSessionHandler: Prevent clients requesting the same chunk more than once Currently this can be used to attack the server by spamming requests for the same chunks forever. This commit prevents that by disconnecting the client if a chunk is requested more than 1 time. It is not necessary to allow more than 1 request per chunk, since RakNet should ensure that these are always delivered correctly. --- .../handler/ResourcePacksSessionHandler.php | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/pocketmine/network/mcpe/handler/ResourcePacksSessionHandler.php b/src/pocketmine/network/mcpe/handler/ResourcePacksSessionHandler.php index 105a1829b..8d22d04d6 100644 --- a/src/pocketmine/network/mcpe/handler/ResourcePacksSessionHandler.php +++ b/src/pocketmine/network/mcpe/handler/ResourcePacksSessionHandler.php @@ -48,6 +48,9 @@ class ResourcePacksSessionHandler extends SessionHandler{ /** @var ResourcePackManager */ private $resourcePackManager; + /** @var bool[][] uuid => [chunk index => hasSent] */ + private $downloadedChunks = []; + public function __construct(Player $player, NetworkSession $session, ResourcePackManager $resourcePackManager){ $this->player = $player; $this->session = $session; @@ -113,6 +116,15 @@ class ResourcePacksSessionHandler extends SessionHandler{ return false; } + $packId = $pack->getPackId(); //use this because case may be different + + if(isset($this->downloadedChunks[$packId][$packet->chunkIndex])){ + $this->player->close("", "disconnectionScreen.resourcePack", true); + $this->player->getServer()->getLogger()->debug("Got a duplicate resource pack chunk request for pack " . $packet->packId . " chunk $packet->chunkIndex"); + + return false; + } + $offset = $packet->chunkIndex * self::PACK_CHUNK_SIZE; if($offset < 0 or $offset >= $pack->getPackSize()){ $this->player->close("", "disconnectionScreen.resourcePack", true); @@ -121,8 +133,14 @@ class ResourcePacksSessionHandler extends SessionHandler{ return false; } + if(!isset($this->downloadedChunks[$packId])){ + $this->downloadedChunks[$packId] = [$packet->chunkIndex => true]; + }else{ + $this->downloadedChunks[$packId][$packet->chunkIndex] = true; + } + $pk = new ResourcePackChunkDataPacket(); - $pk->packId = $pack->getPackId(); + $pk->packId = $packId; $pk->chunkIndex = $packet->chunkIndex; $pk->data = $pack->getPackChunk($offset, self::PACK_CHUNK_SIZE); $pk->progress = $offset;