minor bug fix
[openemr.git] / library / phpseclib / Net / SSH1.php
blob67e0965254f8fac1795aaf5fc0966f670242a264
1 <?php
2 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4 /**
5 * Pure-PHP implementation of SSHv1.
7 * PHP versions 4 and 5
9 * Here's a short example of how to use this library:
10 * <code>
11 * <?php
12 * include('Net/SSH1.php');
14 * $ssh = new Net_SSH1('www.domain.tld');
15 * if (!$ssh->login('username', 'password')) {
16 * exit('Login Failed');
17 * }
19 * echo $ssh->exec('ls -la');
20 * ?>
21 * </code>
23 * Here's another short example:
24 * <code>
25 * <?php
26 * include('Net/SSH1.php');
28 * $ssh = new Net_SSH1('www.domain.tld');
29 * if (!$ssh->login('username', 'password')) {
30 * exit('Login Failed');
31 * }
33 * echo $ssh->read('username@username:~$');
34 * $ssh->write("ls -la\n");
35 * echo $ssh->read('username@username:~$');
36 * ?>
37 * </code>
39 * More information on the SSHv1 specification can be found by reading
40 * {@link http://www.snailbook.com/docs/protocol-1.5.txt protocol-1.5.txt}.
42 * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
43 * of this software and associated documentation files (the "Software"), to deal
44 * in the Software without restriction, including without limitation the rights
45 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
46 * copies of the Software, and to permit persons to whom the Software is
47 * furnished to do so, subject to the following conditions:
49 * The above copyright notice and this permission notice shall be included in
50 * all copies or substantial portions of the Software.
52 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
53 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
54 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
55 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
56 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
57 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
58 * THE SOFTWARE.
60 * @category Net
61 * @package Net_SSH1
62 * @author Jim Wigginton <terrafrost@php.net>
63 * @copyright MMVII Jim Wigginton
64 * @license http://www.opensource.org/licenses/mit-license.html MIT License
65 * @version $Id: SSH1.php,v 1.15 2010/03/22 22:01:38 terrafrost Exp $
66 * @link http://phpseclib.sourceforge.net
69 /**
70 * Include Math_BigInteger
72 * Used to do RSA encryption.
74 if (!class_exists('Math_BigInteger')) {
75 require_once('Math/BigInteger.php');
78 /**
79 * Include Crypt_Null
81 //require_once('Crypt/Null.php');
83 /**
84 * Include Crypt_DES
86 if (!class_exists('Crypt_DES')) {
87 require_once('Crypt/DES.php');
90 /**
91 * Include Crypt_TripleDES
93 if (!class_exists('Crypt_TripleDES')) {
94 require_once('Crypt/TripleDES.php');
97 /**
98 * Include Crypt_RC4
100 if (!class_exists('Crypt_RC4')) {
101 require_once('Crypt/RC4.php');
105 * Include Crypt_Random
107 // the class_exists() will only be called if the crypt_random function hasn't been defined and
108 // will trigger a call to __autoload() if you're wanting to auto-load classes
109 // call function_exists() a second time to stop the require_once from being called outside
110 // of the auto loader
111 if (!function_exists('crypt_random') && !class_exists('Crypt_Random') && !function_exists('crypt_random')) {
112 require_once('Crypt/Random.php');
115 /**#@+
116 * Encryption Methods
118 * @see Net_SSH1::getSupportedCiphers()
119 * @access public
122 * No encryption
124 * Not supported.
126 define('NET_SSH1_CIPHER_NONE', 0);
128 * IDEA in CFB mode
130 * Not supported.
132 define('NET_SSH1_CIPHER_IDEA', 1);
134 * DES in CBC mode
136 define('NET_SSH1_CIPHER_DES', 2);
138 * Triple-DES in CBC mode
140 * All implementations are required to support this
142 define('NET_SSH1_CIPHER_3DES', 3);
144 * TRI's Simple Stream encryption CBC
146 * Not supported nor is it defined in the official SSH1 specs. OpenSSH, however, does define it (see cipher.h),
147 * although it doesn't use it (see cipher.c)
149 define('NET_SSH1_CIPHER_BROKEN_TSS', 4);
151 * RC4
153 * Not supported.
155 * @internal According to the SSH1 specs:
157 * "The first 16 bytes of the session key are used as the key for
158 * the server to client direction. The remaining 16 bytes are used
159 * as the key for the client to server direction. This gives
160 * independent 128-bit keys for each direction."
162 * This library currently only supports encryption when the same key is being used for both directions. This is
163 * because there's only one $crypto object. Two could be added ($encrypt and $decrypt, perhaps).
165 define('NET_SSH1_CIPHER_RC4', 5);
167 * Blowfish
169 * Not supported nor is it defined in the official SSH1 specs. OpenSSH, however, defines it (see cipher.h) and
170 * uses it (see cipher.c)
172 define('NET_SSH1_CIPHER_BLOWFISH', 6);
173 /**#@-*/
175 /**#@+
176 * Authentication Methods
178 * @see Net_SSH1::getSupportedAuthentications()
179 * @access public
182 * .rhosts or /etc/hosts.equiv
184 define('NET_SSH1_AUTH_RHOSTS', 1);
186 * pure RSA authentication
188 define('NET_SSH1_AUTH_RSA', 2);
190 * password authentication
192 * This is the only method that is supported by this library.
194 define('NET_SSH1_AUTH_PASSWORD', 3);
196 * .rhosts with RSA host authentication
198 define('NET_SSH1_AUTH_RHOSTS_RSA', 4);
199 /**#@-*/
201 /**#@+
202 * Terminal Modes
204 * @link http://3sp.com/content/developer/maverick-net/docs/Maverick.SSH.PseudoTerminalModesMembers.html
205 * @access private
207 define('NET_SSH1_TTY_OP_END', 0);
208 /**#@-*/
211 * The Response Type
213 * @see Net_SSH1::_get_binary_packet()
214 * @access private
216 define('NET_SSH1_RESPONSE_TYPE', 1);
219 * The Response Data
221 * @see Net_SSH1::_get_binary_packet()
222 * @access private
224 define('NET_SSH1_RESPONSE_DATA', 2);
226 /**#@+
227 * Execution Bitmap Masks
229 * @see Net_SSH1::bitmap
230 * @access private
232 define('NET_SSH1_MASK_CONSTRUCTOR', 0x00000001);
233 define('NET_SSH1_MASK_LOGIN', 0x00000002);
234 define('NET_SSH1_MASK_SHELL', 0x00000004);
235 /**#@-*/
237 /**#@+
238 * @access public
239 * @see Net_SSH1::getLog()
242 * Returns the message numbers
244 define('NET_SSH1_LOG_SIMPLE', 1);
246 * Returns the message content
248 define('NET_SSH1_LOG_COMPLEX', 2);
249 /**#@-*/
251 /**#@+
252 * @access public
253 * @see Net_SSH1::read()
256 * Returns when a string matching $expect exactly is found
258 define('NET_SSH1_READ_SIMPLE', 1);
260 * Returns when a string matching the regular expression $expect is found
262 define('NET_SSH1_READ_REGEX', 2);
263 /**#@-*/
266 * Pure-PHP implementation of SSHv1.
268 * @author Jim Wigginton <terrafrost@php.net>
269 * @version 0.1.0
270 * @access public
271 * @package Net_SSH1
273 class Net_SSH1 {
275 * The SSH identifier
277 * @var String
278 * @access private
280 var $identifier = 'SSH-1.5-phpseclib';
283 * The Socket Object
285 * @var Object
286 * @access private
288 var $fsock;
291 * The cryptography object
293 * @var Object
294 * @access private
296 var $crypto = false;
299 * Execution Bitmap
301 * The bits that are set represent functions that have been called already. This is used to determine
302 * if a requisite function has been successfully executed. If not, an error should be thrown.
304 * @var Integer
305 * @access private
307 var $bitmap = 0;
310 * The Server Key Public Exponent
312 * Logged for debug purposes
314 * @see Net_SSH1::getServerKeyPublicExponent()
315 * @var String
316 * @access private
318 var $server_key_public_exponent;
321 * The Server Key Public Modulus
323 * Logged for debug purposes
325 * @see Net_SSH1::getServerKeyPublicModulus()
326 * @var String
327 * @access private
329 var $server_key_public_modulus;
332 * The Host Key Public Exponent
334 * Logged for debug purposes
336 * @see Net_SSH1::getHostKeyPublicExponent()
337 * @var String
338 * @access private
340 var $host_key_public_exponent;
343 * The Host Key Public Modulus
345 * Logged for debug purposes
347 * @see Net_SSH1::getHostKeyPublicModulus()
348 * @var String
349 * @access private
351 var $host_key_public_modulus;
354 * Supported Ciphers
356 * Logged for debug purposes
358 * @see Net_SSH1::getSupportedCiphers()
359 * @var Array
360 * @access private
362 var $supported_ciphers = array(
363 NET_SSH1_CIPHER_NONE => 'No encryption',
364 NET_SSH1_CIPHER_IDEA => 'IDEA in CFB mode',
365 NET_SSH1_CIPHER_DES => 'DES in CBC mode',
366 NET_SSH1_CIPHER_3DES => 'Triple-DES in CBC mode',
367 NET_SSH1_CIPHER_BROKEN_TSS => 'TRI\'s Simple Stream encryption CBC',
368 NET_SSH1_CIPHER_RC4 => 'RC4',
369 NET_SSH1_CIPHER_BLOWFISH => 'Blowfish'
373 * Supported Authentications
375 * Logged for debug purposes
377 * @see Net_SSH1::getSupportedAuthentications()
378 * @var Array
379 * @access private
381 var $supported_authentications = array(
382 NET_SSH1_AUTH_RHOSTS => '.rhosts or /etc/hosts.equiv',
383 NET_SSH1_AUTH_RSA => 'pure RSA authentication',
384 NET_SSH1_AUTH_PASSWORD => 'password authentication',
385 NET_SSH1_AUTH_RHOSTS_RSA => '.rhosts with RSA host authentication'
389 * Server Identification
391 * @see Net_SSH1::getServerIdentification()
392 * @var String
393 * @access private
395 var $server_identification = '';
398 * Protocol Flags
400 * @see Net_SSH1::Net_SSH1()
401 * @var Array
402 * @access private
404 var $protocol_flags = array();
407 * Protocol Flag Log
409 * @see Net_SSH1::getLog()
410 * @var Array
411 * @access private
413 var $protocol_flag_log = array();
416 * Message Log
418 * @see Net_SSH1::getLog()
419 * @var Array
420 * @access private
422 var $message_log = array();
425 * Interactive Buffer
427 * @see Net_SSH1::read()
428 * @var Array
429 * @access private
431 var $interactiveBuffer = '';
434 * Default Constructor.
436 * Connects to an SSHv1 server
438 * @param String $host
439 * @param optional Integer $port
440 * @param optional Integer $timeout
441 * @param optional Integer $cipher
442 * @return Net_SSH1
443 * @access public
445 function Net_SSH1($host, $port = 22, $timeout = 10, $cipher = NET_SSH1_CIPHER_3DES)
447 $this->protocol_flags = array(
448 1 => 'NET_SSH1_MSG_DISCONNECT',
449 2 => 'NET_SSH1_SMSG_PUBLIC_KEY',
450 3 => 'NET_SSH1_CMSG_SESSION_KEY',
451 4 => 'NET_SSH1_CMSG_USER',
452 9 => 'NET_SSH1_CMSG_AUTH_PASSWORD',
453 10 => 'NET_SSH1_CMSG_REQUEST_PTY',
454 12 => 'NET_SSH1_CMSG_EXEC_SHELL',
455 13 => 'NET_SSH1_CMSG_EXEC_CMD',
456 14 => 'NET_SSH1_SMSG_SUCCESS',
457 15 => 'NET_SSH1_SMSG_FAILURE',
458 16 => 'NET_SSH1_CMSG_STDIN_DATA',
459 17 => 'NET_SSH1_SMSG_STDOUT_DATA',
460 18 => 'NET_SSH1_SMSG_STDERR_DATA',
461 19 => 'NET_SSH1_CMSG_EOF',
462 20 => 'NET_SSH1_SMSG_EXITSTATUS',
463 33 => 'NET_SSH1_CMSG_EXIT_CONFIRMATION'
466 $this->_define_array($this->protocol_flags);
468 $this->fsock = @fsockopen($host, $port, $errno, $errstr, $timeout);
469 if (!$this->fsock) {
470 user_error(rtrim("Cannot connect to $host. Error $errno. $errstr"), E_USER_NOTICE);
471 return;
474 $this->server_identification = $init_line = fgets($this->fsock, 255);
476 if (defined('NET_SSH1_LOGGING')) {
477 $this->protocol_flags_log[] = '<-';
478 $this->protocol_flags_log[] = '->';
480 if (NET_SSH1_LOGGING == NET_SSH1_LOG_COMPLEX) {
481 $this->message_log[] = $this->server_identification;
482 $this->message_log[] = $this->identifier . "\r\n";
486 if (!preg_match('#SSH-([0-9\.]+)-(.+)#', $init_line, $parts)) {
487 user_error('Can only connect to SSH servers', E_USER_NOTICE);
488 return;
490 if ($parts[1][0] != 1) {
491 user_error("Cannot connect to SSH $parts[1] servers", E_USER_NOTICE);
492 return;
495 fputs($this->fsock, $this->identifier."\r\n");
497 $response = $this->_get_binary_packet();
498 if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_PUBLIC_KEY) {
499 user_error('Expected SSH_SMSG_PUBLIC_KEY', E_USER_NOTICE);
500 return;
503 $anti_spoofing_cookie = $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 8);
505 $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4);
507 $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
508 $server_key_public_exponent = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
509 $this->server_key_public_exponent = $server_key_public_exponent;
511 $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
512 $server_key_public_modulus = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
513 $this->server_key_public_modulus = $server_key_public_modulus;
515 $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4);
517 $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
518 $host_key_public_exponent = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
519 $this->host_key_public_exponent = $host_key_public_exponent;
521 $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
522 $host_key_public_modulus = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
523 $this->host_key_public_modulus = $host_key_public_modulus;
525 $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4);
527 // get a list of the supported ciphers
528 extract(unpack('Nsupported_ciphers_mask', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4)));
529 foreach ($this->supported_ciphers as $mask=>$name) {
530 if (($supported_ciphers_mask & (1 << $mask)) == 0) {
531 unset($this->supported_ciphers[$mask]);
535 // get a list of the supported authentications
536 extract(unpack('Nsupported_authentications_mask', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4)));
537 foreach ($this->supported_authentications as $mask=>$name) {
538 if (($supported_authentications_mask & (1 << $mask)) == 0) {
539 unset($this->supported_authentications[$mask]);
543 $session_id = pack('H*', md5($host_key_public_modulus->toBytes() . $server_key_public_modulus->toBytes() . $anti_spoofing_cookie));
545 $session_key = '';
546 for ($i = 0; $i < 32; $i++) {
547 $session_key.= chr(crypt_random(0, 255));
549 $double_encrypted_session_key = $session_key ^ str_pad($session_id, 32, chr(0));
551 if ($server_key_public_modulus->compare($host_key_public_modulus) < 0) {
552 $double_encrypted_session_key = $this->_rsa_crypt(
553 $double_encrypted_session_key,
554 array(
555 $server_key_public_exponent,
556 $server_key_public_modulus
559 $double_encrypted_session_key = $this->_rsa_crypt(
560 $double_encrypted_session_key,
561 array(
562 $host_key_public_exponent,
563 $host_key_public_modulus
566 } else {
567 $double_encrypted_session_key = $this->_rsa_crypt(
568 $double_encrypted_session_key,
569 array(
570 $host_key_public_exponent,
571 $host_key_public_modulus
574 $double_encrypted_session_key = $this->_rsa_crypt(
575 $double_encrypted_session_key,
576 array(
577 $server_key_public_exponent,
578 $server_key_public_modulus
583 $cipher = isset($this->supported_ciphers[$cipher]) ? $cipher : NET_SSH1_CIPHER_3DES;
584 $data = pack('C2a*na*N', NET_SSH1_CMSG_SESSION_KEY, $cipher, $anti_spoofing_cookie, 8 * strlen($double_encrypted_session_key), $double_encrypted_session_key, 0);
586 if (!$this->_send_binary_packet($data)) {
587 user_error('Error sending SSH_CMSG_SESSION_KEY', E_USER_NOTICE);
588 return;
591 switch ($cipher) {
592 //case NET_SSH1_CIPHER_NONE:
593 // $this->crypto = new Crypt_Null();
594 // break;
595 case NET_SSH1_CIPHER_DES:
596 $this->crypto = new Crypt_DES();
597 $this->crypto->disablePadding();
598 $this->crypto->enableContinuousBuffer();
599 $this->crypto->setKey(substr($session_key, 0, 8));
600 break;
601 case NET_SSH1_CIPHER_3DES:
602 $this->crypto = new Crypt_TripleDES(CRYPT_DES_MODE_3CBC);
603 $this->crypto->disablePadding();
604 $this->crypto->enableContinuousBuffer();
605 $this->crypto->setKey(substr($session_key, 0, 24));
606 break;
607 //case NET_SSH1_CIPHER_RC4:
608 // $this->crypto = new Crypt_RC4();
609 // $this->crypto->enableContinuousBuffer();
610 // $this->crypto->setKey(substr($session_key, 0, 16));
611 // break;
614 $response = $this->_get_binary_packet();
616 if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) {
617 user_error('Expected SSH_SMSG_SUCCESS', E_USER_NOTICE);
618 return;
621 $this->bitmap = NET_SSH1_MASK_CONSTRUCTOR;
625 * Login
627 * @param String $username
628 * @param optional String $password
629 * @return Boolean
630 * @access public
632 function login($username, $password = '')
634 if (!($this->bitmap & NET_SSH1_MASK_CONSTRUCTOR)) {
635 return false;
638 $data = pack('CNa*', NET_SSH1_CMSG_USER, strlen($username), $username);
640 if (!$this->_send_binary_packet($data)) {
641 user_error('Error sending SSH_CMSG_USER', E_USER_NOTICE);
642 return false;
645 $response = $this->_get_binary_packet();
647 if ($response[NET_SSH1_RESPONSE_TYPE] == NET_SSH1_SMSG_SUCCESS) {
648 $this->bitmap |= NET_SSH1_MASK_LOGIN;
649 return true;
650 } else if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_FAILURE) {
651 user_error('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE', E_USER_NOTICE);
652 return false;
655 $data = pack('CNa*', NET_SSH1_CMSG_AUTH_PASSWORD, strlen($password), $password);
657 if (!$this->_send_binary_packet($data)) {
658 user_error('Error sending SSH_CMSG_AUTH_PASSWORD', E_USER_NOTICE);
659 return false;
662 // remove the username and password from the last logged packet
663 if (defined('NET_SSH1_LOGGING') && NET_SSH1_LOGGING == NET_SSH1_LOG_COMPLEX) {
664 $data = pack('CNa*', NET_SSH1_CMSG_AUTH_PASSWORD, strlen('password'), 'password');
665 $this->message_log[count($this->message_log) - 1] = $data; // zzzzz
668 $response = $this->_get_binary_packet();
670 if ($response[NET_SSH1_RESPONSE_TYPE] == NET_SSH1_SMSG_SUCCESS) {
671 $this->bitmap |= NET_SSH1_MASK_LOGIN;
672 return true;
673 } else if ($response[NET_SSH1_RESPONSE_TYPE] == NET_SSH1_SMSG_FAILURE) {
674 return false;
675 } else {
676 user_error('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE', E_USER_NOTICE);
677 return false;
682 * Executes a command on a non-interactive shell, returns the output, and quits.
684 * An SSH1 server will close the connection after a command has been executed on a non-interactive shell. SSH2
685 * servers don't, however, this isn't an SSH2 client. The way this works, on the server, is by initiating a
686 * shell with the -s option, as discussed in the following links:
688 * {@link http://www.faqs.org/docs/bashman/bashref_65.html http://www.faqs.org/docs/bashman/bashref_65.html}
689 * {@link http://www.faqs.org/docs/bashman/bashref_62.html http://www.faqs.org/docs/bashman/bashref_62.html}
691 * To execute further commands, a new Net_SSH1 object will need to be created.
693 * Returns false on failure and the output, otherwise.
695 * @see Net_SSH1::interactiveRead()
696 * @see Net_SSH1::interactiveWrite()
697 * @param String $cmd
698 * @return mixed
699 * @access public
701 function exec($cmd, $block = true)
703 if (!($this->bitmap & NET_SSH1_MASK_LOGIN)) {
704 user_error('Operation disallowed prior to login()', E_USER_NOTICE);
705 return false;
708 $data = pack('CNa*', NET_SSH1_CMSG_EXEC_CMD, strlen($cmd), $cmd);
710 if (!$this->_send_binary_packet($data)) {
711 user_error('Error sending SSH_CMSG_EXEC_CMD', E_USER_NOTICE);
712 return false;
715 if (!$block) {
716 return true;
719 $output = '';
720 $response = $this->_get_binary_packet();
722 do {
723 $output.= substr($response[NET_SSH1_RESPONSE_DATA], 4);
724 $response = $this->_get_binary_packet();
725 } while ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_EXITSTATUS);
727 $data = pack('C', NET_SSH1_CMSG_EXIT_CONFIRMATION);
729 // i don't think it's really all that important if this packet gets sent or not.
730 $this->_send_binary_packet($data);
732 fclose($this->fsock);
734 // reset the execution bitmap - a new Net_SSH1 object needs to be created.
735 $this->bitmap = 0;
737 return $output;
741 * Creates an interactive shell
743 * @see Net_SSH1::interactiveRead()
744 * @see Net_SSH1::interactiveWrite()
745 * @return Boolean
746 * @access private
748 function _initShell()
750 // connect using the sample parameters in protocol-1.5.txt.
751 // according to wikipedia.org's entry on text terminals, "the fundamental type of application running on a text
752 // terminal is a command line interpreter or shell". thus, opening a terminal session to run the shell.
753 $data = pack('CNa*N4C', NET_SSH1_CMSG_REQUEST_PTY, strlen('vt100'), 'vt100', 24, 80, 0, 0, NET_SSH1_TTY_OP_END);
755 if (!$this->_send_binary_packet($data)) {
756 user_error('Error sending SSH_CMSG_REQUEST_PTY', E_USER_NOTICE);
757 return false;
760 $response = $this->_get_binary_packet();
762 if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) {
763 user_error('Expected SSH_SMSG_SUCCESS', E_USER_NOTICE);
764 return false;
767 $data = pack('C', NET_SSH1_CMSG_EXEC_SHELL);
769 if (!$this->_send_binary_packet($data)) {
770 user_error('Error sending SSH_CMSG_EXEC_SHELL', E_USER_NOTICE);
771 return false;
774 $this->bitmap |= NET_SSH1_MASK_SHELL;
776 //stream_set_blocking($this->fsock, 0);
778 return true;
782 * Inputs a command into an interactive shell.
784 * @see Net_SSH1::interactiveWrite()
785 * @param String $cmd
786 * @return Boolean
787 * @access public
789 function write($cmd)
791 return $this->interactiveWrite($cmd);
795 * Returns the output of an interactive shell when there's a match for $expect
797 * $expect can take the form of a string literal or, if $mode == NET_SSH1_READ_REGEX,
798 * a regular expression.
800 * @see Net_SSH1::write()
801 * @param String $expect
802 * @param Integer $mode
803 * @return Boolean
804 * @access public
806 function read($expect, $mode = NET_SSH1_READ_SIMPLE)
808 if (!($this->bitmap & NET_SSH1_MASK_LOGIN)) {
809 user_error('Operation disallowed prior to login()', E_USER_NOTICE);
810 return false;
813 if (!($this->bitmap & NET_SSH1_MASK_SHELL) && !$this->_initShell()) {
814 user_error('Unable to initiate an interactive shell session', E_USER_NOTICE);
815 return false;
818 $match = $expect;
819 while (true) {
820 if ($mode == NET_SSH1_READ_REGEX) {
821 preg_match($expect, $this->interactiveBuffer, $matches);
822 $match = $matches[0];
824 $pos = strpos($this->interactiveBuffer, $match);
825 if ($pos !== false) {
826 return $this->_string_shift($this->interactiveBuffer, $pos + strlen($match));
828 $response = $this->_get_binary_packet();
829 $this->interactiveBuffer.= substr($response[NET_SSH1_RESPONSE_DATA], 4);
834 * Inputs a command into an interactive shell.
836 * @see Net_SSH1::interactiveRead()
837 * @param String $cmd
838 * @return Boolean
839 * @access public
841 function interactiveWrite($cmd)
843 if (!($this->bitmap & NET_SSH1_MASK_LOGIN)) {
844 user_error('Operation disallowed prior to login()', E_USER_NOTICE);
845 return false;
848 if (!($this->bitmap & NET_SSH1_MASK_SHELL) && !$this->_initShell()) {
849 user_error('Unable to initiate an interactive shell session', E_USER_NOTICE);
850 return false;
853 $data = pack('CNa*', NET_SSH1_CMSG_STDIN_DATA, strlen($cmd), $cmd);
855 if (!$this->_send_binary_packet($data)) {
856 user_error('Error sending SSH_CMSG_STDIN', E_USER_NOTICE);
857 return false;
860 return true;
864 * Returns the output of an interactive shell when no more output is available.
866 * Requires PHP 4.3.0 or later due to the use of the stream_select() function. If you see stuff like
867 * "\e[00m", you're seeing ANSI escape codes. According to
868 * {@link http://support.microsoft.com/kb/101875 How to Enable ANSI.SYS in a Command Window}, "Windows NT
869 * does not support ANSI escape sequences in Win32 Console applications", so if you're a Windows user,
870 * there's not going to be much recourse.
872 * @see Net_SSH1::interactiveRead()
873 * @return String
874 * @access public
876 function interactiveRead()
878 if (!($this->bitmap & NET_SSH1_MASK_LOGIN)) {
879 user_error('Operation disallowed prior to login()', E_USER_NOTICE);
880 return false;
883 if (!($this->bitmap & NET_SSH1_MASK_SHELL) && !$this->_initShell()) {
884 user_error('Unable to initiate an interactive shell session', E_USER_NOTICE);
885 return false;
888 $read = array($this->fsock);
889 $write = $except = null;
890 if (stream_select($read, $write, $except, 0)) {
891 $response = $this->_get_binary_packet();
892 return substr($response[NET_SSH1_RESPONSE_DATA], 4);
893 } else {
894 return '';
899 * Disconnect
901 * @access public
903 function disconnect()
905 $this->_disconnect();
909 * Destructor.
911 * Will be called, automatically, if you're supporting just PHP5. If you're supporting PHP4, you'll need to call
912 * disconnect().
914 * @access public
916 function __destruct()
918 $this->_disconnect();
922 * Disconnect
924 * @param String $msg
925 * @access private
927 function _disconnect($msg = 'Client Quit')
929 if ($this->bitmap) {
930 $data = pack('C', NET_SSH1_CMSG_EOF);
931 $this->_send_binary_packet($data);
933 $response = $this->_get_binary_packet();
934 switch ($response[NET_SSH1_RESPONSE_TYPE]) {
935 case NET_SSH1_SMSG_EXITSTATUS:
936 $data = pack('C', NET_SSH1_CMSG_EXIT_CONFIRMATION);
937 break;
938 default:
939 $data = pack('CNa*', NET_SSH1_MSG_DISCONNECT, strlen($msg), $msg);
942 $this->_send_binary_packet($data);
943 fclose($this->fsock);
944 $this->bitmap = 0;
949 * Gets Binary Packets
951 * See 'The Binary Packet Protocol' of protocol-1.5.txt for more info.
953 * Also, this function could be improved upon by adding detection for the following exploit:
954 * http://www.securiteam.com/securitynews/5LP042K3FY.html
956 * @see Net_SSH1::_send_binary_packet()
957 * @return Array
958 * @access private
960 function _get_binary_packet()
962 if (feof($this->fsock)) {
963 //user_error('connection closed prematurely', E_USER_NOTICE);
964 return false;
967 $temp = unpack('Nlength', fread($this->fsock, 4));
969 $padding_length = 8 - ($temp['length'] & 7);
970 $length = $temp['length'] + $padding_length;
972 $start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838
973 $raw = fread($this->fsock, $length);
974 $stop = strtok(microtime(), ' ') + strtok('');
976 if ($this->crypto !== false) {
977 $raw = $this->crypto->decrypt($raw);
980 $padding = substr($raw, 0, $padding_length);
981 $type = $raw[$padding_length];
982 $data = substr($raw, $padding_length + 1, -4);
984 $temp = unpack('Ncrc', substr($raw, -4));
986 //if ( $temp['crc'] != $this->_crc($padding . $type . $data) ) {
987 // user_error('Bad CRC in packet from server', E_USER_NOTICE);
988 // return false;
991 $type = ord($type);
993 if (defined('NET_SSH1_LOGGING')) {
994 $temp = isset($this->protocol_flags[$type]) ? $this->protocol_flags[$type] : 'UNKNOWN';
995 $this->protocol_flags_log[] = '<- ' . $temp .
996 ' (' . round($stop - $start, 4) . 's)';
997 if (NET_SSH1_LOGGING == NET_SSH1_LOG_COMPLEX) {
998 $this->message_log[] = $data;
1002 return array(
1003 NET_SSH1_RESPONSE_TYPE => $type,
1004 NET_SSH1_RESPONSE_DATA => $data
1009 * Sends Binary Packets
1011 * Returns true on success, false on failure.
1013 * @see Net_SSH1::_get_binary_packet()
1014 * @param String $data
1015 * @return Boolean
1016 * @access private
1018 function _send_binary_packet($data) {
1019 if (feof($this->fsock)) {
1020 //user_error('connection closed prematurely', E_USER_NOTICE);
1021 return false;
1024 if (defined('NET_SSH1_LOGGING')) {
1025 $temp = isset($this->protocol_flags[ord($data[0])]) ? $this->protocol_flags[ord($data[0])] : 'UNKNOWN';
1026 $this->protocol_flags_log[] = '-> ' . $temp .
1027 ' (' . round($stop - $start, 4) . 's)';
1028 if (NET_SSH1_LOGGING == NET_SSH1_LOG_COMPLEX) {
1029 $this->message_log[] = substr($data, 1);
1033 $length = strlen($data) + 4;
1035 $padding_length = 8 - ($length & 7);
1036 $padding = '';
1037 for ($i = 0; $i < $padding_length; $i++) {
1038 $padding.= chr(crypt_random(0, 255));
1041 $data = $padding . $data;
1042 $data.= pack('N', $this->_crc($data));
1044 if ($this->crypto !== false) {
1045 $data = $this->crypto->encrypt($data);
1048 $packet = pack('Na*', $length, $data);
1050 $start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838
1051 $result = strlen($packet) == fputs($this->fsock, $packet);
1052 $stop = strtok(microtime(), ' ') + strtok('');
1054 return $result;
1058 * Cyclic Redundancy Check (CRC)
1060 * PHP's crc32 function is implemented slightly differently than the one that SSH v1 uses, so
1061 * we've reimplemented it. A more detailed discussion of the differences can be found after
1062 * $crc_lookup_table's initialization.
1064 * @see Net_SSH1::_get_binary_packet()
1065 * @see Net_SSH1::_send_binary_packet()
1066 * @param String $data
1067 * @return Integer
1068 * @access private
1070 function _crc($data)
1072 static $crc_lookup_table = array(
1073 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
1074 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
1075 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
1076 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
1077 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
1078 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
1079 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
1080 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
1081 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
1082 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
1083 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
1084 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
1085 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
1086 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
1087 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
1088 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
1089 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
1090 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
1091 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
1092 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
1093 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
1094 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
1095 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
1096 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
1097 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
1098 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
1099 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
1100 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
1101 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
1102 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
1103 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
1104 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
1105 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
1106 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
1107 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
1108 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
1109 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
1110 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
1111 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
1112 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
1113 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
1114 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
1115 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
1116 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
1117 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
1118 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
1119 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
1120 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
1121 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
1122 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
1123 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
1124 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
1125 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
1126 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
1127 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
1128 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
1129 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
1130 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
1131 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
1132 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
1133 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
1134 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
1135 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
1136 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
1139 // For this function to yield the same output as PHP's crc32 function, $crc would have to be
1140 // set to 0xFFFFFFFF, initially - not 0x00000000 as it currently is.
1141 $crc = 0x00000000;
1142 $length = strlen($data);
1144 for ($i=0;$i<$length;$i++) {
1145 // We AND $crc >> 8 with 0x00FFFFFF because we want the eight newly added bits to all
1146 // be zero. PHP, unfortunately, doesn't always do this. 0x80000000 >> 8, as an example,
1147 // yields 0xFF800000 - not 0x00800000. The following link elaborates:
1148 // http://www.php.net/manual/en/language.operators.bitwise.php#57281
1149 $crc = (($crc >> 8) & 0x00FFFFFF) ^ $crc_lookup_table[($crc & 0xFF) ^ ord($data[$i])];
1152 // In addition to having to set $crc to 0xFFFFFFFF, initially, the return value must be XOR'd with
1153 // 0xFFFFFFFF for this function to return the same thing that PHP's crc32 function would.
1154 return $crc;
1158 * String Shift
1160 * Inspired by array_shift
1162 * @param String $string
1163 * @param optional Integer $index
1164 * @return String
1165 * @access private
1167 function _string_shift(&$string, $index = 1)
1169 $substr = substr($string, 0, $index);
1170 $string = substr($string, $index);
1171 return $substr;
1175 * RSA Encrypt
1177 * Returns mod(pow($m, $e), $n), where $n should be the product of two (large) primes $p and $q and where $e
1178 * should be a number with the property that gcd($e, ($p - 1) * ($q - 1)) == 1. Could just make anything that
1179 * calls this call modexp, instead, but I think this makes things clearer, maybe...
1181 * @see Net_SSH1::Net_SSH1()
1182 * @param Math_BigInteger $m
1183 * @param Array $key
1184 * @return Math_BigInteger
1185 * @access private
1187 function _rsa_crypt($m, $key)
1190 if (!class_exists('Crypt_RSA')) {
1191 require_once('Crypt/RSA.php');
1194 $rsa = new Crypt_RSA();
1195 $rsa->loadKey($key, CRYPT_RSA_PUBLIC_FORMAT_RAW);
1196 $rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
1197 return $rsa->encrypt($m);
1200 // To quote from protocol-1.5.txt:
1201 // The most significant byte (which is only partial as the value must be
1202 // less than the public modulus, which is never a power of two) is zero.
1204 // The next byte contains the value 2 (which stands for public-key
1205 // encrypted data in the PKCS standard [PKCS#1]). Then, there are non-
1206 // zero random bytes to fill any unused space, a zero byte, and the data
1207 // to be encrypted in the least significant bytes, the last byte of the
1208 // data in the least significant byte.
1210 // Presumably the part of PKCS#1 they're refering to is "Section 7.2.1 Encryption Operation",
1211 // under "7.2 RSAES-PKCS1-v1.5" and "7 Encryption schemes" of the following URL:
1212 // ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.pdf
1213 $temp = chr(0) . chr(2);
1214 $modulus = $key[1]->toBytes();
1215 $length = strlen($modulus) - strlen($m) - 3;
1216 for ($i = 0; $i < $length; $i++) {
1217 $temp.= chr(crypt_random(1, 255));
1219 $temp.= chr(0) . $m;
1221 $m = new Math_BigInteger($temp, 256);
1222 $m = $m->modPow($key[0], $key[1]);
1224 return $m->toBytes();
1228 * Define Array
1230 * Takes any number of arrays whose indices are integers and whose values are strings and defines a bunch of
1231 * named constants from it, using the value as the name of the constant and the index as the value of the constant.
1232 * If any of the constants that would be defined already exists, none of the constants will be defined.
1234 * @param Array $array
1235 * @access private
1237 function _define_array()
1239 $args = func_get_args();
1240 foreach ($args as $arg) {
1241 foreach ($arg as $key=>$value) {
1242 if (!defined($value)) {
1243 define($value, $key);
1244 } else {
1245 break 2;
1252 * Returns a log of the packets that have been sent and received.
1254 * Returns a string if NET_SSH2_LOGGING == NET_SSH2_LOG_COMPLEX, an array if NET_SSH2_LOGGING == NET_SSH2_LOG_SIMPLE and false if !defined('NET_SSH2_LOGGING')
1256 * @access public
1257 * @return String or Array
1259 function getLog()
1261 if (!defined('NET_SSH1_LOGGING')) {
1262 return false;
1265 switch (NET_SSH1_LOGGING) {
1266 case NET_SSH1_LOG_SIMPLE:
1267 return $this->message_number_log;
1268 break;
1269 case NET_SSH1_LOG_COMPLEX:
1270 return $this->_format_log($this->message_log, $this->protocol_flags_log);
1271 break;
1272 default:
1273 return false;
1278 * Formats a log for printing
1280 * @param Array $message_log
1281 * @param Array $message_number_log
1282 * @access private
1283 * @return String
1285 function _format_log($message_log, $message_number_log)
1287 static $boundary = ':', $long_width = 65, $short_width = 16;
1289 $output = '';
1290 for ($i = 0; $i < count($message_log); $i++) {
1291 $output.= $message_number_log[$i] . "\r\n";
1292 $current_log = $message_log[$i];
1293 $j = 0;
1294 do {
1295 if (!empty($current_log)) {
1296 $output.= str_pad(dechex($j), 7, '0', STR_PAD_LEFT) . '0 ';
1298 $fragment = $this->_string_shift($current_log, $short_width);
1299 $hex = substr(
1300 preg_replace(
1301 '#(.)#es',
1302 '"' . $boundary . '" . str_pad(dechex(ord(substr("\\1", -1))), 2, "0", STR_PAD_LEFT)',
1303 $fragment),
1304 strlen($boundary)
1306 // replace non ASCII printable characters with dots
1307 // http://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters
1308 // also replace < with a . since < messes up the output on web browsers
1309 $raw = preg_replace('#[^\x20-\x7E]|<#', '.', $fragment);
1310 $output.= str_pad($hex, $long_width - $short_width, ' ') . $raw . "\r\n";
1311 $j++;
1312 } while (!empty($current_log));
1313 $output.= "\r\n";
1316 return $output;
1320 * Return the server key public exponent
1322 * Returns, by default, the base-10 representation. If $raw_output is set to true, returns, instead,
1323 * the raw bytes. This behavior is similar to PHP's md5() function.
1325 * @param optional Boolean $raw_output
1326 * @return String
1327 * @access public
1329 function getServerKeyPublicExponent($raw_output = false)
1331 return $raw_output ? $this->server_key_public_exponent->toBytes() : $this->server_key_public_exponent->toString();
1335 * Return the server key public modulus
1337 * Returns, by default, the base-10 representation. If $raw_output is set to true, returns, instead,
1338 * the raw bytes. This behavior is similar to PHP's md5() function.
1340 * @param optional Boolean $raw_output
1341 * @return String
1342 * @access public
1344 function getServerKeyPublicModulus($raw_output = false)
1346 return $raw_output ? $this->server_key_public_modulus->toBytes() : $this->server_key_public_modulus->toString();
1350 * Return the host key public exponent
1352 * Returns, by default, the base-10 representation. If $raw_output is set to true, returns, instead,
1353 * the raw bytes. This behavior is similar to PHP's md5() function.
1355 * @param optional Boolean $raw_output
1356 * @return String
1357 * @access public
1359 function getHostKeyPublicExponent($raw_output = false)
1361 return $raw_output ? $this->host_key_public_exponent->toBytes() : $this->host_key_public_exponent->toString();
1365 * Return the host key public modulus
1367 * Returns, by default, the base-10 representation. If $raw_output is set to true, returns, instead,
1368 * the raw bytes. This behavior is similar to PHP's md5() function.
1370 * @param optional Boolean $raw_output
1371 * @return String
1372 * @access public
1374 function getHostKeyPublicModulus($raw_output = false)
1376 return $raw_output ? $this->host_key_public_modulus->toBytes() : $this->host_key_public_modulus->toString();
1380 * Return a list of ciphers supported by SSH1 server.
1382 * Just because a cipher is supported by an SSH1 server doesn't mean it's supported by this library. If $raw_output
1383 * is set to true, returns, instead, an array of constants. ie. instead of array('Triple-DES in CBC mode'), you'll
1384 * get array(NET_SSH1_CIPHER_3DES).
1386 * @param optional Boolean $raw_output
1387 * @return Array
1388 * @access public
1390 function getSupportedCiphers($raw_output = false)
1392 return $raw_output ? array_keys($this->supported_ciphers) : array_values($this->supported_ciphers);
1396 * Return a list of authentications supported by SSH1 server.
1398 * Just because a cipher is supported by an SSH1 server doesn't mean it's supported by this library. If $raw_output
1399 * is set to true, returns, instead, an array of constants. ie. instead of array('password authentication'), you'll
1400 * get array(NET_SSH1_AUTH_PASSWORD).
1402 * @param optional Boolean $raw_output
1403 * @return Array
1404 * @access public
1406 function getSupportedAuthentications($raw_output = false)
1408 return $raw_output ? array_keys($this->supported_authentications) : array_values($this->supported_authentications);
1412 * Return the server identification.
1414 * @return String
1415 * @access public
1417 function getServerIdentification()
1419 return rtrim($this->server_identification);