Advertisement
Guest User

Untitled

a guest
May 25th, 2018
329
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 17.83 KB | None | 0 0
  1. <?php
  2. /**
  3. * rConfig Connection class
  4. *
  5. * Class for managing connections via telnet and SSH to devices
  6. * This class is heavily modified from the 'Telnet for PHP' class from Ray Soucy <rps@soucy.org>
  7. * see http://www.soucy.org/ for original file
  8. *
  9. *
  10. * @package rConfigConnectionClass
  11. * @originalauthor Ray Soucy <rps@soucy.org>
  12. * @modifiedauthor Stephen Stack <www.rconfig.com>
  13. * @version 2.0
  14. * @link http://www.rconfig.com/
  15. */
  16.  
  17. class Connection {
  18.  
  19. private $_hostname;
  20. private $_username;
  21. private $_password;
  22. private $_connection;
  23. private $_port;
  24. private $_data;
  25. private $_timeout;
  26. private $_prompt;
  27.  
  28. const TELNET_OK = TRUE;
  29.  
  30. /**
  31. * Class Constructor
  32. * @param string $hostname Hostname or IP address of the device
  33. * @param string $username Username used to connect
  34. * @param string $password Password used to connect
  35. * @param string $enableModeOn Enable Mode On/Off as set in database
  36. * @param string $enablePassword Enable Mode password
  37. * @param integer $connPort port to be used when connecting to the device
  38. * @param integer $timeout Connection timeout (seconds)
  39. * @return object Telnet object
  40. */
  41. public function __construct($hostname, $username = "", $password,
  42. $enableModePassword, $connPort, $timeout = 60,
  43. $userPrmpt, $passPrmpt, $enable,
  44. $enableCmd, $enablePrompt, $enablePassPrmpt, $prompt,
  45. $linebreak, $paging, $pagingCmd, $pagerPrompt, $pagerPromptCmd, $resetPagingCmd,
  46. $hpAnyKeyStatus, $hpAnyKeyPrmpt) {
  47. $this->_hostname = $hostname;
  48. $this->_username = $username;
  49. $this->_password = $password;
  50. $this->_timeout = $timeout;
  51. $this->_enableModePassword = $enableModePassword;
  52. $this->_port = $connPort;
  53. $this->_userPrmpt = $userPrmpt;
  54. $this->_passPrmpt = $passPrmpt;
  55. $this->_enable = $enable;
  56. $this->_enableCmd = $enableCmd;
  57. $this->_enablePrompt = $enablePrompt;
  58. $this->_enablePassPrmpt = $enablePassPrmpt;
  59. $this->_prompt = $prompt;
  60. $this->_linebreak = $linebreak;
  61. $this->_paging = $paging;
  62. $this->_pagingCmd = $pagingCmd;
  63. $this->_pagerPrompt = $pagerPrompt;
  64. $this->_pagerPromptCmd = $pagerPromptCmd;
  65. $this->_resetPagingCmd = $resetPagingCmd;
  66. $this->_hpAnyKeyStatus = $hpAnyKeyStatus;
  67. $this->_hpAnyKeyPrmpt = $hpAnyKeyPrmpt;
  68. $this->_use_usleep = 0; // change to 1 for faster execution
  69. // don't change to 1 on Windows servers unless you have PHP 5
  70. $this->_sleeptime = 125000;
  71.  
  72. // below are headers that telnet requires for proper session setup - google 'fsockopen php telnet' for more info
  73. // and per here http://www.phpfreaks.com/forums/index.php?topic=201740.0
  74. // Not currenty used in this version of the class
  75. // $this->_header1 = chr(0xFF) . chr(0xFB) . chr(0x1F) . chr(0xFF) . chr(0xFB) . chr(0x20) . chr(0xFF) . chr(0xFB) . chr(0x18) . chr(0xFF) . chr(0xFB) . chr(0x27) . chr(0xFF) . chr(0xFD) . chr(0x01) . chr(0xFF) . chr(0xFB) . chr(0x03) . chr(0xFF) . chr(0xFD) . chr(0x03) . chr(0xFF) . chr(0xFC) . chr(0x23) . chr(0xFF) . chr(0xFC) . chr(0x24) . chr(0xFF) . chr(0xFA) . chr(0x1F) . chr(0x00) . chr(0x50) . chr(0x00) . chr(0x18) . chr(0xFF) . chr(0xF0) . chr(0xFF) . chr(0xFA) . chr(0x20) . chr(0x00) . chr(0x33) . chr(0x38) . chr(0x34) . chr(0x30) . chr(0x30) . chr(0x2C) . chr(0x33) . chr(0x38) . chr(0x34) . chr(0x30) . chr(0x30) . chr(0xFF) . chr(0xF0) . chr(0xFF) . chr(0xFA) . chr(0x27) . chr(0x00) . chr(0xFF) . chr(0xF0) . chr(0xFF) . chr(0xFA) . chr(0x18) . chr(0x00) . chr(0x58) . chr(0x54) . chr(0x45) . chr(0x52) . chr(0x4D) . chr(0xFF) . chr(0xF0);
  76. // $this->_header2 = chr(0xFF) . chr(0xFC) . chr(0x01) . chr(0xFF) . chr(0xFC) . chr(0x22) . chr(0xFF) . chr(0xFE) . chr(0x05) . chr(0xFF) . chr(0xFC) . chr(0x21);
  77. }
  78.  
  79. /**
  80. * Establish a connection to an IOS based device check for enable mode also and enter enable cmds if needed
  81. */
  82. public function connectTelnet() {
  83.  
  84. $log = ADLog::getInstance();
  85.  
  86. // Ensure port is set to a valid number. If not, use default
  87. if ($this->_port == null || $this->_port <= 0 || $this->_port > 65535) {
  88. $this->_port = 23;
  89. }
  90.  
  91. $this->_connection = fsockopen($this->_hostname, $this->_port, $errno, $errstr, $this->_timeout);
  92.  
  93. if ($this->_connection === false) {
  94.  
  95. $log->Conn("Failure: Unable to connect to " . $this->_hostname . " on port " . $this->_port . " - fsockopen Error:$errstr ($errno) (File: " . $_SERVER['PHP_SELF'] . ")");
  96. return false;
  97. }
  98. stream_set_timeout($this->_connection, $this->_timeout);
  99.  
  100. if ($this->_userPrmpt == true) { // lowercase username for Cisco ACS5 implementations
  101. $this->_send($this->_username);
  102. $this->_readTo($this->_userPrmpt);
  103. }
  104. $this->_send($this->_password);
  105.  
  106. if ($this->_enable == 'on') {
  107. $this->_readTo($this->_enablePrompt);
  108. if (strpos($this->_data, $this->_enablePrompt) === false) {
  109. fclose($this->_connection);
  110. $log->Conn("Error: Authentication Failed for $this->_hostname (File: " . $_SERVER['PHP_SELF'] . ")");
  111. return false;
  112. } else {
  113. $this->_send($this->_enableCmd);
  114. $this->_readTo($this->_enablePassPrmpt);
  115. $this->_send($this->_enableModePassword);
  116. $this->_readTo($this->_prompt);
  117. if (strpos($this->_data, $this->_prompt) == false) {
  118. $log->Conn("Error: Authentication Failed for enable mode for enable mode for or $this->_hostname (File: " . $_SERVER['PHP_SELF'] . ")");
  119. return false;
  120. }
  121. }
  122. } else {
  123. if (strpos($this->_data, $this->_prompt) === false) {
  124. fclose($this->_connection);
  125. echo "Error: Authentication Failed for $this->_hostname\n";
  126. $log->Conn("Error: Authentication Failed for $this->_hostname (File: " . $_SERVER['PHP_SELF'] . ")");
  127. return false;
  128. }
  129. }
  130. $this->_send($this->_pagingCmd);
  131. $this->_readTo($this->_prompt);
  132. }
  133.  
  134. /**
  135. * Telnet Show Command Input
  136. * @param string $cmd The command to execute
  137. * @param string $prompt The device exec mode prompt
  138. * @return array|boolean On success returns an array, false on failure.
  139. */
  140. public function showCmdTelnet($cmd, $cliDebugOutput = false) {
  141. $this->_send($cmd);
  142. if($this->_readTo($this->_prompt, $cliDebugOutput) == true){
  143. // $this->_readTo($this->_prompt, $cliDebugOutput);
  144. $result = array();
  145. $this->_data = explode("\r\n", $this->_data);
  146. array_shift($this->_data);
  147. array_pop($this->_data);
  148. if (count($this->_data) > 0) {
  149. foreach ($this->_data as $line) {
  150. $line = explode("\r\n", $line);
  151. array_push($result, $line[0]);
  152. }
  153. }
  154. $this->_data = $result;
  155. return $this->_data;
  156. }
  157. }
  158. /**
  159. * Read from socket until $prompt
  160. * @param string $prompt Single character or string
  161. */
  162. private function _readTo($prompt, $cliDebugOutput = false) {
  163. $log = ADLog::getInstance();
  164. if (!$this->_connection) {
  165. throw new Exception("Telnet connection closed");
  166. }
  167. // clear the buffer
  168. // $this->_clearBuffer();
  169. while (($c = fgetc($this->_connection)) !== false) {
  170. // @ to supress array to string conversion error
  171. @$this->_data .= $c;
  172. if ($cliDebugOutput == true) {
  173. echo $c;
  174. }
  175. // muchos advanced debugging - uncomment next line to enable
  176. if ((substr($this->_data, strlen($this->_data) - strlen($prompt))) == $prompt) {
  177. // var_dump($this->_data);
  178. // return true if we encounter prompt from buffer text
  179. return true;
  180. }
  181.  
  182. // Remove --More-- and backspace and whitespace from output so that it does not copy to text files
  183. $this->_data = str_replace($this->_pagerPrompt, "", $this->_data);
  184. $this->_data = str_replace(chr(8), "", $this->_data);
  185. $this->_data = str_replace(' ', "", $this->_data);
  186. // Set $_data as false if previous command failed.
  187. if (strpos($this->_data, '% Invalid input detected') !== false) {
  188. $this->_data = false;
  189. }
  190. } // while
  191. }
  192.  
  193. /**
  194. * Issue a command to the device
  195. */
  196. private function _send($command) {
  197. fputs($this->_connection, $command . "\r\n");
  198. }
  199.  
  200. /**
  201. * Telnet Do Command Input
  202. * @param string $cmd The command to execute
  203. * @param string $result to send back for output
  204. * @return read data from connection
  205. */
  206. public function writeSnippetTelnet($c, &$r) {
  207. if ($this->_connection) {
  208. fputs($this->_connection, "$c\r");
  209. $this->_sleep();
  210. $this->_getResponse($r);
  211. $r = preg_replace("/^.*?\n(.*)\n[^\n]*$/", "$1", $r);
  212. }
  213. return $this->_connection ? 1 : 0;
  214. }
  215. private function _getResponse(&$r) {
  216. $r = '';
  217. do {
  218. $r.=fread($this->_connection, 1000);
  219. $s = socket_get_status($this->_connection);
  220. } while ($s['unread_bytes']);
  221. }
  222. private function _sleep() {
  223. if ($this->_use_usleep){
  224. usleep($this->_sleeptime);
  225. } else {
  226. sleep(1);
  227. }
  228. }
  229. /**
  230. *
  231. * Close an active telnet connection and reset the term len if set
  232. */
  233. public function closeTelnet($resetPagingCmd, $saveConfig, $exitCmd) {
  234.  
  235. if ($this->_connection) {
  236. if(!empty($resetPagingCmd)){
  237. $this->_send($resetPagingCmd);
  238.  
  239. }
  240. if(!empty($saveConfig)){
  241. $this->_send($saveConfig);
  242. }
  243. if(!empty($exitCmd)){
  244. $this->_send($exitCmd);
  245. }
  246. fclose($this->_connection);
  247. } else {
  248. echo "Telnet connection already closed";
  249. throw new Exception("Telnet connection closed");
  250. }
  251. }
  252.  
  253. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  254. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  255. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  256.  
  257. /**
  258. * Establish a connection to an IOS based device on SSHv2 check for enable mode also and enter enable cmds if needed
  259. */
  260. public function connectSSH($command, $prompt, $debugOnOff = 0) {
  261.  
  262. $log = ADLog::getInstance();
  263. // debugging check - real time output on CLI
  264. if ($debugOnOff === '1' || isset($cliDebugOutput)) {
  265. define('NET_SSH2_LOGGING', NET_SSH2_LOG_REALTIME);
  266. }
  267.  
  268. // Ensure port is set to a valid number. If not, use default
  269. if ($this->_port == null || $this->_port <= 0 || $this->_port > 65535) {
  270. $this->_port = 22;
  271. }
  272. if (!$ssh = new Net_SSH2($this->_hostname, $this->_port, $this->_timeout)) {
  273. echo "Failure: Unable to connect to " . $this->_hostname . " on port " . $this->_port . "\n";
  274. $log->Conn("Failure: Unable to connect to " . $this->_hostname . " on port " . $this->_port . " - (File: " . $_SERVER['PHP_SELF'] . ")");
  275. $ssh->disconnect();
  276. return false;
  277. }
  278.  
  279. if (!$ssh->login($this->_username, $this->_password)) {
  280. //
  281. echo "Error: Authentication Failed or unable to connect to " . $this->_hostname . "\n";
  282. $log->Conn("Error: Authentication Failed or unable to connect to " . $this->_hostname . " on port " . $this->_port . " - (File: " . $_SERVER['PHP_SELF'] . ")");
  283. $ssh->disconnect();
  284. return false;
  285. }
  286.  
  287. $output = '';
  288. if ($this->_enable === true) {
  289.  
  290. $ssh->write($this->_enableCmd . "\n");
  291. $ssh->read($this->_enablePassPrmpt);
  292. $ssh->write($this->_enableModePassword . "\n");
  293. $ssh->read($this->_prompt);
  294. if($this->_paging === true){
  295. $ssh->write($this->_pagingCmd . "\n");
  296. }
  297. $ssh->read($this->_prompt);
  298. if($this->_linebreak == 'n'){$ssh->write($command . "\n");}
  299. if($this->_linebreak == 'r'){$ssh->write($command . "\r");}
  300. $output = $ssh->read($this->_prompt);
  301. $ssh->write("\n"); // to line break after command output
  302. $ssh->read($this->_prompt);
  303. } else {
  304. /* for HP devices, may add this to template in future if moe like it */
  305.  
  306. if($this->_hpAnyKeyStatus === true){
  307. $ssh->read($this->_hpAnyKeyPrmpt);
  308. $ssh->write("\n");
  309. }
  310. $ssh->read($this->_prompt);
  311.  
  312.  
  313. if($this->_paging === true){
  314. $ssh->write($this->_pagingCmd . "\n");
  315. sleep(1);
  316. $ssh->read($this->_prompt);
  317. }
  318. if($this->_linebreak == 'n'){$ssh->write($command . "\n");}
  319. if($this->_linebreak == 'r'){$ssh->write($command . "\r");}
  320. $output = $ssh->read($this->_prompt);
  321. if($this->_linebreak == 'n'){$ssh->write("\n");}
  322. if($this->_linebreak == 'r'){$ssh->write("\r");}
  323. $ssh->read($this->_prompt);
  324. }
  325. // reset paging if paging is set
  326. if($this->_paging === true){
  327. if($this->_linebreak == 'n'){$ssh->write($this->_resetPagingCmd . "\n"); }
  328. if($this->_linebreak == 'r'){$ssh->write($this->_resetPagingCmd . "\n"); }
  329. sleep(1);
  330. $ssh->read($this->_prompt);
  331. }
  332. $ssh->disconnect();
  333. $result = array();
  334. $this->_data = explode("\r\n", $output);
  335. array_shift($this->_data);
  336. array_pop($this->_data);
  337. if (count($this->_data) > 0) {
  338. foreach ($this->_data as $line) {
  339. $line = explode("\r\n", $line); // changed from 3xSpaces to /r/n as a delimiter for explode
  340. array_push($result, $line[0]);
  341. } // foreach
  342. }
  343. $this->_data = $result;
  344. return $this->_data;
  345. }
  346.  
  347. /**
  348. * Write a config snippet to to a device using SSH
  349. */
  350. public function writeSnippetSSH($snippetArr, $prompt) {
  351.  
  352. $log = ADLog::getInstance();
  353.  
  354. if (!$ssh = new Net_SSH2($this->_hostname, 22, $this->_timeout)) {
  355. $output = "Failure: Unable to connect to $this->_hostname\n";
  356. $log->Conn("Failure: Unable to connect to " . $this->_hostname . " - (File: " . $_SERVER['PHP_SELF'] . ")");
  357. return false;
  358. }
  359.  
  360. if (!$ssh->login($this->_username, $this->_password)) {
  361. $output = "Error: Authentication Failed for $this->_hostname\n";
  362. $log->Conn("Error: Authentication Failed for $this->_hostname (File: " . $_SERVER['PHP_SELF'] . ")");
  363. return false;
  364. }
  365. $output = '';
  366. if ($this->_enable === true) {
  367. $ssh->write($this->_enableCmd . "\n");
  368. $ssh->read($this->_enablePassPrmpt);
  369. $ssh->write($this->_enableModePassword . "\n");
  370. $ssh->read($this->_prompt);
  371. if($this->_paging === true){
  372. $ssh->write($this->_pagingCmd . "\n");
  373. }
  374. $ssh->read($this->_prompt);
  375. foreach ($snippetArr as $key => $command) {
  376. if($this->_linebreak == 'n'){$ssh->write($command . "\n");}
  377. if($this->_linebreak == 'r'){$ssh->write($command . "\r");}
  378. }
  379. $output = $ssh->read($this->_prompt);
  380. $ssh->write("\n"); // to line break after command output
  381. $ssh->read($this->_prompt);
  382. } else {
  383. /* for HP devices, may add this to template in future if moe like it */
  384.  
  385. if($this->_hpAnyKeyStatus === true){
  386. $ssh->read($this->_hpAnyKeyPrmpt);
  387. $ssh->write("\n");
  388. }
  389. $ssh->read($this->_prompt);
  390. if($this->_paging === true){
  391. $ssh->write($this->_pagingCmd . "\n");
  392. sleep(1);
  393. $ssh->read($this->_prompt);
  394. }
  395. foreach ($snippetArr as $key => $command) {
  396. if($this->_linebreak == 'n'){$ssh->write($command . "\n");}
  397. if($this->_linebreak == 'r'){$ssh->write($command . "\r");}
  398. }
  399. $output = $ssh->read($this->_prompt);
  400. if($this->_linebreak == 'n'){$ssh->write("\n");}
  401. if($this->_linebreak == 'r'){$ssh->write("\r");}
  402. $ssh->read($this->_prompt);
  403. }
  404. // reset paging if paging is set
  405. if($this->_paging === true){
  406. if($this->_linebreak == 'n'){$ssh->write($this->_resetPagingCmd . "\n"); }
  407. if($this->_linebreak == 'r'){$ssh->write($this->_resetPagingCmd . "\n"); }
  408. sleep(1);
  409. $ssh->read($this->_prompt);
  410. }
  411. $ssh->disconnect();
  412. return $output;
  413. }
  414.  
  415.  
  416.  
  417.  
  418. /**
  419. * Clears internal command buffer
  420. *
  421. * @return void
  422. */
  423. private function _clearBuffer() {
  424. $this->_data = '';
  425. }
  426.  
  427. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement