From df4e0a1dd697e7c336ff17879c6c76d02bbd5a3e Mon Sep 17 00:00:00 2001 From: Paul Rock Date: Sun, 3 Mar 2019 18:05:18 +0300 Subject: [PATCH] endless loop prevention added to login method of Client class --- src/Client.php | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/src/Client.php b/src/Client.php index c9c67df..21cc980 100644 --- a/src/Client.php +++ b/src/Client.php @@ -358,12 +358,13 @@ class Client implements Interfaces\ClientInterface /** * Authorization logic * + * @param bool $legacyRetry Retry login if we detect legacy version of RouterOS * @return bool * @throws \RouterOS\Exceptions\ClientException * @throws \RouterOS\Exceptions\ConfigException * @throws \RouterOS\Exceptions\QueryException */ - private function login(): bool + private function login(bool $legacyRetry = false): bool { // If legacy login scheme is enabled if ($this->config('legacy')) { @@ -380,23 +381,39 @@ class Client implements Interfaces\ClientInterface $query = (new Query('/login')) ->add('=name=' . $this->config('user')) ->add('=password=' . $this->config('pass')); + + // If we set modern auth scheme but router with legacy firmware then need to retry query, + // but need to prevent endless loop + $legacyRetry = true; } // Execute query and get response $response = $this->write($query)->read(false); - // if : + // if: // - we have more than one response // - response is '!done' // => problem with legacy version, swap it and retry - // Only tested with ROS pre 6.43, will test with post 6.43 => this could make legacy parameter obsolete ? - if (count($response)>1 && $response[0] === '!done' && !$this->config('legacy')) - { - $this->_config->set('legacy', true); - return $this->login(); + // Only tested with ROS pre 6.43, will test with post 6.43 => this could make legacy parameter obsolete? + if ($legacyRetry && $this->isLegacy($response)) { + $this->_config->set('legacy', true); + return $this->login(true); } + // Return true if we have only one line from server and this line is !done - return (1 === count($response)) && isset($response[0]) && ($response[0] === '!done'); + return 1 === \count($response) || (isset($response[0]) && $response[0] === '!done'); + } + + /** + * Detect by login request if firmware is legacy + * + * @param array $response + * @return bool + * @throws ConfigException + */ + private function isLegacy(array &$response): bool + { + return \count($response) > 1 && $response[0] === '!done' && !$this->config('legacy'); } /**