From 35a39175ed0b66caab411eaaa36d1c6b82063b3f Mon Sep 17 00:00:00 2001 From: Stricted Date: Sat, 8 Aug 2015 15:26:56 +0200 Subject: [PATCH] do some changes to support other speedport router --- ISpeedport.class.php | 22 +++++ Speedport.class.php | 153 +++++++++++++++++++++++++++++++++++ SpeedportHybrid.class.php | 125 +++++----------------------- Speedportw724v.class.php | 43 +++++++++- lib/trait/CryptLib.class.php | 14 ---- lib/trait/Login.class.php | 25 +----- 6 files changed, 238 insertions(+), 144 deletions(-) create mode 100644 ISpeedport.class.php create mode 100644 Speedport.class.php diff --git a/ISpeedport.class.php b/ISpeedport.class.php new file mode 100644 index 0000000..a613483 --- /dev/null +++ b/ISpeedport.class.php @@ -0,0 +1,22 @@ + + * @copyright 2015 Jan Altensen (Stricted) + */ +interface ISpeedport { + /** + * login into the router with the given password + * + * @param string $password + */ + public function login ($password); + + /** + * get the csrf_token + * + * @return string + */ + protected function getToken (); +} diff --git a/Speedport.class.php b/Speedport.class.php new file mode 100644 index 0000000..52f0916 --- /dev/null +++ b/Speedport.class.php @@ -0,0 +1,153 @@ + + * @copyright 2015 Jan Altensen (Stricted) + */ +class Speedport { + /** + * router url + * @var string + */ + protected $url = ''; + + /** + * hashed password + * @var string + */ + protected $hash = ''; + + /** + * session cookie + * @var string + */ + protected $cookie = ''; + + /** + * csrf_token + * @var string + */ + protected $token = ''; + + /** + * inititalize this class + * + * @param string $url + */ + public function __construct ($url = 'http://speedport.ip/') { + $this->url = $url; + $this->checkRequirements(); + } + + /** + * check php requirements + */ + protected function checkRequirements () { + } + + /** + * get the values from array + * + * @param array $array + * @return array + */ + protected function getValues($array) { + $data = array(); + foreach ($array as $item) { + if (!isset($item['vartype']) || !isset($item['varid']) || !isset($item['varvalue'])) continue; + + // thank you telekom for this piece of shit + if ($item['vartype'] == 'template') { + if (is_array($item['varvalue'])) { + $data[$item['varid']][] = $this->getValues($item['varvalue']); + } + else { + // i dont know if we need this + $data[$item['varid']] = $item['varvalue']; + } + } + else { + if (is_array($item['varvalue'])) { + $data[$item['varid']] = $this->getValues($item['varvalue']); + } + else { + $data[$item['varid']] = $item['varvalue']; + } + } + } + + return $data; + } + + /** + * sends the request to router + * + * @param string $path + * @param mixed $fields + * @param string $cookie + * @param integer $count + * @return array + */ + protected function sentRequest ($path, $fields, $cookie = false, $count = 0) { + $url = $this->url.$path.'?lang=en'; + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + + if (!empty($fields)) { + if (is_array($fields)) { + curl_setopt($ch, CURLOPT_POST, count($fields)); + curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($fields)); + } + else { + curl_setopt($ch, CURLOPT_POST, $count); + curl_setopt($ch, CURLOPT_POSTFIELDS, $fields); + } + } + + if ($cookie === true) { + curl_setopt($ch, CURLOPT_COOKIE, $this->cookie); + } + + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_HEADER, true); + + $result = curl_exec($ch); + + $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE); + $header = substr($result, 0, $header_size); + $body = substr($result, $header_size); + curl_close($ch); + + // check if response is empty + if (empty($body)) { + throw new RouterException('empty response'); + } + + return array('header' => $this->parse_headers($header), 'body' => $body); + } + + /** + * parse the curl return header into an array + * + * @param string $response + * @return array + */ + private function parse_headers($response) { + $headers = array(); + $header_text = substr($response, 0, strpos($response, "\r\n\r\n")); + + $header_text = explode("\r\n", $header_text); + foreach ($header_text as $i => $line) { + if ($i === 0) { + $headers['http_code'] = $line; + } + else { + list ($key, $value) = explode(': ', $line); + $headers[$key] = $value; + } + } + + return $headers; + } +} diff --git a/SpeedportHybrid.class.php b/SpeedportHybrid.class.php index 1ab6207..e5f03a6 100644 --- a/SpeedportHybrid.class.php +++ b/SpeedportHybrid.class.php @@ -2,6 +2,8 @@ require_once('lib/exception/RebootException.class.php'); require_once('lib/exception/RouterException.class.php'); require_once('CryptLib/CryptLib.php'); +require_once('Speedport.class.php'); +require_once('ISpeedport.class.php'); require_once('lib/trait/Connection.class.php'); require_once('lib/trait/CryptLib.class.php'); require_once('lib/trait/Login.class.php'); @@ -15,7 +17,7 @@ require_once('lib/trait/System.class.php'); * @license GNU Lesser General Public License * @copyright 2015 Jan Altensen (Stricted) */ -class SpeedportHybrid { +class SpeedportHybrid extends Speedport implements ISpeedport { use Connection; use CryptLib; use Firewall; @@ -30,26 +32,10 @@ class SpeedportHybrid { */ const VERSION = '1.0.4'; - /** - * router url - * @var string - */ - private $url = ''; - - /** - * inititalize this class - * - * @param string $url - */ - public function __construct ($url = 'http://speedport.ip/') { - $this->url = $url; - $this->checkRequirements(); - } - /** * check php requirements */ - private function checkRequirements () { + protected function checkRequirements () { if (!extension_loaded('curl')) { throw new Exception("The PHP Extension 'curl' is missing."); } @@ -71,37 +57,17 @@ class SpeedportHybrid { } /** - * get the values from array + * sends the encrypted request to router * - * @param array $array + * @param string $path + * @param mixed $fields + * @param string $cookie * @return array */ - private function getValues($array) { - $data = array(); - foreach ($array as $item) { - if (!isset($item['vartype']) || !isset($item['varid']) || !isset($item['varvalue'])) continue; - - // thank you telekom for this piece of shit - if ($item['vartype'] == 'template') { - if (is_array($item['varvalue'])) { - $data[$item['varid']][] = $this->getValues($item['varvalue']); - } - else { - // i dont know if we need this - $data[$item['varid']] = $item['varvalue']; - } - } - else { - if (is_array($item['varvalue'])) { - $data[$item['varid']] = $this->getValues($item['varvalue']); - } - else { - $data[$item['varid']] = $item['varvalue']; - } - } - } - - return $data; + protected function sentEncryptedRequest ($path, $fields, $cookie = false) { + $count = count($fields); + $fields = $this->encrypt(http_build_query($fields)); + return $this->sentRequest($path, $fields, $cookie, $count); } /** @@ -113,41 +79,10 @@ class SpeedportHybrid { * @param integer $count * @return array */ - private function sentRequest ($path, $fields, $cookie = false, $count = 0) { - $url = $this->url.$path.'?lang=en'; - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $url); - - if (!empty($fields)) { - if (is_array($fields)) { - curl_setopt($ch, CURLOPT_POST, count($fields)); - curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($fields)); - } - else { - curl_setopt($ch, CURLOPT_POST, $count); - curl_setopt($ch, CURLOPT_POSTFIELDS, $fields); - } - } - - if ($cookie === true) { - curl_setopt($ch, CURLOPT_COOKIE, 'challengev='.$this->challenge.'; '.$this->cookie); - } - - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - curl_setopt($ch, CURLOPT_HEADER, true); - - $result = curl_exec($ch); - - $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE); - $header = substr($result, 0, $header_size); - $body = substr($result, $header_size); - curl_close($ch); - - // check if response is empty - if (empty($body)) { - throw new RouterException('empty response'); - } - + protected function sentRequest ($path, $fields, $cookie = false, $count = 0) { + $data = parent::sentRequest($path, $fields, $cookie, $count); + $header = $data['header']; + $body = $data['body']; // check if body is encrypted (hex instead of json) if (ctype_xdigit($body)) { $body = $this->decrypt($body); @@ -160,7 +95,7 @@ class SpeedportHybrid { $body = preg_replace("/},\s+]/", "}\n]", $body); // decode json - if (strpos($url, '.json') !== false) { + if (strpos($path, '.json') !== false) { $json = json_decode($body, true); if (is_array($json)) { @@ -168,30 +103,6 @@ class SpeedportHybrid { } } - return array('header' => $this->parse_headers($header), 'body' => $body); - } - - /** - * parse the curl return header into an array - * - * @param string $response - * @return array - */ - private function parse_headers($response) { - $headers = array(); - $header_text = substr($response, 0, strpos($response, "\r\n\r\n")); - - $header_text = explode("\r\n", $header_text); - foreach ($header_text as $i => $line) { - if ($i === 0) { - $headers['http_code'] = $line; - } - else { - list ($key, $value) = explode(': ', $line); - $headers[$key] = $value; - } - } - - return $headers; + return array('header' => $header, 'body' => $body); } } diff --git a/Speedportw724v.class.php b/Speedportw724v.class.php index 2f7a37a..85557f7 100644 --- a/Speedportw724v.class.php +++ b/Speedportw724v.class.php @@ -1,4 +1,6 @@ * @copyright 2015 Jan Altensen (Stricted) */ -class Speedportw724v extends SpeedportHybrid { +class Speedportw724v extends SpeedportHybrid implements ISpeedport { public function login ($password) { /* this is experimental, i dont have a speedport w724v so i cant test this * feel free to test it and report if it dosent work @@ -18,11 +20,48 @@ class Speedportw724v extends SpeedportHybrid { $json = $this->getValues($data['body']); if (isset($json['login']) && $json['login'] == 'success') { - $this->cookie = $data['header']['Set-Cookie']; + if (isset($data['header']['Set-Cookie']) && !empty($data['header']['Set-Cookie'])) { + $this->cookie = $data['header']['Set-Cookie']; + } + else { + throw new RouterException('unable to get the session cookie from the router'); + } return true; } return false; } + + /** + * sends the request to router + * + * @param string $path + * @param mixed $fields + * @param string $cookie + * @param integer $count + * @return array + */ + protected function sentRequest ($path, $fields, $cookie = false, $count = 0) { + $data = parent::sentRequest($path, $fields, $cookie, $count); + $header = $data['header']; + $body = $data['body']; + + // fix invalid json + $body = preg_replace("/(\r\n)|(\r)/", "\n", $body); + $body = preg_replace('/\'/i', '"', $body); + $body = preg_replace("/\[\s+\]/i", '[ {} ]', $body); + $body = preg_replace("/},\s+]/", "}\n]", $body); + + // decode json + if (strpos($path, '.json') !== false) { + $json = json_decode($body, true); + + if (is_array($json)) { + $body = $json; + } + } + + return array('header' => $header, 'body' => $body); + } } diff --git a/lib/trait/CryptLib.class.php b/lib/trait/CryptLib.class.php index ce32bb7..71778b4 100644 --- a/lib/trait/CryptLib.class.php +++ b/lib/trait/CryptLib.class.php @@ -5,20 +5,6 @@ * @copyright 2015 Jan Altensen (Stricted) */ trait CryptLib { - /** - * sends the encrypted request to router - * - * @param string $path - * @param mixed $fields - * @param string $cookie - * @return array - */ - private function sentEncryptedRequest ($path, $fields, $cookie = false) { - $count = count($fields); - $fields = $this->encrypt(http_build_query($fields)); - return $this->sentRequest($path, $fields, $cookie, $count); - } - /** * decrypt data from router * diff --git a/lib/trait/Login.class.php b/lib/trait/Login.class.php index d03b94a..b33947c 100644 --- a/lib/trait/Login.class.php +++ b/lib/trait/Login.class.php @@ -11,24 +11,6 @@ trait Login { */ private $challenge = ''; - /** - * csrf_token - * @var string - */ - private $token = ''; - - /** - * hashed password - * @var string - */ - private $hash = ''; - - /** - * session cookie - * @var string - */ - private $cookie = ''; - /** * derivedk cookie * @var string @@ -51,7 +33,8 @@ trait Login { $json = $this->getValues($data['body']); if (isset($json['login']) && $json['login'] == 'success') { - $this->cookie = $this->getCookie($data); + $this->cookie = 'challengev='.$this->challenge.'; '; + $this->cookie .= $this->getCookie($data); $this->derivedk = $this->getDerviedk($password); @@ -74,7 +57,7 @@ trait Login { $fields = array('csrf_token' => 'nulltoken', 'showpw' => 0, 'challengev' => 'null'); $data = $this->sentRequest($path, $fields); $data = $this->getValues($data['body']); - + print_r($data); if (isset($data['challengev']) && !empty($data['challengev'])) { return $data['challengev']; } @@ -145,7 +128,7 @@ trait Login { * * @return string */ - private function getToken () { + protected function getToken () { $this->checkLogin(); $path = 'html/content/overview/index.html'; -- 2.20.1