bosha/ptel

PHP telnet with negotiation support

dev-master 2015-03-18 12:02 UTC

This package is not auto-updated.

Last update: 2024-04-27 15:09:47 UTC


README

Yet another implementation of Telnet protocol written using PHP. This class created && used for my daily use cases, so it can contains bugs. If you found them - open issue, or feel free to contact with me.

Installation

Composer

Inside your root folder with project run following command:

composer require "bosha/ptel": "dev-master"

Or manually add to your composer.json:

"require": {
    "bosha/ptel": "dev-master"
}

And use it:

<?php

require_once(__DIR__."/../vendor/autoload.php");

$telnet = new PTel\PTel();

Manually

Navigate to location of your project, and run following commands:

git clone https://github.com/bosha/PTel.git
mv PTel PTel_orig
mv PTel_orig/src/PTel PTel
rm -rf PTel_orig

Add to your code:

<?php

require_once("PTel/PTel.php");
require_once("PTel/SocketClientException.php");
require_once("PTel/TelnetException.php");

$telnet = new PTel();

After that - you can create new instance of class, and use it.

Using PTel

Using

After creating new instance, you need to connect to device and login:

try {
  $telnet = new PTel();
  $telnet->connect("mysupercisco.hostname.com");
  $telnet->login("bosha", "mysupersecurepassword");
} catch (Exception $e) { print_r($e); }

After successful login - you can do basic stuff like send and receive information from device:

$telnet->send("show version");
echo $telnet->recvAll();

Also some additional commands can be useful:

// Getting output of command:
$cisco_log = $telnet->getOutputOf("show logging");

// Searching for something in output stream to make application logic:
$telnet->send("copy running start");
if ($telnet->find("OK")) {
  echo "Configuration successful saved!"
}

// Some basic "expect" logic:
try {
  $telnet->send("enable");
  $telnet->expect('(P|p)ass((W|w)ord|)(:|)', "enablesecretpassword"); // Regular expressions supported
  if ($telnet->find("#")) {
    echo "Enable successful!"
  } else {
    echo "Looks like enable password are wrong!"
  }
} catch (Exception $e) {
    throw new BadPasswordException('Enable failed!');
}

// If you know that command execution can take a long - you can wait for some output from socket:
try {
  $telnet->send("copy running start");
  $telnet->waitReply(10); // Will not wait longer than 10 seconds
} catch (Exception $e) { print_r($e); }
// Or wait for some text. For example - prompt:
try {
  $telnet->send("copy running start");
  $telnet->waitFor($telnet->prompt); // $prompt - public variable with prompt
} catch (Exception $e) { print_r($e); }

Usually, prompt will be automatically cutted from device output after successful login. Current prompt can be returned and changes if required:

if ($telnet->getPrompt() !== ">#") {
  $telnet->setPrompt(">#");
}

Prompt is using to determine command execution end, so if you will use commands like getOutputOf - you need to be sure that prompt is properly configured.

Some additional telnet negotiation options can be also specified:

// Terminal speed
$telnet->setTermSpeed(38000, 38000);

// Terminal type
$telnet->setTerm("xterm);

If device using some unusual page delimiters - they can be specified by changing $page_delimiter variable. New line character (carriage return) can be also changed by changing $retcarriage variable.

Extending

PTel can be easily extended if you need some functionality which not implemented, or for rewriting exists methods to suits your needs:

class Cisco_Telnet extends PTel
{

  public function login($user, $pass, $timeout = 10) {
    try {
      $this->expect('CustomUserNameRequest:', $user);
      $this->expect('CustomPasswordRequest:', $pass);
    } catch (Exception $e) {
      throw new Exception('Could not find password request. Login failed.');
    }

    $timestart = time();
    $buff = '';
    while (true) {
      $buff = $this->recvLine();
      $timerun = time() - $timestart;

      if (preg_match("/wrong!)/i", $buff)) {
        throw new Exception("Username or password wrong! Login failed");
      }

      if (preg_match("/]>>>/", $buff)) {
        break;
      }

      if ($timerun >= $maxtimeout) {
        throw new Exception("Could not get reply from device. Login failed.");
      }
    }

    $lines = explode("\n", $this->getBuffer());
    $prompt = array_slice($lines, -1);
    $this->prompt = $prompt[0];
    return true;
  }
  
  public function enable($enpass) {
    try {
      $this->send("enable");
      $this->expect('EnablePasswordRequest:', "enablesecretpassword");
      if ($telnet->find("#")) {
        $lines = explode("\n", $this->getBuffer());
        $prompt = array_slice($lines, -1);
        $this->prompt = $prompt[0] 
      } else {
        throw new Exception("Login fail [ bad password ] !");
      }
    } catch (Exception $e) {
      throw new BadPasswordException('Enable failed!');
    }
  }

}