From 738e310798f5a4742b2dc81a926bd0989e543ee5 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 23 Jan 2019 20:39:16 +0000 Subject: [PATCH] Strip out RCON, closes #2686 Users should move to the new RconServer plugin instead. --- src/pocketmine/CrashDump.php | 2 - src/pocketmine/Server.php | 24 -- .../command/RemoteConsoleCommandSender.php | 51 ---- src/pocketmine/network/rcon/RCON.php | 126 --------- src/pocketmine/network/rcon/RCONInstance.php | 267 ------------------ src/pocketmine/wizard/SetupWizard.php | 13 - 6 files changed, 483 deletions(-) delete mode 100644 src/pocketmine/command/RemoteConsoleCommandSender.php delete mode 100644 src/pocketmine/network/rcon/RCON.php delete mode 100644 src/pocketmine/network/rcon/RCONInstance.php diff --git a/src/pocketmine/CrashDump.php b/src/pocketmine/CrashDump.php index 4131a6023..7c9cfeb80 100644 --- a/src/pocketmine/CrashDump.php +++ b/src/pocketmine/CrashDump.php @@ -53,7 +53,6 @@ use function ob_start; use function php_uname; use function phpinfo; use function phpversion; -use function preg_replace; use function str_split; use function strpos; use function substr; @@ -173,7 +172,6 @@ class CrashDump{ if($this->server->getProperty("auto-report.send-settings", true) !== false){ $this->data["parameters"] = (array) $argv; $this->data["server.properties"] = @file_get_contents($this->server->getDataPath() . "server.properties"); - $this->data["server.properties"] = preg_replace("#^rcon\\.password=(.*)$#m", "rcon.password=******", $this->data["server.properties"]); $this->data["pocketmine.yml"] = @file_get_contents($this->server->getDataPath() . "pocketmine.yml"); }else{ $this->data["pocketmine.yml"] = ""; diff --git a/src/pocketmine/Server.php b/src/pocketmine/Server.php index ba197174c..2ba02af18 100644 --- a/src/pocketmine/Server.php +++ b/src/pocketmine/Server.php @@ -74,7 +74,6 @@ use pocketmine\network\mcpe\protocol\types\PlayerListEntry; use pocketmine\network\mcpe\RakLibInterface; use pocketmine\network\Network; use pocketmine\network\query\QueryHandler; -use pocketmine\network\rcon\RCON; use pocketmine\network\upnp\UPnP; use pocketmine\permission\BanList; use pocketmine\permission\DefaultPermissions; @@ -143,7 +142,6 @@ use function stripos; use function strlen; use function strrpos; use function strtolower; -use function substr; use function time; use function touch; use function trim; @@ -245,9 +243,6 @@ class Server{ /** @var bool */ private $onlineMode = true; - /** @var RCON */ - private $rcon; - /** @var EntityMetadataStore */ private $entityMetadata; @@ -1087,8 +1082,6 @@ class Server{ "level-seed" => "", "level-type" => "DEFAULT", "enable-query" => true, - "enable-rcon" => false, - "rcon.password" => substr(base64_encode(random_bytes(20)), 3, 10), "auto-save" => true, "view-distance" => 8, "xbox-auth" => true, @@ -1191,20 +1184,6 @@ class Server{ }); $this->console->start(PTHREADS_INHERIT_NONE); - if($this->getConfigBool("enable-rcon", false)){ - try{ - $this->rcon = new RCON( - $this, - $this->getConfigString("rcon.password", ""), - $this->getConfigInt("rcon.port", $this->getPort()), - $this->getIp(), - $this->getConfigInt("rcon.max-clients", 50) - ); - }catch(\RuntimeException $e){ - $this->getLogger()->critical("RCON can't be started: " . $e->getMessage()); - } - } - $this->entityMetadata = new EntityMetadataStore(); $this->playerMetadata = new PlayerMetadataStore(); $this->levelMetadata = new LevelMetadataStore(); @@ -1692,9 +1671,6 @@ class Server{ $this->hasStopped = true; $this->shutdown(); - if($this->rcon instanceof RCON){ - $this->rcon->stop(); - } if($this->getProperty("network.upnp-forwarding", false)){ $this->logger->info("[UPnP] Removing port forward..."); diff --git a/src/pocketmine/command/RemoteConsoleCommandSender.php b/src/pocketmine/command/RemoteConsoleCommandSender.php deleted file mode 100644 index 054d7ad88..000000000 --- a/src/pocketmine/command/RemoteConsoleCommandSender.php +++ /dev/null @@ -1,51 +0,0 @@ -getServer()->getLanguage()->translate($message); - }else{ - $message = $this->getServer()->getLanguage()->translateString($message); - } - - $this->messages .= trim($message, "\r\n") . "\n"; - } - - public function getMessage(){ - return $this->messages; - } - - public function getName() : string{ - return "Rcon"; - } -} diff --git a/src/pocketmine/network/rcon/RCON.php b/src/pocketmine/network/rcon/RCON.php deleted file mode 100644 index 19aae8c60..000000000 --- a/src/pocketmine/network/rcon/RCON.php +++ /dev/null @@ -1,126 +0,0 @@ -server = $server; - $this->server->getLogger()->info("Starting remote control listener"); - if($password === ""){ - throw new \RuntimeException("Empty password"); - } - - $this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); - - if($this->socket === false or !@socket_bind($this->socket, $interface, $port) or !@socket_listen($this->socket, 5)){ - throw new \RuntimeException(trim(socket_strerror(socket_last_error()))); - } - - socket_set_block($this->socket); - - $ret = @socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $ipc); - if(!$ret){ - $err = socket_last_error(); - if(($err !== SOCKET_EPROTONOSUPPORT and $err !== SOCKET_ENOPROTOOPT) or !@socket_create_pair(AF_INET, SOCK_STREAM, 0, $ipc)){ - throw new \RuntimeException(trim(socket_strerror(socket_last_error()))); - } - } - - [$this->ipcMainSocket, $this->ipcThreadSocket] = $ipc; - - $notifier = new SleeperNotifier(); - $this->server->getTickSleeper()->addNotifier($notifier, function() : void{ - $response = new RemoteConsoleCommandSender(); - $this->server->dispatchCommand($response, $this->instance->cmd); - - $this->instance->response = TextFormat::clean($response->getMessage()); - $this->instance->synchronized(function(RCONInstance $thread){ - $thread->notify(); - }, $this->instance); - }); - $this->instance = new RCONInstance($this->socket, $password, (int) max(1, $maxClients), $this->server->getLogger(), $this->ipcThreadSocket, $notifier); - - socket_getsockname($this->socket, $addr, $port); - $this->server->getLogger()->info("RCON running on $addr:$port"); - } - - public function stop() : void{ - $this->instance->close(); - socket_write($this->ipcMainSocket, "\x00"); //make select() return - $this->instance->quit(); - - @socket_close($this->socket); - @socket_close($this->ipcMainSocket); - @socket_close($this->ipcThreadSocket); - } -} diff --git a/src/pocketmine/network/rcon/RCONInstance.php b/src/pocketmine/network/rcon/RCONInstance.php deleted file mode 100644 index 9b852d114..000000000 --- a/src/pocketmine/network/rcon/RCONInstance.php +++ /dev/null @@ -1,267 +0,0 @@ -stop = false; - $this->cmd = ""; - $this->response = ""; - $this->socket = $socket; - $this->password = $password; - $this->maxClients = $maxClients; - $this->logger = $logger; - $this->ipcSocket = $ipcSocket; - $this->notifier = $notifier; - - $this->start(PTHREADS_INHERIT_NONE); - } - - private function writePacket($client, int $requestID, int $packetType, string $payload){ - $pk = Binary::writeLInt($requestID) - . Binary::writeLInt($packetType) - . $payload - . "\x00\x00"; //Terminate payload and packet - return socket_write($client, Binary::writeLInt(strlen($pk)) . $pk); - } - - private function readPacket($client, ?int &$requestID, ?int &$packetType, ?string &$payload){ - $d = @socket_read($client, 4); - - socket_getpeername($client, $ip, $port); - if($d === false){ - $err = socket_last_error($client); - if($err !== SOCKET_ECONNRESET){ - $this->logger->debug("Connection error with $ip $port: " . trim(socket_strerror($err))); - } - return false; - } - if(strlen($d) !== 4){ - if($d !== ""){ //empty data is returned on disconnection - $this->logger->debug("Truncated packet from $ip $port (want 4 bytes, have " . strlen($d) . "), disconnecting"); - } - return false; - } - $size = Binary::readLInt($d); - if($size < 0 or $size > 65535){ - $this->logger->debug("Packet with too-large length header $size from $ip $port, disconnecting"); - return false; - } - $buf = @socket_read($client, $size); - if($buf === false){ - $err = socket_last_error($client); - if($err !== SOCKET_ECONNRESET){ - $this->logger->debug("Connection error with $ip $port: " . trim(socket_strerror($err))); - } - return false; - } - if(strlen($buf) !== $size){ - $this->logger->debug("Truncated packet from $ip $port (want $size bytes, have " . strlen($buf) . "), disconnecting"); - return false; - } - $requestID = Binary::readLInt(substr($buf, 0, 4)); - $packetType = Binary::readLInt(substr($buf, 4, 4)); - $payload = substr($buf, 8, -2); //Strip two null bytes - return true; - } - - public function close() : void{ - $this->stop = true; - } - - public function run() : void{ - $this->registerClassLoader(); - - /** @var resource[] $clients */ - $clients = []; - /** @var int[] $authenticated */ - $authenticated = []; - /** @var float[] $timeouts */ - $timeouts = []; - - /** @var int $nextClientId */ - $nextClientId = 0; - - while(!$this->stop){ - $r = $clients; - $r["main"] = $this->socket; //this is ugly, but we need to be able to mass-select() - $r["ipc"] = $this->ipcSocket; - $w = null; - $e = null; - - $disconnect = []; - - if(socket_select($r, $w, $e, 5, 0) > 0){ - foreach($r as $id => $sock){ - if($sock === $this->socket){ - if(($client = socket_accept($this->socket)) !== false){ - if(count($clients) >= $this->maxClients){ - @socket_close($client); - }else{ - socket_set_nonblock($client); - socket_set_option($client, SOL_SOCKET, SO_KEEPALIVE, 1); - - $id = $nextClientId++; - $clients[$id] = $client; - $authenticated[$id] = false; - $timeouts[$id] = microtime(true) + 5; - } - } - }elseif($sock === $this->ipcSocket){ - //read dummy data - socket_read($sock, 65535); - }else{ - $p = $this->readPacket($sock, $requestID, $packetType, $payload); - if($p === false){ - $disconnect[$id] = $sock; - continue; - }elseif($p === null){ - continue; - } - - switch($packetType){ - case 3: //Login - if($authenticated[$id]){ - $disconnect[$id] = $sock; - break; - } - if($payload === $this->password){ - socket_getpeername($sock, $addr, $port); - $this->logger->info("Successful Rcon connection from: /$addr:$port"); - $this->writePacket($sock, $requestID, 2, ""); - $authenticated[$id] = true; - }else{ - $disconnect[$id] = $sock; - $this->writePacket($sock, -1, 2, ""); - } - break; - case 2: //Command - if(!$authenticated[$id]){ - $disconnect[$id] = $sock; - break; - } - if($payload !== ""){ - $this->cmd = ltrim($payload); - $this->synchronized(function(){ - $this->notifier->wakeupSleeper(); - $this->wait(); - }); - $this->writePacket($sock, $requestID, 0, str_replace("\n", "\r\n", trim($this->response))); - $this->response = ""; - $this->cmd = ""; - } - break; - } - } - } - } - - foreach($authenticated as $id => $status){ - if(!isset($disconnect[$id]) and !$authenticated[$id] and $timeouts[$id] < microtime(true)){ //Timeout - $disconnect[$id] = $clients[$id]; - } - } - - foreach($disconnect as $id => $client){ - $this->disconnectClient($client); - unset($clients[$id], $authenticated[$id], $timeouts[$id]); - } - } - - foreach($clients as $client){ - $this->disconnectClient($client); - } - } - - private function disconnectClient($client) : void{ - socket_getpeername($client, $ip, $port); - @socket_set_option($client, SOL_SOCKET, SO_LINGER, ["l_onoff" => 1, "l_linger" => 1]); - @socket_shutdown($client, 2); - @socket_set_block($client); - @socket_read($client, 1); - @socket_close($client); - $this->logger->info("Disconnected client: /$ip:$port"); - } - - public function getThreadName() : string{ - return "RCON"; - } -} diff --git a/src/pocketmine/wizard/SetupWizard.php b/src/pocketmine/wizard/SetupWizard.php index 548ff372c..af2356aa8 100644 --- a/src/pocketmine/wizard/SetupWizard.php +++ b/src/pocketmine/wizard/SetupWizard.php @@ -31,13 +31,10 @@ use pocketmine\lang\Language; use pocketmine\lang\LanguageNotFoundException; use pocketmine\utils\Config; use pocketmine\utils\Internet; -use function base64_encode; use function fgets; use function gethostbyname; -use function random_bytes; use function sleep; use function strtolower; -use function substr; use function trim; use const PHP_EOL; use const STDIN; @@ -206,16 +203,6 @@ LICENSE; $config->set("enable-query", true); } - $this->message($this->lang->get("rcon_info")); - if(strtolower($this->getInput($this->lang->get("rcon_enable"), "n", "y/N")) === "y"){ - $config->set("enable-rcon", true); - $password = substr(base64_encode(random_bytes(20)), 3, 10); - $config->set("rcon.password", $password); - $this->message($this->lang->get("rcon_password") . ": " . $password); - }else{ - $config->set("enable-rcon", false); - } - $config->save();