mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-04-22 00:33:59 +00:00
Properly handle Query packet errors
This commit is contained in:
parent
38cf8d157d
commit
2dee7e9e0f
@ -2118,16 +2118,8 @@ class Server{
|
||||
* TODO: move this to Network
|
||||
*/
|
||||
public function handlePacket(AdvancedNetworkInterface $interface, string $address, int $port, string $payload){
|
||||
try{
|
||||
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));
|
||||
}
|
||||
}catch(\Throwable $e){
|
||||
$this->logger->logException($e);
|
||||
|
||||
$this->getNetwork()->blockAddress($address, 600);
|
||||
if($this->queryHandler === null or !$this->queryHandler->handle($interface, $address, $port, $payload)){
|
||||
$this->logger->debug("Unhandled raw packet from $address $port: " . bin2hex($payload));
|
||||
}
|
||||
//TODO: add raw packet events
|
||||
}
|
||||
|
@ -30,11 +30,11 @@ namespace pocketmine\network\query;
|
||||
use pocketmine\network\AdvancedNetworkInterface;
|
||||
use pocketmine\Server;
|
||||
use pocketmine\utils\Binary;
|
||||
use function bin2hex;
|
||||
use pocketmine\utils\BinaryDataException;
|
||||
use pocketmine\utils\BinaryStream;
|
||||
use function chr;
|
||||
use function hash;
|
||||
use function microtime;
|
||||
use function ord;
|
||||
use function random_bytes;
|
||||
use function strlen;
|
||||
use function substr;
|
||||
@ -88,44 +88,62 @@ class QueryHandler{
|
||||
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;
|
||||
$packetType = ord($packet{$offset++});
|
||||
$sessionID = Binary::readInt(substr($packet, $offset, 4));
|
||||
$offset += 4;
|
||||
$payload = substr($packet, $offset);
|
||||
/**
|
||||
* @param AdvancedNetworkInterface $interface
|
||||
* @param string $address
|
||||
* @param int $port
|
||||
* @param string $packet
|
||||
*
|
||||
* @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){
|
||||
case self::HANDSHAKE: //Handshake
|
||||
$reply = chr(self::HANDSHAKE);
|
||||
$reply .= Binary::writeInt($sessionID);
|
||||
$reply .= self::getTokenString($this->token, $address) . "\x00";
|
||||
switch($packetType){
|
||||
case self::HANDSHAKE: //Handshake
|
||||
$reply = chr(self::HANDSHAKE);
|
||||
$reply .= Binary::writeInt($sessionID);
|
||||
$reply .= self::getTokenString($this->token, $address) . "\x00";
|
||||
|
||||
$interface->sendRawPacket($address, $port, $reply);
|
||||
break;
|
||||
case self::STATISTICS: //Stat
|
||||
$token = Binary::readInt(substr($payload, 0, 4));
|
||||
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");
|
||||
break;
|
||||
}
|
||||
$reply = chr(self::STATISTICS);
|
||||
$reply .= Binary::writeInt($sessionID);
|
||||
$interface->sendRawPacket($address, $port, $reply);
|
||||
|
||||
if($this->timeout < microtime(true)){
|
||||
$this->regenerateInfo();
|
||||
}
|
||||
return true;
|
||||
case self::STATISTICS: //Stat
|
||||
$token = $stream->getInt();
|
||||
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");
|
||||
|
||||
if(strlen($payload) === 8){
|
||||
$reply .= $this->longData;
|
||||
}else{
|
||||
$reply .= $this->shortData;
|
||||
}
|
||||
$interface->sendRawPacket($address, $port, $reply);
|
||||
break;
|
||||
default:
|
||||
$this->debug("Unhandled packet from $address $port: 0x" . bin2hex($packet));
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
$reply = chr(self::STATISTICS);
|
||||
$reply .= Binary::writeInt($sessionID);
|
||||
|
||||
if($this->timeout < microtime(true)){
|
||||
$this->regenerateInfo();
|
||||
}
|
||||
|
||||
$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;
|
||||
}else{
|
||||
$reply .= $this->shortData;
|
||||
}
|
||||
$interface->sendRawPacket($address, $port, $reply);
|
||||
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}catch(BinaryDataException $e){
|
||||
$this->debug("Bad packet from $address $port: " . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user