mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-07-06 01:51:51 +00:00
Properly handle Query packet errors
This commit is contained in:
parent
38cf8d157d
commit
2dee7e9e0f
@ -2118,17 +2118,9 @@ class Server{
|
|||||||
* TODO: move this to Network
|
* TODO: move this to Network
|
||||||
*/
|
*/
|
||||||
public function handlePacket(AdvancedNetworkInterface $interface, string $address, int $port, string $payload){
|
public function handlePacket(AdvancedNetworkInterface $interface, string $address, int $port, string $payload){
|
||||||
try{
|
if($this->queryHandler === null or !$this->queryHandler->handle($interface, $address, $port, $payload)){
|
||||||
if(strlen($payload) > 2 and substr($payload, 0, 2) === "\xfe\xfd" and $this->queryHandler instanceof QueryHandler){
|
|
||||||
$this->queryHandler->handle($interface, $address, $port, $payload);
|
|
||||||
}else{
|
|
||||||
$this->logger->debug("Unhandled raw packet from $address $port: " . bin2hex($payload));
|
$this->logger->debug("Unhandled raw packet from $address $port: " . bin2hex($payload));
|
||||||
}
|
}
|
||||||
}catch(\Throwable $e){
|
|
||||||
$this->logger->logException($e);
|
|
||||||
|
|
||||||
$this->getNetwork()->blockAddress($address, 600);
|
|
||||||
}
|
|
||||||
//TODO: add raw packet events
|
//TODO: add raw packet events
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,11 +30,11 @@ namespace pocketmine\network\query;
|
|||||||
use pocketmine\network\AdvancedNetworkInterface;
|
use pocketmine\network\AdvancedNetworkInterface;
|
||||||
use pocketmine\Server;
|
use pocketmine\Server;
|
||||||
use pocketmine\utils\Binary;
|
use pocketmine\utils\Binary;
|
||||||
use function bin2hex;
|
use pocketmine\utils\BinaryDataException;
|
||||||
|
use pocketmine\utils\BinaryStream;
|
||||||
use function chr;
|
use function chr;
|
||||||
use function hash;
|
use function hash;
|
||||||
use function microtime;
|
use function microtime;
|
||||||
use function ord;
|
|
||||||
use function random_bytes;
|
use function random_bytes;
|
||||||
use function strlen;
|
use function strlen;
|
||||||
use function substr;
|
use function substr;
|
||||||
@ -88,12 +88,23 @@ class QueryHandler{
|
|||||||
return Binary::readInt(substr(hash("sha512", $salt . ":" . $token, true), 7, 4));
|
return Binary::readInt(substr(hash("sha512", $salt . ":" . $token, true), 7, 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handle(AdvancedNetworkInterface $interface, string $address, int $port, string $packet) : void{
|
/**
|
||||||
$offset = 2;
|
* @param AdvancedNetworkInterface $interface
|
||||||
$packetType = ord($packet{$offset++});
|
* @param string $address
|
||||||
$sessionID = Binary::readInt(substr($packet, $offset, 4));
|
* @param int $port
|
||||||
$offset += 4;
|
* @param string $packet
|
||||||
$payload = substr($packet, $offset);
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function handle(AdvancedNetworkInterface $interface, string $address, int $port, string $packet) : bool{
|
||||||
|
try{
|
||||||
|
$stream = new BinaryStream($packet);
|
||||||
|
$header = $stream->get(2);
|
||||||
|
if($header !== "\xfe\xfd"){ //TODO: have this filtered by the regex filter we installed above
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$packetType = $stream->getByte();
|
||||||
|
$sessionID = $stream->getInt();
|
||||||
|
|
||||||
switch($packetType){
|
switch($packetType){
|
||||||
case self::HANDSHAKE: //Handshake
|
case self::HANDSHAKE: //Handshake
|
||||||
@ -102,12 +113,14 @@ class QueryHandler{
|
|||||||
$reply .= self::getTokenString($this->token, $address) . "\x00";
|
$reply .= self::getTokenString($this->token, $address) . "\x00";
|
||||||
|
|
||||||
$interface->sendRawPacket($address, $port, $reply);
|
$interface->sendRawPacket($address, $port, $reply);
|
||||||
break;
|
|
||||||
|
return true;
|
||||||
case self::STATISTICS: //Stat
|
case self::STATISTICS: //Stat
|
||||||
$token = Binary::readInt(substr($payload, 0, 4));
|
$token = $stream->getInt();
|
||||||
if($token !== ($t1 = self::getTokenString($this->token, $address)) and $token !== ($t2 = self::getTokenString($this->lastToken, $address))){
|
if($token !== ($t1 = self::getTokenString($this->token, $address)) and $token !== ($t2 = self::getTokenString($this->lastToken, $address))){
|
||||||
$this->debug("Bad token $token from $address $port, expected $t1 or $t2");
|
$this->debug("Bad token $token from $address $port, expected $t1 or $t2");
|
||||||
break;
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
$reply = chr(self::STATISTICS);
|
$reply = chr(self::STATISTICS);
|
||||||
$reply .= Binary::writeInt($sessionID);
|
$reply .= Binary::writeInt($sessionID);
|
||||||
@ -116,16 +129,21 @@ class QueryHandler{
|
|||||||
$this->regenerateInfo();
|
$this->regenerateInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(strlen($payload) === 8){
|
$remaining = $stream->getRemaining();
|
||||||
|
if(strlen($remaining) === 4){ //TODO: check this! according to the spec, this should always be here and always be FF FF FF 01
|
||||||
$reply .= $this->longData;
|
$reply .= $this->longData;
|
||||||
}else{
|
}else{
|
||||||
$reply .= $this->shortData;
|
$reply .= $this->shortData;
|
||||||
}
|
}
|
||||||
$interface->sendRawPacket($address, $port, $reply);
|
$interface->sendRawPacket($address, $port, $reply);
|
||||||
break;
|
|
||||||
|
return true;
|
||||||
default:
|
default:
|
||||||
$this->debug("Unhandled packet from $address $port: 0x" . bin2hex($packet));
|
return false;
|
||||||
break;
|
}
|
||||||
|
}catch(BinaryDataException $e){
|
||||||
|
$this->debug("Bad packet from $address $port: " . $e->getMessage());
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user