Advertisement
Guest User

Untitled

a guest
Jun 23rd, 2014
580
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 9.66 KB | None | 0 0
  1. <?php
  2. /**
  3.  * Telnet class
  4.  *
  5.  * Used to execute remote commands via telnet connection
  6.  * Usess sockets functions and fgetc() to process result
  7.  *
  8.  * All methods throw Exceptions on error
  9.  *
  10.  * Written by Dalibor Andzakovic <dali@swerve.co.nz>
  11.  * Based on the code originally written by Marc Ennaji and extended by
  12.  * Matthias Blaser <mb@adfinis.ch>
  13.  *
  14.  * Extended by Christian Hammers <chammers@netcologne.de>
  15.  *
  16.  */
  17. class Telnet
  18. {
  19.  
  20.     private $host;
  21.     private $port;
  22.     private $timeout;
  23.  
  24.     private $socket = NULL;
  25.     private $buffer = NULL;
  26.     private $prompt;
  27.     private $errno;
  28.     private $errstr;
  29.  
  30.     private $NULL;
  31.     private $DC1;
  32.     private $WILL;
  33.     private $WONT;
  34.     private $DO;
  35.     private $DONT;
  36.     private $IAC;
  37.  
  38.     private $global_buffer = '';
  39.  
  40.     const TELNET_ERROR = FALSE;
  41.     const TELNET_OK = TRUE;
  42.  
  43.     /**
  44.      * Constructor. Initialises host, port and timeout parameters
  45.      * defaults to localhost port 23 (standard telnet port)
  46.      *
  47.      * @param string $host Host name or IP addres
  48.      * @param int $port TCP port number
  49.      * @param int $timeout Connection timeout in seconds
  50.      * @return void
  51.      */
  52.     public function __construct($host = '192.168.0.2', $port = '23', $timeout = 10, $prompt = '#')
  53.     {
  54.  
  55.         $this->host = $host;
  56.         $this->port = $port;
  57.         $this->timeout = $timeout;
  58.         $this->prompt = $prompt;
  59.  
  60.         // set some telnet special characters
  61.         $this->NULL = chr(0);
  62.         $this->DC1 = chr(17);
  63.         $this->WILL = chr(251);
  64.         $this->WONT = chr(252);
  65.         $this->DO = chr(253);
  66.         //$this->DONT = chr(32);
  67.         $this->DONT = chr(254);
  68.         $this->IAC = chr(255);
  69.         $this->RQMORE = chr(63);
  70.         $this->SPACE = chr(32);
  71.  
  72.         $this->connect();
  73.  
  74.     }
  75.  
  76.     /**
  77.      * Destructor. Cleans up socket connection and command buffer
  78.      *
  79.      * @return void
  80.      */
  81.     public function __destruct()
  82.     {
  83.  
  84.         // cleanup resources
  85.         $this->disconnect();
  86.         $this->buffer = NULL;
  87.         $this->global_buffer = NULL;
  88.     }
  89.  
  90.     /**
  91.      * Attempts connection to remote host. Returns TRUE if sucessful.
  92.      *
  93.      * @return boolean
  94.      */
  95.     public function connect()
  96.     {
  97.  
  98.         // check if we need to convert host to IP
  99.         if (!preg_match('/([0-9]{1,3}\\.){3,3}[0-9]{1,3}/', $this->host)) {
  100.  
  101.             $ip = gethostbyname($this->host);
  102.  
  103.             if ($this->host == $ip) {
  104.  
  105.                 throw new Exception("Cannot resolve $this->host");
  106.  
  107.             } else {
  108.                 $this->host = $ip;
  109.             }
  110.         }
  111.  
  112.         // attempt connection
  113.         $this->socket = fsockopen($this->host, $this->port, $this->errno, $this->errstr, $this->timeout);
  114.  
  115.         if (!$this->socket) {
  116.             throw new Exception("Cannot connect to $this->host on port $this->port");
  117.         }
  118.  
  119.         $this->waitPrompt();
  120.  
  121.         return self::TELNET_OK;
  122.     }
  123.  
  124.     /**
  125.      * Closes IP socket
  126.      *
  127.      * @return boolean
  128.      */
  129.     public function disconnect()
  130.     {
  131.         if ($this->socket) {
  132.             if (!fclose($this->socket)) {
  133.                 throw new Exception("Error while closing telnet socket");
  134.             }
  135.             $this->socket = NULL;
  136.         }
  137.         return self::TELNET_OK;
  138.     }
  139.  
  140.     /**
  141.      * Executes command and returns a string with result.
  142.      * This method is a wrapper for lower level private methods
  143.      *
  144.      * @param string $command Command to execute
  145.      * @return string Command result
  146.      */
  147.     public function exec($command)
  148.     {
  149.         $this->write($command);
  150.         $this->waitPrompt($command);
  151.         return $this->getBuffer();
  152.     }
  153.  
  154.     /**
  155.      * Attempts login to remote host.
  156.      * This method is a wrapper for lower level private methods and should be
  157.      * modified to reflect telnet implementation details like login/password
  158.      * and line prompts. Defaults to standard unix non-root prompts
  159.      *
  160.      * @param string $username Username
  161.      * @param string $password Password
  162.      * @return boolean
  163.      */
  164.     public function login($username, $password)
  165.     {
  166.  
  167.         try {
  168.             $this->setPrompt('Username:');
  169.             $this->waitPrompt();
  170.             $this->write($username);
  171.             $this->setPrompt('Password:');
  172.             $this->waitPrompt();
  173.             $this->write($password);
  174.             $this->setPrompt();
  175.             $this->waitPrompt();
  176.         } catch (Exception $e) {
  177.  
  178.             throw new Exception("Login failed.");
  179.         }
  180.  
  181.         return self::TELNET_OK;
  182.     }
  183.  
  184.     /**
  185.      * Sets the string of characters to respond to.
  186.      * This should be set to the last character of the command line prompt
  187.      *
  188.      * @param string $s String to respond to
  189.      * @return boolean
  190.      */
  191.     public function setPrompt($s = '>')
  192.     {
  193.         $this->prompt = $s;
  194.         return self::TELNET_OK;
  195.     }
  196.  
  197.     /**
  198.      * Gets character from the socket
  199.      *
  200.      * @return void
  201.      */
  202.     protected function getc()
  203.     {
  204.         $c = fgetc($this->socket);
  205.         $this->global_buffer .= $c;
  206.         return $c;
  207.     }
  208.  
  209.     /**
  210.      * Clears internal command buffer
  211.      *
  212.      * @return void
  213.      */
  214.     public function clearBuffer()
  215.     {
  216.         $this->buffer = '';
  217.     }
  218.  
  219.     /**
  220.      * Reads characters from the socket and adds them to command buffer.
  221.      * Handles telnet control characters. Stops when prompt is ecountered.
  222.      *
  223.      * @param string $prompt
  224.      * @return boolean
  225.      */
  226.     protected function readTo($prompt, $command = false)
  227.     {
  228.         $log_add = false;
  229.  
  230.         if (!$this->socket) {
  231.             throw new Exception("Telnet connection closed");
  232.         }
  233.  
  234.         // clear the buffer
  235.         $this->clearBuffer();
  236.  
  237.         $until_t = time() + $this->timeout;
  238.         do {
  239.             // time's up (loop can be exited at end or through continue!)
  240.             if (time() > $until_t) {
  241.                 throw new Exception("Couldn't find the requested : '$prompt' within {$this->timeout} seconds");
  242.             }
  243.  
  244.             $c = $this->getc();
  245.  
  246.             if ($c === false) {
  247.                 throw new Exception("Couldn't find the requested : '" . $prompt . "', it was not in the data returned from server: " . $this->buffer);
  248.             }
  249.  
  250.             if (substr($this->buffer, strlen($this->buffer) - strlen('--More--')) == '--More--') {
  251.                 fwrite($this->socket, $this->SPACE);
  252.                 $this->buffer = substr($this->buffer, 0, - strlen('--More--'));
  253.             }
  254.  
  255.             // Interpreted As Command
  256.             if ($c == $this->IAC) {
  257.                 if ($this->negotiateTelnetOptions()) {
  258.                     continue;
  259.                 }
  260.             }
  261.  
  262.             // append current char to global buffer
  263.             if ($c !== chr(8)) {
  264.                 $this->buffer .= $c;
  265.             }
  266.  
  267.             // we've encountered the prompt. Break out of the loop
  268.             if ((substr($this->buffer, strlen($this->buffer) - strlen($prompt))) == $prompt) {
  269.                 return self::TELNET_OK;
  270.             }
  271.  
  272.         } while ($c != $this->NULL || $c != $this->DC1);
  273.     }
  274.  
  275.     /**
  276.      * Write command to a socket
  277.      *
  278.      * @param string $buffer Stuff to write to socket
  279.      * @param boolean $addNewLine Default true, adds newline to the command
  280.      * @return boolean
  281.      */
  282.     protected function write($buffer, $addNewLine = true)
  283.     {
  284.  
  285.         if (!$this->socket) {
  286.             throw new Exception("Telnet connection closed");
  287.         }
  288.  
  289.         // clear buffer from last command
  290.         $this->clearBuffer();
  291.  
  292.         if ($addNewLine == true) {
  293.             $buffer .= "\n";
  294.         }
  295.  
  296.         $this->global_buffer .= $buffer;
  297.         if (!fwrite($this->socket, $buffer) < 0) {
  298.             throw new Exception("Error writing to socket");
  299.         }
  300.  
  301.         return self::TELNET_OK;
  302.     }
  303.  
  304.     /**
  305.      * Returns the content of the command buffer
  306.      *
  307.      * @return string Content of the command buffer
  308.      */
  309.     protected function getBuffer()
  310.     {
  311.         // cut last line (is always prompt)
  312.         $buf = explode("\n", $this->buffer);
  313.         unset($buf[count($buf) - 1]);
  314.         $buf = implode("\n", $buf);
  315.         return trim($buf);
  316.     }
  317.  
  318.     /**
  319.      * Returns the content of the global command buffer
  320.      *
  321.      * @return string Content of the global command buffer
  322.      */
  323.     public function getGlobalBuffer()
  324.     {
  325.         return $this->global_buffer;
  326.     }
  327.  
  328.     /**
  329.      * Telnet control character magic
  330.      *
  331.      * @param string $command Character to check
  332.      * @return boolean
  333.      */
  334.     protected function negotiateTelnetOptions()
  335.     {
  336.  
  337.         $c = $this->getc();
  338.  
  339.         if ($c != $this->IAC) {
  340.             if (false) {
  341.                 fwrite($this->socket, $this->SPACE);
  342.             } else if (($c == $this->DO) || ($c == $this->DONT)) {
  343.  
  344.                 $opt = $this->getc();
  345.                 fwrite($this->socket, $this->IAC . $this->WONT . $opt);
  346.             } else if (($c == $this->WILL) || ($c == $this->WONT)) {
  347.  
  348.                 $opt = $this->getc();
  349.                 fwrite($this->socket, $this->IAC . $this->DONT . $opt);
  350.             } else {
  351.                 throw new Exception('Error: unknown control character ' . ord($c));
  352.             }
  353.         } else {
  354.             throw new Exception('Error: Something Wicked Happened');
  355.         }
  356.  
  357.         return self::TELNET_OK;
  358.     }
  359.  
  360.     /**
  361.      * Reads socket until prompt is encountered
  362.      */
  363.     protected function waitPrompt($command = false)
  364.     {
  365.         return $this->readTo($this->prompt, $command);
  366.     }
  367.  
  368. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement