]> git.mxchange.org Git - friendica.git/blob - library/phpsec/Net/SSH1.php
Merge pull request #482 from pixelroot/master
[friendica.git] / library / phpsec / Net / SSH1.php
1 <?php\r
2 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */\r
3 \r
4 /**\r
5  * Pure-PHP implementation of SSHv1.\r
6  *\r
7  * PHP versions 4 and 5\r
8  *\r
9  * Here's a short example of how to use this library:\r
10  * <code>\r
11  * <?php\r
12  *    include('Net/SSH1.php');\r
13  *\r
14  *    $ssh = new Net_SSH1('www.domain.tld');\r
15  *    if (!$ssh->login('username', 'password')) {\r
16  *        exit('Login Failed');\r
17  *    }\r
18  *\r
19  *    while (true) {\r
20  *        echo $ssh->interactiveRead();\r
21  *\r
22  *        $read = array(STDIN);\r
23  *        $write = $except = NULL;\r
24  *        if (stream_select($read, $write, $except, 0)) {\r
25  *            $ssh->interactiveWrite(fread(STDIN, 1));\r
26  *        }\r
27  *    }\r
28  * ?>\r
29  * </code>\r
30  *\r
31  * Here's another short example:\r
32  * <code>\r
33  * <?php\r
34  *    include('Net/SSH1.php');\r
35  *\r
36  *    $ssh = new Net_SSH1('www.domain.tld');\r
37  *    if (!$ssh->login('username', 'password')) {\r
38  *        exit('Login Failed');\r
39  *    }\r
40  *\r
41  *    echo $ssh->exec('ls -la');\r
42  * ?>\r
43  * </code>\r
44  *\r
45  * More information on the SSHv1 specification can be found by reading \r
46  * {@link http://www.snailbook.com/docs/protocol-1.5.txt protocol-1.5.txt}.\r
47  *\r
48  * LICENSE: This library is free software; you can redistribute it and/or\r
49  * modify it under the terms of the GNU Lesser General Public\r
50  * License as published by the Free Software Foundation; either\r
51  * version 2.1 of the License, or (at your option) any later version.\r
52  *\r
53  * This library is distributed in the hope that it will be useful,\r
54  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
55  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
56  * Lesser General Public License for more details.\r
57  *\r
58  * You should have received a copy of the GNU Lesser General Public\r
59  * License along with this library; if not, write to the Free Software\r
60  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,\r
61  * MA  02111-1307  USA\r
62  *\r
63  * @category   Net\r
64  * @package    Net_SSH1\r
65  * @author     Jim Wigginton <terrafrost@php.net>\r
66  * @copyright  MMVII Jim Wigginton\r
67  * @license    http://www.gnu.org/licenses/lgpl.txt\r
68  * @version    $Id: SSH1.php,v 1.15 2010/03/22 22:01:38 terrafrost Exp $\r
69  * @link       http://phpseclib.sourceforge.net\r
70  */\r
71 \r
72 /**\r
73  * Include Math_BigInteger\r
74  *\r
75  * Used to do RSA encryption.\r
76  */\r
77 require_once('Math/BigInteger.php');\r
78 \r
79 /**\r
80  * Include Crypt_Null\r
81  */\r
82 //require_once('Crypt/Null.php');\r
83 \r
84 /**\r
85  * Include Crypt_DES\r
86  */\r
87 require_once('Crypt/DES.php');\r
88 \r
89 /**\r
90  * Include Crypt_TripleDES\r
91  */\r
92 require_once('Crypt/TripleDES.php');\r
93 \r
94 /**\r
95  * Include Crypt_RC4\r
96  */\r
97 require_once('Crypt/RC4.php');\r
98 \r
99 /**\r
100  * Include Crypt_Random\r
101  */\r
102 require_once('Crypt/Random.php');\r
103 \r
104 /**#@+\r
105  * Protocol Flags\r
106  *\r
107  * @access private\r
108  */\r
109 define('NET_SSH1_MSG_DISCONNECT',          1);\r
110 define('NET_SSH1_SMSG_PUBLIC_KEY',         2);\r
111 define('NET_SSH1_CMSG_SESSION_KEY',        3);\r
112 define('NET_SSH1_CMSG_USER',               4);\r
113 define('NET_SSH1_CMSG_AUTH_PASSWORD',      9);\r
114 define('NET_SSH1_CMSG_REQUEST_PTY',       10);\r
115 define('NET_SSH1_CMSG_EXEC_SHELL',        12);\r
116 define('NET_SSH1_CMSG_EXEC_CMD',          13);\r
117 define('NET_SSH1_SMSG_SUCCESS',           14);\r
118 define('NET_SSH1_SMSG_FAILURE',           15);\r
119 define('NET_SSH1_CMSG_STDIN_DATA',        16);\r
120 define('NET_SSH1_SMSG_STDOUT_DATA',       17);\r
121 define('NET_SSH1_SMSG_STDERR_DATA',       18);\r
122 define('NET_SSH1_SMSG_EXITSTATUS',        20);\r
123 define('NET_SSH1_CMSG_EXIT_CONFIRMATION', 33);\r
124 /**#@-*/\r
125 \r
126 /**#@+\r
127  * Encryption Methods\r
128  *\r
129  * @see Net_SSH1::getSupportedCiphers()\r
130  * @access public\r
131  */\r
132 /**\r
133  * No encryption\r
134  *\r
135  * Not supported.\r
136  */\r
137 define('NET_SSH1_CIPHER_NONE',       0);\r
138 /**\r
139  * IDEA in CFB mode\r
140  *\r
141  * Not supported.\r
142  */\r
143 define('NET_SSH1_CIPHER_IDEA',       1);\r
144 /**\r
145  * DES in CBC mode\r
146  */\r
147 define('NET_SSH1_CIPHER_DES',        2);\r
148 /**\r
149  * Triple-DES in CBC mode\r
150  *\r
151  * All implementations are required to support this\r
152  */\r
153 define('NET_SSH1_CIPHER_3DES',       3);\r
154 /**\r
155  * TRI's Simple Stream encryption CBC\r
156  *\r
157  * Not supported nor is it defined in the official SSH1 specs.  OpenSSH, however, does define it (see cipher.h),\r
158  * although it doesn't use it (see cipher.c)\r
159  */\r
160 define('NET_SSH1_CIPHER_BROKEN_TSS', 4);\r
161 /**\r
162  * RC4\r
163  *\r
164  * Not supported.\r
165  *\r
166  * @internal According to the SSH1 specs:\r
167  *\r
168  *        "The first 16 bytes of the session key are used as the key for\r
169  *         the server to client direction.  The remaining 16 bytes are used\r
170  *         as the key for the client to server direction.  This gives\r
171  *         independent 128-bit keys for each direction."\r
172  *\r
173  *     This library currently only supports encryption when the same key is being used for both directions.  This is\r
174  *     because there's only one $crypto object.  Two could be added ($encrypt and $decrypt, perhaps).\r
175  */\r
176 define('NET_SSH1_CIPHER_RC4',        5);\r
177 /**\r
178  * Blowfish\r
179  *\r
180  * Not supported nor is it defined in the official SSH1 specs.  OpenSSH, however, defines it (see cipher.h) and\r
181  * uses it (see cipher.c)\r
182  */\r
183 define('NET_SSH1_CIPHER_BLOWFISH',   6);\r
184 /**#@-*/\r
185 \r
186 /**#@+\r
187  * Authentication Methods\r
188  *\r
189  * @see Net_SSH1::getSupportedAuthentications()\r
190  * @access public\r
191  */\r
192 /**\r
193  * .rhosts or /etc/hosts.equiv\r
194  */\r
195 define('NET_SSH1_AUTH_RHOSTS',     1);\r
196 /**\r
197  * pure RSA authentication\r
198  */\r
199 define('NET_SSH1_AUTH_RSA',        2);\r
200 /**\r
201  * password authentication\r
202  *\r
203  * This is the only method that is supported by this library.\r
204  */\r
205 define('NET_SSH1_AUTH_PASSWORD',   3);\r
206 /**\r
207  * .rhosts with RSA host authentication\r
208  */\r
209 define('NET_SSH1_AUTH_RHOSTS_RSA', 4);\r
210 /**#@-*/\r
211 \r
212 /**#@+\r
213  * Terminal Modes\r
214  *\r
215  * @link http://3sp.com/content/developer/maverick-net/docs/Maverick.SSH.PseudoTerminalModesMembers.html\r
216  * @access private\r
217  */\r
218 define('NET_SSH1_TTY_OP_END',  0);\r
219 /**#@-*/\r
220 \r
221 /**\r
222  * The Response Type\r
223  *\r
224  * @see Net_SSH1::_get_binary_packet()\r
225  * @access private\r
226  */\r
227 define('NET_SSH1_RESPONSE_TYPE', 1);\r
228 \r
229 /**\r
230  * The Response Data\r
231  *\r
232  * @see Net_SSH1::_get_binary_packet()\r
233  * @access private\r
234  */\r
235 define('NET_SSH1_RESPONSE_DATA', 2);\r
236 \r
237 /**#@+\r
238  * Execution Bitmap Masks\r
239  *\r
240  * @see Net_SSH1::bitmap\r
241  * @access private\r
242  */\r
243 define('NET_SSH1_MASK_CONSTRUCTOR', 0x00000001);\r
244 define('NET_SSH1_MASK_LOGIN',       0x00000002);\r
245 define('NET_SSH1_MASK_SHELL',       0x00000004);\r
246 /**#@-*/\r
247 \r
248 /**\r
249  * Pure-PHP implementation of SSHv1.\r
250  *\r
251  * @author  Jim Wigginton <terrafrost@php.net>\r
252  * @version 0.1.0\r
253  * @access  public\r
254  * @package Net_SSH1\r
255  */\r
256 class Net_SSH1 {\r
257     /**\r
258      * The SSH identifier\r
259      *\r
260      * @var String\r
261      * @access private\r
262      */\r
263     var $identifier = 'SSH-1.5-phpseclib';\r
264 \r
265     /**\r
266      * The Socket Object\r
267      *\r
268      * @var Object\r
269      * @access private\r
270      */\r
271     var $fsock;\r
272 \r
273     /**\r
274      * The cryptography object\r
275      *\r
276      * @var Object\r
277      * @access private\r
278      */\r
279     var $crypto = false;\r
280 \r
281     /**\r
282      * Execution Bitmap\r
283      *\r
284      * The bits that are set reprsent functions that have been called already.  This is used to determine\r
285      * if a requisite function has been successfully executed.  If not, an error should be thrown.\r
286      *\r
287      * @var Integer\r
288      * @access private\r
289      */\r
290     var $bitmap = 0;\r
291 \r
292     /**\r
293      * The Server Key Public Exponent\r
294      *\r
295      * Logged for debug purposes\r
296      *\r
297      * @see Net_SSH1::getServerKeyPublicExponent()\r
298      * @var String\r
299      * @access private\r
300      */\r
301     var $server_key_public_exponent;\r
302 \r
303     /**\r
304      * The Server Key Public Modulus\r
305      *\r
306      * Logged for debug purposes\r
307      *\r
308      * @see Net_SSH1::getServerKeyPublicModulus()\r
309      * @var String\r
310      * @access private\r
311      */\r
312     var $server_key_public_modulus;\r
313 \r
314     /**\r
315      * The Host Key Public Exponent\r
316      *\r
317      * Logged for debug purposes\r
318      *\r
319      * @see Net_SSH1::getHostKeyPublicExponent()\r
320      * @var String\r
321      * @access private\r
322      */\r
323     var $host_key_public_exponent;\r
324 \r
325     /**\r
326      * The Host Key Public Modulus\r
327      *\r
328      * Logged for debug purposes\r
329      *\r
330      * @see Net_SSH1::getHostKeyPublicModulus()\r
331      * @var String\r
332      * @access private\r
333      */\r
334     var $host_key_public_modulus;\r
335 \r
336     /**\r
337      * Supported Ciphers\r
338      *\r
339      * Logged for debug purposes\r
340      *\r
341      * @see Net_SSH1::getSupportedCiphers()\r
342      * @var Array\r
343      * @access private\r
344      */\r
345     var $supported_ciphers = array(\r
346         NET_SSH1_CIPHER_NONE       => 'No encryption',\r
347         NET_SSH1_CIPHER_IDEA       => 'IDEA in CFB mode',\r
348         NET_SSH1_CIPHER_DES        => 'DES in CBC mode',\r
349         NET_SSH1_CIPHER_3DES       => 'Triple-DES in CBC mode',\r
350         NET_SSH1_CIPHER_BROKEN_TSS => 'TRI\'s Simple Stream encryption CBC',\r
351         NET_SSH1_CIPHER_RC4        => 'RC4',\r
352         NET_SSH1_CIPHER_BLOWFISH   => 'Blowfish'\r
353     );\r
354 \r
355     /**\r
356      * Supported Authentications\r
357      *\r
358      * Logged for debug purposes\r
359      *\r
360      * @see Net_SSH1::getSupportedAuthentications()\r
361      * @var Array\r
362      * @access private\r
363      */\r
364     var $supported_authentications = array(\r
365         NET_SSH1_AUTH_RHOSTS     => '.rhosts or /etc/hosts.equiv',\r
366         NET_SSH1_AUTH_RSA        => 'pure RSA authentication',\r
367         NET_SSH1_AUTH_PASSWORD   => 'password authentication',\r
368         NET_SSH1_AUTH_RHOSTS_RSA => '.rhosts with RSA host authentication'\r
369     );\r
370 \r
371     /**\r
372      * Server Identification\r
373      *\r
374      * @see Net_SSH1::getServerIdentification()\r
375      * @var String\r
376      * @access private\r
377      */\r
378     var $server_identification = '';\r
379 \r
380     /**\r
381      * Default Constructor.\r
382      *\r
383      * Connects to an SSHv1 server\r
384      *\r
385      * @param String $host\r
386      * @param optional Integer $port\r
387      * @param optional Integer $timeout\r
388      * @param optional Integer $cipher\r
389      * @return Net_SSH1\r
390      * @access public\r
391      */\r
392     function Net_SSH1($host, $port = 22, $timeout = 10, $cipher = NET_SSH1_CIPHER_3DES)\r
393     {\r
394         $this->fsock = @fsockopen($host, $port, $errno, $errstr, $timeout);\r
395         if (!$this->fsock) {\r
396             user_error(rtrim("Cannot connect to $host. Error $errno. $errstr"), E_USER_NOTICE);\r
397             return;\r
398         }\r
399 \r
400         $this->server_identification = $init_line = fgets($this->fsock, 255);\r
401         if (!preg_match('#SSH-([0-9\.]+)-(.+)#', $init_line, $parts)) {\r
402             user_error('Can only connect to SSH servers', E_USER_NOTICE);\r
403             return;\r
404         }\r
405         if ($parts[1][0] != 1) {\r
406             user_error("Cannot connect to SSH $parts[1] servers", E_USER_NOTICE);\r
407             return;\r
408         }\r
409 \r
410         fputs($this->fsock, $this->identifier."\r\n");\r
411 \r
412         $response = $this->_get_binary_packet();\r
413         if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_PUBLIC_KEY) {\r
414             user_error('Expected SSH_SMSG_PUBLIC_KEY', E_USER_NOTICE);\r
415             return;\r
416         }\r
417 \r
418         $anti_spoofing_cookie = $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 8);\r
419 \r
420         $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4);\r
421 \r
422         $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));\r
423         $server_key_public_exponent = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);\r
424         $this->server_key_public_exponent = $server_key_public_exponent;\r
425 \r
426         $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));\r
427         $server_key_public_modulus = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);\r
428         $this->server_key_public_modulus = $server_key_public_modulus;\r
429 \r
430         $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4);\r
431 \r
432         $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));\r
433         $host_key_public_exponent = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);\r
434         $this->host_key_public_exponent = $host_key_public_exponent;\r
435 \r
436         $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));\r
437         $host_key_public_modulus = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);\r
438         $this->host_key_public_modulus = $host_key_public_modulus;\r
439 \r
440         $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4);\r
441 \r
442         // get a list of the supported ciphers\r
443         extract(unpack('Nsupported_ciphers_mask', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4)));\r
444         foreach ($this->supported_ciphers as $mask=>$name) {\r
445             if (($supported_ciphers_mask & (1 << $mask)) == 0) {\r
446                 unset($this->supported_ciphers[$mask]);\r
447             }\r
448         }\r
449 \r
450         // get a list of the supported authentications\r
451         extract(unpack('Nsupported_authentications_mask', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4)));\r
452         foreach ($this->supported_authentications as $mask=>$name) {\r
453             if (($supported_authentications_mask & (1 << $mask)) == 0) {\r
454                 unset($this->supported_authentications[$mask]);\r
455             }\r
456         }\r
457 \r
458         $session_id = pack('H*', md5($host_key_public_modulus->toBytes() . $server_key_public_modulus->toBytes() . $anti_spoofing_cookie));\r
459 \r
460         $session_key = '';\r
461         for ($i = 0; $i < 32; $i++) {\r
462             $session_key.= chr(crypt_random(0, 255));\r
463         }\r
464         $double_encrypted_session_key = $session_key ^ str_pad($session_id, 32, chr(0));\r
465 \r
466         if ($server_key_public_modulus->compare($host_key_public_modulus) < 0) {\r
467             $double_encrypted_session_key = $this->_rsa_crypt(\r
468                 $double_encrypted_session_key,\r
469                 array(\r
470                     $server_key_public_exponent,\r
471                     $server_key_public_modulus\r
472                 )\r
473             );\r
474             $double_encrypted_session_key = $this->_rsa_crypt(\r
475                 $double_encrypted_session_key,\r
476                 array(\r
477                     $host_key_public_exponent,\r
478                     $host_key_public_modulus\r
479                 )\r
480             );\r
481         } else {\r
482             $double_encrypted_session_key = $this->_rsa_crypt(\r
483                 $double_encrypted_session_key,\r
484                 array(\r
485                     $host_key_public_exponent,\r
486                     $host_key_public_modulus\r
487                 )\r
488             );\r
489             $double_encrypted_session_key = $this->_rsa_crypt(\r
490                 $double_encrypted_session_key,\r
491                 array(\r
492                     $server_key_public_exponent,\r
493                     $server_key_public_modulus\r
494                 )\r
495             );\r
496         }\r
497 \r
498         $cipher = isset($this->supported_ciphers[$cipher]) ? $cipher : NET_SSH1_CIPHER_3DES;\r
499         $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);\r
500 \r
501         if (!$this->_send_binary_packet($data)) {\r
502             user_error('Error sending SSH_CMSG_SESSION_KEY', E_USER_NOTICE);\r
503             return;\r
504         }\r
505 \r
506         switch ($cipher) {\r
507             //case NET_SSH1_CIPHER_NONE:\r
508             //    $this->crypto = new Crypt_Null();\r
509             //    break;\r
510             case NET_SSH1_CIPHER_DES:\r
511                 $this->crypto = new Crypt_DES();\r
512                 $this->crypto->disablePadding();\r
513                 $this->crypto->enableContinuousBuffer();\r
514                 $this->crypto->setKey(substr($session_key, 0,  8));\r
515                 break;\r
516             case NET_SSH1_CIPHER_3DES:\r
517                 $this->crypto = new Crypt_TripleDES(CRYPT_DES_MODE_3CBC);\r
518                 $this->crypto->disablePadding();\r
519                 $this->crypto->enableContinuousBuffer();\r
520                 $this->crypto->setKey(substr($session_key, 0, 24));\r
521                 break;\r
522             //case NET_SSH1_CIPHER_RC4:\r
523             //    $this->crypto = new Crypt_RC4();\r
524             //    $this->crypto->enableContinuousBuffer();\r
525             //    $this->crypto->setKey(substr($session_key, 0,  16));\r
526             //    break;\r
527         }\r
528 \r
529         $response = $this->_get_binary_packet();\r
530 \r
531         if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) {\r
532             user_error('Expected SSH_SMSG_SUCCESS', E_USER_NOTICE);\r
533             return;\r
534         }\r
535 \r
536         $this->bitmap = NET_SSH1_MASK_CONSTRUCTOR;\r
537     }\r
538 \r
539     /**\r
540      * Login\r
541      *\r
542      * @param String $username\r
543      * @param optional String $password\r
544      * @return Boolean\r
545      * @access public\r
546      */\r
547     function login($username, $password = '')\r
548     {\r
549         if (!($this->bitmap & NET_SSH1_MASK_CONSTRUCTOR)) {\r
550             return false;\r
551         }\r
552 \r
553         $data = pack('CNa*', NET_SSH1_CMSG_USER, strlen($username), $username);\r
554 \r
555         if (!$this->_send_binary_packet($data)) {\r
556             user_error('Error sending SSH_CMSG_USER', E_USER_NOTICE);\r
557             return false;\r
558         }\r
559 \r
560         $response = $this->_get_binary_packet();\r
561 \r
562         if ($response[NET_SSH1_RESPONSE_TYPE] == NET_SSH1_SMSG_SUCCESS) {\r
563             $this->bitmap |= NET_SSH1_MASK_LOGIN;\r
564             return true;\r
565         } else if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_FAILURE) {\r
566             user_error('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE', E_USER_NOTICE);\r
567             return false;\r
568         }\r
569 \r
570         $data = pack('CNa*', NET_SSH1_CMSG_AUTH_PASSWORD, strlen($password), $password);\r
571 \r
572         if (!$this->_send_binary_packet($data)) {\r
573             user_error('Error sending SSH_CMSG_AUTH_PASSWORD', E_USER_NOTICE);\r
574             return false;\r
575         }\r
576 \r
577         $response = $this->_get_binary_packet();\r
578 \r
579         if ($response[NET_SSH1_RESPONSE_TYPE] == NET_SSH1_SMSG_SUCCESS) {\r
580             $this->bitmap |= NET_SSH1_MASK_LOGIN;\r
581             return true;\r
582         } else if ($response[NET_SSH1_RESPONSE_TYPE] == NET_SSH1_SMSG_FAILURE) {\r
583             return false;\r
584         } else {\r
585             user_error('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE', E_USER_NOTICE);\r
586             return false;\r
587         }\r
588     }\r
589 \r
590     /**\r
591      * Executes a command on a non-interactive shell, returns the output, and quits.\r
592      *\r
593      * An SSH1 server will close the connection after a command has been executed on a non-interactive shell.  SSH2\r
594      * servers don't, however, this isn't an SSH2 client.  The way this works, on the server, is by initiating a\r
595      * shell with the -s option, as discussed in the following links:\r
596      *\r
597      * {@link http://www.faqs.org/docs/bashman/bashref_65.html http://www.faqs.org/docs/bashman/bashref_65.html}\r
598      * {@link http://www.faqs.org/docs/bashman/bashref_62.html http://www.faqs.org/docs/bashman/bashref_62.html}\r
599      *\r
600      * To execute further commands, a new Net_SSH1 object will need to be created.\r
601      *\r
602      * Returns false on failure and the output, otherwise.\r
603      *\r
604      * @see Net_SSH1::interactiveRead()\r
605      * @see Net_SSH1::interactiveWrite()\r
606      * @param String $cmd\r
607      * @return mixed\r
608      * @access public\r
609      */\r
610     function exec($cmd)\r
611     {\r
612         if (!($this->bitmap & NET_SSH1_MASK_LOGIN)) {\r
613             user_error('Operation disallowed prior to login()', E_USER_NOTICE);\r
614             return false;\r
615         }\r
616 \r
617         // connect using the sample parameters in protocol-1.5.txt.\r
618         // according to wikipedia.org's entry on text terminals, "the fundamental type of application running on a text\r
619         // terminal is a command line interpreter or shell".  thus, opening a terminal session to run the shell.\r
620         $data = pack('CNa*N4C', NET_SSH1_CMSG_REQUEST_PTY, strlen('vt100'), 'vt100', 24, 80, 0, 0, NET_SSH1_TTY_OP_END);\r
621 \r
622         if (!$this->_send_binary_packet($data)) {\r
623             user_error('Error sending SSH_CMSG_REQUEST_PTY', E_USER_NOTICE);\r
624             return false;\r
625         }\r
626 \r
627         $response = $this->_get_binary_packet();\r
628 \r
629         if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) {\r
630             user_error('Expected SSH_SMSG_SUCCESS', E_USER_NOTICE);\r
631             return false;\r
632         }\r
633 \r
634         $data = pack('CNa*', NET_SSH1_CMSG_EXEC_CMD, strlen($cmd), $cmd);\r
635 \r
636         if (!$this->_send_binary_packet($data)) {\r
637             user_error('Error sending SSH_CMSG_EXEC_CMD', E_USER_NOTICE);\r
638             return false;\r
639         }\r
640 \r
641         $output = '';\r
642         $response = $this->_get_binary_packet();\r
643 \r
644         do {\r
645             $output.= substr($response[NET_SSH1_RESPONSE_DATA], 4);\r
646             $response = $this->_get_binary_packet();\r
647         } while ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_EXITSTATUS);\r
648 \r
649         $data = pack('C', NET_SSH1_CMSG_EXIT_CONFIRMATION);\r
650 \r
651         // i don't think it's really all that important if this packet gets sent or not.\r
652         $this->_send_binary_packet($data);\r
653 \r
654         fclose($this->fsock);\r
655 \r
656         // reset the execution bitmap - a new Net_SSH1 object needs to be created.\r
657         $this->bitmap = 0;\r
658 \r
659         return $output;\r
660     }\r
661 \r
662     /**\r
663      * Creates an interactive shell\r
664      *\r
665      * @see Net_SSH1::interactiveRead()\r
666      * @see Net_SSH1::interactiveWrite()\r
667      * @return Boolean\r
668      * @access private\r
669      */\r
670     function _initShell()\r
671     {\r
672         $data = pack('CNa*N4C', NET_SSH1_CMSG_REQUEST_PTY, strlen('vt100'), 'vt100', 24, 80, 0, 0, NET_SSH1_TTY_OP_END);\r
673 \r
674         if (!$this->_send_binary_packet($data)) {\r
675             user_error('Error sending SSH_CMSG_REQUEST_PTY', E_USER_NOTICE);\r
676             return false;\r
677         }\r
678 \r
679         $response = $this->_get_binary_packet();\r
680 \r
681         if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) {\r
682             user_error('Expected SSH_SMSG_SUCCESS', E_USER_NOTICE);\r
683             return false;\r
684         }\r
685 \r
686         $data = pack('C', NET_SSH1_CMSG_EXEC_SHELL);\r
687 \r
688         if (!$this->_send_binary_packet($data)) {\r
689             user_error('Error sending SSH_CMSG_EXEC_SHELL', E_USER_NOTICE);\r
690             return false;\r
691         }\r
692 \r
693         $this->bitmap |= NET_SSH1_MASK_SHELL;\r
694 \r
695         //stream_set_blocking($this->fsock, 0);\r
696 \r
697         return true;\r
698     }\r
699 \r
700     /**\r
701      * Inputs a command into an interactive shell.\r
702      *\r
703      * @see Net_SSH1::interactiveRead()\r
704      * @param String $cmd\r
705      * @return Boolean\r
706      * @access public\r
707      */\r
708     function interactiveWrite($cmd)\r
709     {\r
710         if (!($this->bitmap & NET_SSH1_MASK_LOGIN)) {\r
711             user_error('Operation disallowed prior to login()', E_USER_NOTICE);\r
712             return false;\r
713         }\r
714 \r
715         if (!($this->bitmap & NET_SSH1_MASK_SHELL) && !$this->_initShell()) {\r
716             user_error('Unable to initiate an interactive shell session', E_USER_NOTICE);\r
717             return false;\r
718         }\r
719 \r
720         $data = pack('CNa*', NET_SSH1_CMSG_STDIN_DATA, strlen($cmd), $cmd);\r
721 \r
722         if (!$this->_send_binary_packet($data)) {\r
723             user_error('Error sending SSH_CMSG_STDIN', E_USER_NOTICE);\r
724             return false;\r
725         }\r
726 \r
727         return true;\r
728     }\r
729 \r
730     /**\r
731      * Reads the output of an interactive shell.\r
732      *\r
733      * Requires PHP 4.3.0 or later due to the use of the stream_select() function.  If you see crap, \r
734      * you're seeing ANSI escape codes.  According to\r
735      * {@link http://support.microsoft.com/kb/101875 How to Enable ANSI.SYS in a Command Window}, "Windows NT\r
736      * does not support ANSI escape sequences in Win32 Console applications", so if you're a Windows user,\r
737      * there's not going to be much recourse.\r
738      *\r
739      * @see Net_SSH1::interactiveRead()\r
740      * @return String\r
741      * @access public\r
742      */\r
743     function interactiveRead()\r
744     {\r
745         if (!($this->bitmap & NET_SSH1_MASK_LOGIN)) {\r
746             user_error('Operation disallowed prior to login()', E_USER_NOTICE);\r
747             return false;\r
748         }\r
749 \r
750         if (!($this->bitmap & NET_SSH1_MASK_SHELL) && !$this->_initShell()) {\r
751             user_error('Unable to initiate an interactive shell session', E_USER_NOTICE);\r
752             return false;\r
753         }\r
754 \r
755         $read = array($this->fsock);\r
756         $write = $except = null;\r
757         if (stream_select($read, $write, $except, 0)) {\r
758             $response = $this->_get_binary_packet();\r
759             return substr($response[NET_SSH1_RESPONSE_DATA], 4);\r
760         } else {\r
761             return '';\r
762         }\r
763     }\r
764 \r
765     /**\r
766      * Disconnect\r
767      *\r
768      * @access public\r
769      */\r
770     function disconnect()\r
771     {\r
772         $this->_disconnect();\r
773     }\r
774 \r
775     /**\r
776      * Destructor.\r
777      *\r
778      * Will be called, automatically, if you're supporting just PHP5.  If you're supporting PHP4, you'll need to call\r
779      * disconnect().\r
780      *\r
781      * @access public\r
782      */\r
783     function __destruct()\r
784     {\r
785         $this->_disconnect();\r
786     }\r
787 \r
788     /**\r
789      * Disconnect\r
790      *\r
791      * @param String $msg\r
792      * @access private\r
793      */\r
794     function _disconnect($msg = 'Client Quit')\r
795     {\r
796         if ($this->bitmap) {\r
797             $data = pack('CNa*', NET_SSH1_MSG_DISCONNECT, strlen($msg), $msg);\r
798             $this->_send_binary_packet($data);\r
799             fclose($this->fsock);\r
800             $this->bitmap = 0;\r
801         }\r
802     }\r
803 \r
804     /**\r
805      * Gets Binary Packets\r
806      *\r
807      * See 'The Binary Packet Protocol' of protocol-1.5.txt for more info.\r
808      *\r
809      * Also, this function could be improved upon by adding detection for the following exploit:\r
810      * http://www.securiteam.com/securitynews/5LP042K3FY.html\r
811      *\r
812      * @see Net_SSH1::_send_binary_packet()\r
813      * @return Array\r
814      * @access private\r
815      */\r
816     function _get_binary_packet()\r
817     {\r
818         if (feof($this->fsock)) {\r
819             //user_error('connection closed prematurely', E_USER_NOTICE);\r
820             return false;\r
821         }\r
822 \r
823         $temp = unpack('Nlength', fread($this->fsock, 4));\r
824 \r
825         $padding_length = 8 - ($temp['length'] & 7);\r
826         $length = $temp['length'] + $padding_length;\r
827 \r
828         $raw = fread($this->fsock, $length);\r
829 \r
830         if ($this->crypto !== false) {\r
831             $raw = $this->crypto->decrypt($raw);\r
832         }\r
833 \r
834         $padding = substr($raw, 0, $padding_length);\r
835         $type = $raw[$padding_length];\r
836         $data = substr($raw, $padding_length + 1, -4);\r
837 \r
838         $temp = unpack('Ncrc', substr($raw, -4));\r
839 \r
840         //if ( $temp['crc'] != $this->_crc($padding . $type . $data) ) {\r
841         //    user_error('Bad CRC in packet from server', E_USER_NOTICE);\r
842         //    return false;\r
843         //}\r
844 \r
845         return array(\r
846             NET_SSH1_RESPONSE_TYPE => ord($type),\r
847             NET_SSH1_RESPONSE_DATA => $data\r
848         );\r
849     }\r
850 \r
851     /**\r
852      * Sends Binary Packets\r
853      *\r
854      * Returns true on success, false on failure.\r
855      *\r
856      * @see Net_SSH1::_get_binary_packet()\r
857      * @param String $data\r
858      * @return Boolean\r
859      * @access private\r
860      */\r
861     function _send_binary_packet($data) {\r
862         if (feof($this->fsock)) {\r
863             //user_error('connection closed prematurely', E_USER_NOTICE);\r
864             return false;\r
865         }\r
866 \r
867         $length = strlen($data) + 4;\r
868 \r
869         $padding_length = 8 - ($length & 7);\r
870         $padding = '';\r
871         for ($i = 0; $i < $padding_length; $i++) {\r
872             $padding.= chr(crypt_random(0, 255));\r
873         }\r
874 \r
875         $data = $padding . $data;\r
876         $data.= pack('N', $this->_crc($data));\r
877 \r
878         if ($this->crypto !== false) {\r
879             $data = $this->crypto->encrypt($data);\r
880         }\r
881 \r
882         $packet = pack('Na*', $length, $data);\r
883 \r
884         return strlen($packet) == fputs($this->fsock, $packet);\r
885     }\r
886 \r
887     /**\r
888      * Cyclic Redundancy Check (CRC)\r
889      *\r
890      * PHP's crc32 function is implemented slightly differently than the one that SSH v1 uses, so\r
891      * we've reimplemented it. A more detailed discussion of the differences can be found after\r
892      * $crc_lookup_table's initialization.\r
893      *\r
894      * @see Net_SSH1::_get_binary_packet()\r
895      * @see Net_SSH1::_send_binary_packet()\r
896      * @param String $data\r
897      * @return Integer\r
898      * @access private\r
899      */\r
900     function _crc($data)\r
901     {\r
902         static $crc_lookup_table = array(\r
903             0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,\r
904             0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,\r
905             0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,\r
906             0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,\r
907             0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,\r
908             0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,\r
909             0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,\r
910             0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,\r
911             0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,\r
912             0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,\r
913             0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,\r
914             0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,\r
915             0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,\r
916             0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,\r
917             0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,\r
918             0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,\r
919             0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,\r
920             0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,\r
921             0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,\r
922             0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,\r
923             0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,\r
924             0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,\r
925             0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,\r
926             0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,\r
927             0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,\r
928             0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,\r
929             0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,\r
930             0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,\r
931             0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,\r
932             0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,\r
933             0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,\r
934             0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,\r
935             0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,\r
936             0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,\r
937             0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,\r
938             0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,\r
939             0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,\r
940             0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,\r
941             0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,\r
942             0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,\r
943             0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,\r
944             0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,\r
945             0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,\r
946             0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,\r
947             0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,\r
948             0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,\r
949             0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,\r
950             0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,\r
951             0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,\r
952             0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,\r
953             0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,\r
954             0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,\r
955             0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,\r
956             0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,\r
957             0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,\r
958             0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,\r
959             0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,\r
960             0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,\r
961             0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,\r
962             0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,\r
963             0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,\r
964             0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,\r
965             0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,\r
966             0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D\r
967         );\r
968 \r
969         // For this function to yield the same output as PHP's crc32 function, $crc would have to be\r
970         // set to 0xFFFFFFFF, initially - not 0x00000000 as it currently is.\r
971         $crc = 0x00000000;\r
972         $length = strlen($data);\r
973 \r
974         for ($i=0;$i<$length;$i++) {\r
975             // We AND $crc >> 8 with 0x00FFFFFF because we want the eight newly added bits to all\r
976             // be zero.  PHP, unfortunately, doesn't always do this.  0x80000000 >> 8, as an example,\r
977             // yields 0xFF800000 - not 0x00800000.  The following link elaborates:\r
978             // http://www.php.net/manual/en/language.operators.bitwise.php#57281\r
979             $crc = (($crc >> 8) & 0x00FFFFFF) ^ $crc_lookup_table[($crc & 0xFF) ^ ord($data[$i])];\r
980         }\r
981 \r
982         // In addition to having to set $crc to 0xFFFFFFFF, initially, the return value must be XOR'd with\r
983         // 0xFFFFFFFF for this function to return the same thing that PHP's crc32 function would.\r
984         return $crc;\r
985     }\r
986 \r
987     /**\r
988      * String Shift\r
989      *\r
990      * Inspired by array_shift\r
991      *\r
992      * @param String $string\r
993      * @param optional Integer $index\r
994      * @return String\r
995      * @access private\r
996      */\r
997     function _string_shift(&$string, $index = 1)\r
998     {\r
999         $substr = substr($string, 0, $index);\r
1000         $string = substr($string, $index);\r
1001         return $substr;\r
1002     }\r
1003 \r
1004     /**\r
1005      * RSA Encrypt\r
1006      *\r
1007      * Returns mod(pow($m, $e), $n), where $n should be the product of two (large) primes $p and $q and where $e\r
1008      * should be a number with the property that gcd($e, ($p - 1) * ($q - 1)) == 1.  Could just make anything that\r
1009      * calls this call modexp, instead, but I think this makes things clearer, maybe...\r
1010      *\r
1011      * @see Net_SSH1::Net_SSH1()\r
1012      * @param Math_BigInteger $m\r
1013      * @param Array $key\r
1014      * @return Math_BigInteger\r
1015      * @access private\r
1016      */\r
1017     function _rsa_crypt($m, $key)\r
1018     {\r
1019         /*\r
1020         if (!class_exists('Crypt_RSA')) {\r
1021             require_once('Crypt/RSA.php');\r
1022         }\r
1023 \r
1024         $rsa = new Crypt_RSA();\r
1025         $rsa->loadKey($key, CRYPT_RSA_PUBLIC_FORMAT_RAW);\r
1026         $rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);\r
1027         return $rsa->encrypt($m);\r
1028         */\r
1029 \r
1030         // To quote from protocol-1.5.txt:\r
1031         // The most significant byte (which is only partial as the value must be\r
1032         // less than the public modulus, which is never a power of two) is zero.\r
1033         //\r
1034         // The next byte contains the value 2 (which stands for public-key\r
1035         // encrypted data in the PKCS standard [PKCS#1]).  Then, there are non-\r
1036         // zero random bytes to fill any unused space, a zero byte, and the data\r
1037         // to be encrypted in the least significant bytes, the last byte of the\r
1038         // data in the least significant byte.\r
1039 \r
1040         // Presumably the part of PKCS#1 they're refering to is "Section 7.2.1 Encryption Operation",\r
1041         // under "7.2 RSAES-PKCS1-v1.5" and "7 Encryption schemes" of the following URL:\r
1042         // ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.pdf\r
1043         $temp = chr(0) . chr(2);\r
1044         $modulus = $key[1]->toBytes();\r
1045         $length = strlen($modulus) - strlen($m) - 3;\r
1046         for ($i = 0; $i < $length; $i++) {\r
1047             $temp.= chr(crypt_random(1, 255));\r
1048         }\r
1049         $temp.= chr(0) . $m;\r
1050 \r
1051         $m = new Math_BigInteger($temp, 256);\r
1052         $m = $m->modPow($key[0], $key[1]);\r
1053 \r
1054         return $m->toBytes();\r
1055     }\r
1056 \r
1057     /**\r
1058      * Return the server key public exponent\r
1059      *\r
1060      * Returns, by default, the base-10 representation.  If $raw_output is set to true, returns, instead,\r
1061      * the raw bytes.  This behavior is similar to PHP's md5() function.\r
1062      *\r
1063      * @param optional Boolean $raw_output\r
1064      * @return String\r
1065      * @access public\r
1066      */\r
1067     function getServerKeyPublicExponent($raw_output = false)\r
1068     {\r
1069         return $raw_output ? $this->server_key_public_exponent->toBytes() : $this->server_key_public_exponent->toString();\r
1070     }\r
1071 \r
1072     /**\r
1073      * Return the server key public modulus\r
1074      *\r
1075      * Returns, by default, the base-10 representation.  If $raw_output is set to true, returns, instead,\r
1076      * the raw bytes.  This behavior is similar to PHP's md5() function.\r
1077      *\r
1078      * @param optional Boolean $raw_output\r
1079      * @return String\r
1080      * @access public\r
1081      */\r
1082     function getServerKeyPublicModulus($raw_output = false)\r
1083     {\r
1084         return $raw_output ? $this->server_key_public_modulus->toBytes() : $this->server_key_public_modulus->toString();\r
1085     }\r
1086 \r
1087     /**\r
1088      * Return the host key public exponent\r
1089      *\r
1090      * Returns, by default, the base-10 representation.  If $raw_output is set to true, returns, instead,\r
1091      * the raw bytes.  This behavior is similar to PHP's md5() function.\r
1092      *\r
1093      * @param optional Boolean $raw_output\r
1094      * @return String\r
1095      * @access public\r
1096      */\r
1097     function getHostKeyPublicExponent($raw_output = false)\r
1098     {\r
1099         return $raw_output ? $this->host_key_public_exponent->toBytes() : $this->host_key_public_exponent->toString();\r
1100     }\r
1101 \r
1102     /**\r
1103      * Return the host key public modulus\r
1104      *\r
1105      * Returns, by default, the base-10 representation.  If $raw_output is set to true, returns, instead,\r
1106      * the raw bytes.  This behavior is similar to PHP's md5() function.\r
1107      *\r
1108      * @param optional Boolean $raw_output\r
1109      * @return String\r
1110      * @access public\r
1111      */\r
1112     function getHostKeyPublicModulus($raw_output = false)\r
1113     {\r
1114         return $raw_output ? $this->host_key_public_modulus->toBytes() : $this->host_key_public_modulus->toString();\r
1115     }\r
1116 \r
1117     /**\r
1118      * Return a list of ciphers supported by SSH1 server.\r
1119      *\r
1120      * Just because a cipher is supported by an SSH1 server doesn't mean it's supported by this library. If $raw_output\r
1121      * is set to true, returns, instead, an array of constants.  ie. instead of array('Triple-DES in CBC mode'), you'll\r
1122      * get array(NET_SSH1_CIPHER_3DES).\r
1123      *\r
1124      * @param optional Boolean $raw_output\r
1125      * @return Array\r
1126      * @access public\r
1127      */\r
1128     function getSupportedCiphers($raw_output = false)\r
1129     {\r
1130         return $raw_output ? array_keys($this->supported_ciphers) : array_values($this->supported_ciphers);\r
1131     }\r
1132 \r
1133     /**\r
1134      * Return a list of authentications supported by SSH1 server.\r
1135      *\r
1136      * Just because a cipher is supported by an SSH1 server doesn't mean it's supported by this library. If $raw_output\r
1137      * is set to true, returns, instead, an array of constants.  ie. instead of array('password authentication'), you'll\r
1138      * get array(NET_SSH1_AUTH_PASSWORD).\r
1139      *\r
1140      * @param optional Boolean $raw_output\r
1141      * @return Array\r
1142      * @access public\r
1143      */\r
1144     function getSupportedAuthentications($raw_output = false)\r
1145     {\r
1146         return $raw_output ? array_keys($this->supported_authentications) : array_values($this->supported_authentications);\r
1147     }\r
1148 \r
1149     /**\r
1150      * Return the server identification.\r
1151      *\r
1152      * @return String\r
1153      * @access public\r
1154      */\r
1155     function getServerIdentification()\r
1156     {\r
1157         return rtrim($this->server_identification);\r
1158     }\r
1159 }\r
1160 ?>