PageRenderTime 63ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/drupal/profiles/medienlabor/modules/contrib/aes/phpseclib/Net/SSH2.php

https://bitbucket.org/cbeier/test
PHP | 2901 lines | 1538 code | 348 blank | 1015 comment | 253 complexity | 96d43c659ee7f81da4d0b1a7ce4d3886 MD5 | raw file
Possible License(s): GPL-2.0, AGPL-1.0, LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  3. /**
  4. * Pure-PHP implementation of SSHv2.
  5. *
  6. * PHP versions 4 and 5
  7. *
  8. * Here are some examples of how to use this library:
  9. * <code>
  10. * <?php
  11. * include('Net/SSH2.php');
  12. *
  13. * $ssh = new Net_SSH2('www.domain.tld');
  14. * if (!$ssh->login('username', 'password')) {
  15. * exit('Login Failed');
  16. * }
  17. *
  18. * echo $ssh->exec('pwd');
  19. * echo $ssh->exec('ls -la');
  20. * ?>
  21. * </code>
  22. *
  23. * <code>
  24. * <?php
  25. * include('Crypt/RSA.php');
  26. * include('Net/SSH2.php');
  27. *
  28. * $key = new Crypt_RSA();
  29. * //$key->setPassword('whatever');
  30. * $key->loadKey(file_get_contents('privatekey'));
  31. *
  32. * $ssh = new Net_SSH2('www.domain.tld');
  33. * if (!$ssh->login('username', $key)) {
  34. * exit('Login Failed');
  35. * }
  36. *
  37. * echo $ssh->read('username@username:~$');
  38. * $ssh->write("ls -la\n");
  39. * echo $ssh->read('username@username:~$');
  40. * ?>
  41. * </code>
  42. *
  43. * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
  44. * of this software and associated documentation files (the "Software"), to deal
  45. * in the Software without restriction, including without limitation the rights
  46. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  47. * copies of the Software, and to permit persons to whom the Software is
  48. * furnished to do so, subject to the following conditions:
  49. *
  50. * The above copyright notice and this permission notice shall be included in
  51. * all copies or substantial portions of the Software.
  52. *
  53. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  54. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  55. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  56. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  57. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  58. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  59. * THE SOFTWARE.
  60. *
  61. * @category Net
  62. * @package Net_SSH2
  63. * @author Jim Wigginton <terrafrost@php.net>
  64. * @copyright MMVII Jim Wigginton
  65. * @license http://www.opensource.org/licenses/mit-license.html MIT License
  66. * @version $Id: SSH2.php,v 1.53 2010-10-24 01:24:30 terrafrost Exp $
  67. * @link http://phpseclib.sourceforge.net
  68. */
  69. /**
  70. * Include Math_BigInteger
  71. *
  72. * Used to do Diffie-Hellman key exchange and DSA/RSA signature verification.
  73. */
  74. if (!class_exists('Math_BigInteger')) {
  75. require_once('Math/BigInteger.php');
  76. }
  77. /**
  78. * Include Crypt_Random
  79. */
  80. // the class_exists() will only be called if the crypt_random function hasn't been defined and
  81. // will trigger a call to __autoload() if you're wanting to auto-load classes
  82. // call function_exists() a second time to stop the require_once from being called outside
  83. // of the auto loader
  84. if (!function_exists('crypt_random') && !class_exists('Crypt_Random') && !function_exists('crypt_random')) {
  85. require_once('Crypt/Random.php');
  86. }
  87. /**
  88. * Include Crypt_Hash
  89. */
  90. if (!class_exists('Crypt_Hash')) {
  91. require_once('Crypt/Hash.php');
  92. }
  93. /**
  94. * Include Crypt_TripleDES
  95. */
  96. if (!class_exists('Crypt_TripleDES')) {
  97. require_once('Crypt/TripleDES.php');
  98. }
  99. /**
  100. * Include Crypt_RC4
  101. */
  102. if (!class_exists('Crypt_RC4')) {
  103. require_once('Crypt/RC4.php');
  104. }
  105. /**
  106. * Include Crypt_AES
  107. */
  108. if (!class_exists('Crypt_AES')) {
  109. require_once('Crypt/AES.php');
  110. }
  111. /**#@+
  112. * Execution Bitmap Masks
  113. *
  114. * @see Net_SSH2::bitmap
  115. * @access private
  116. */
  117. define('NET_SSH2_MASK_CONSTRUCTOR', 0x00000001);
  118. define('NET_SSH2_MASK_LOGIN', 0x00000002);
  119. define('NET_SSH2_MASK_SHELL', 0x00000004);
  120. /**#@-*/
  121. /**#@+
  122. * Channel constants
  123. *
  124. * RFC4254 refers not to client and server channels but rather to sender and recipient channels. we don't refer
  125. * to them in that way because RFC4254 toggles the meaning. the client sends a SSH_MSG_CHANNEL_OPEN message with
  126. * a sender channel and the server sends a SSH_MSG_CHANNEL_OPEN_CONFIRMATION in response, with a sender and a
  127. * recepient channel. at first glance, you might conclude that SSH_MSG_CHANNEL_OPEN_CONFIRMATION's sender channel
  128. * would be the same thing as SSH_MSG_CHANNEL_OPEN's sender channel, but it's not, per this snipet:
  129. * The 'recipient channel' is the channel number given in the original
  130. * open request, and 'sender channel' is the channel number allocated by
  131. * the other side.
  132. *
  133. * @see Net_SSH2::_send_channel_packet()
  134. * @see Net_SSH2::_get_channel_packet()
  135. * @access private
  136. */
  137. define('NET_SSH2_CHANNEL_EXEC', 0); // PuTTy uses 0x100
  138. define('NET_SSH2_CHANNEL_SHELL',1);
  139. /**#@-*/
  140. /**#@+
  141. * @access public
  142. * @see Net_SSH2::getLog()
  143. */
  144. /**
  145. * Returns the message numbers
  146. */
  147. define('NET_SSH2_LOG_SIMPLE', 1);
  148. /**
  149. * Returns the message content
  150. */
  151. define('NET_SSH2_LOG_COMPLEX', 2);
  152. /**
  153. * Outputs the content real-time
  154. */
  155. define('NET_SSH2_LOG_REALTIME', 3);
  156. /**#@-*/
  157. /**#@+
  158. * @access public
  159. * @see Net_SSH2::read()
  160. */
  161. /**
  162. * Returns when a string matching $expect exactly is found
  163. */
  164. define('NET_SSH2_READ_SIMPLE', 1);
  165. /**
  166. * Returns when a string matching the regular expression $expect is found
  167. */
  168. define('NET_SSH2_READ_REGEX', 2);
  169. /**
  170. * Make sure that the log never gets larger than this
  171. */
  172. define('NET_SSH2_LOG_MAX_SIZE', 1024 * 1024);
  173. /**#@-*/
  174. /**
  175. * Pure-PHP implementation of SSHv2.
  176. *
  177. * @author Jim Wigginton <terrafrost@php.net>
  178. * @version 0.1.0
  179. * @access public
  180. * @package Net_SSH2
  181. */
  182. class Net_SSH2 {
  183. /**
  184. * The SSH identifier
  185. *
  186. * @var String
  187. * @access private
  188. */
  189. var $identifier = 'SSH-2.0-phpseclib_0.3';
  190. /**
  191. * The Socket Object
  192. *
  193. * @var Object
  194. * @access private
  195. */
  196. var $fsock;
  197. /**
  198. * Execution Bitmap
  199. *
  200. * The bits that are set reprsent functions that have been called already. This is used to determine
  201. * if a requisite function has been successfully executed. If not, an error should be thrown.
  202. *
  203. * @var Integer
  204. * @access private
  205. */
  206. var $bitmap = 0;
  207. /**
  208. * Error information
  209. *
  210. * @see Net_SSH2::getErrors()
  211. * @see Net_SSH2::getLastError()
  212. * @var String
  213. * @access private
  214. */
  215. var $errors = array();
  216. /**
  217. * Server Identifier
  218. *
  219. * @see Net_SSH2::getServerIdentification()
  220. * @var String
  221. * @access private
  222. */
  223. var $server_identifier = '';
  224. /**
  225. * Key Exchange Algorithms
  226. *
  227. * @see Net_SSH2::getKexAlgorithims()
  228. * @var Array
  229. * @access private
  230. */
  231. var $kex_algorithms;
  232. /**
  233. * Server Host Key Algorithms
  234. *
  235. * @see Net_SSH2::getServerHostKeyAlgorithms()
  236. * @var Array
  237. * @access private
  238. */
  239. var $server_host_key_algorithms;
  240. /**
  241. * Encryption Algorithms: Client to Server
  242. *
  243. * @see Net_SSH2::getEncryptionAlgorithmsClient2Server()
  244. * @var Array
  245. * @access private
  246. */
  247. var $encryption_algorithms_client_to_server;
  248. /**
  249. * Encryption Algorithms: Server to Client
  250. *
  251. * @see Net_SSH2::getEncryptionAlgorithmsServer2Client()
  252. * @var Array
  253. * @access private
  254. */
  255. var $encryption_algorithms_server_to_client;
  256. /**
  257. * MAC Algorithms: Client to Server
  258. *
  259. * @see Net_SSH2::getMACAlgorithmsClient2Server()
  260. * @var Array
  261. * @access private
  262. */
  263. var $mac_algorithms_client_to_server;
  264. /**
  265. * MAC Algorithms: Server to Client
  266. *
  267. * @see Net_SSH2::getMACAlgorithmsServer2Client()
  268. * @var Array
  269. * @access private
  270. */
  271. var $mac_algorithms_server_to_client;
  272. /**
  273. * Compression Algorithms: Client to Server
  274. *
  275. * @see Net_SSH2::getCompressionAlgorithmsClient2Server()
  276. * @var Array
  277. * @access private
  278. */
  279. var $compression_algorithms_client_to_server;
  280. /**
  281. * Compression Algorithms: Server to Client
  282. *
  283. * @see Net_SSH2::getCompressionAlgorithmsServer2Client()
  284. * @var Array
  285. * @access private
  286. */
  287. var $compression_algorithms_server_to_client;
  288. /**
  289. * Languages: Server to Client
  290. *
  291. * @see Net_SSH2::getLanguagesServer2Client()
  292. * @var Array
  293. * @access private
  294. */
  295. var $languages_server_to_client;
  296. /**
  297. * Languages: Client to Server
  298. *
  299. * @see Net_SSH2::getLanguagesClient2Server()
  300. * @var Array
  301. * @access private
  302. */
  303. var $languages_client_to_server;
  304. /**
  305. * Block Size for Server to Client Encryption
  306. *
  307. * "Note that the length of the concatenation of 'packet_length',
  308. * 'padding_length', 'payload', and 'random padding' MUST be a multiple
  309. * of the cipher block size or 8, whichever is larger. This constraint
  310. * MUST be enforced, even when using stream ciphers."
  311. *
  312. * -- http://tools.ietf.org/html/rfc4253#section-6
  313. *
  314. * @see Net_SSH2::Net_SSH2()
  315. * @see Net_SSH2::_send_binary_packet()
  316. * @var Integer
  317. * @access private
  318. */
  319. var $encrypt_block_size = 8;
  320. /**
  321. * Block Size for Client to Server Encryption
  322. *
  323. * @see Net_SSH2::Net_SSH2()
  324. * @see Net_SSH2::_get_binary_packet()
  325. * @var Integer
  326. * @access private
  327. */
  328. var $decrypt_block_size = 8;
  329. /**
  330. * Server to Client Encryption Object
  331. *
  332. * @see Net_SSH2::_get_binary_packet()
  333. * @var Object
  334. * @access private
  335. */
  336. var $decrypt = false;
  337. /**
  338. * Client to Server Encryption Object
  339. *
  340. * @see Net_SSH2::_send_binary_packet()
  341. * @var Object
  342. * @access private
  343. */
  344. var $encrypt = false;
  345. /**
  346. * Client to Server HMAC Object
  347. *
  348. * @see Net_SSH2::_send_binary_packet()
  349. * @var Object
  350. * @access private
  351. */
  352. var $hmac_create = false;
  353. /**
  354. * Server to Client HMAC Object
  355. *
  356. * @see Net_SSH2::_get_binary_packet()
  357. * @var Object
  358. * @access private
  359. */
  360. var $hmac_check = false;
  361. /**
  362. * Size of server to client HMAC
  363. *
  364. * We need to know how big the HMAC will be for the server to client direction so that we know how many bytes to read.
  365. * For the client to server side, the HMAC object will make the HMAC as long as it needs to be. All we need to do is
  366. * append it.
  367. *
  368. * @see Net_SSH2::_get_binary_packet()
  369. * @var Integer
  370. * @access private
  371. */
  372. var $hmac_size = false;
  373. /**
  374. * Server Public Host Key
  375. *
  376. * @see Net_SSH2::getServerPublicHostKey()
  377. * @var String
  378. * @access private
  379. */
  380. var $server_public_host_key;
  381. /**
  382. * Session identifer
  383. *
  384. * "The exchange hash H from the first key exchange is additionally
  385. * used as the session identifier, which is a unique identifier for
  386. * this connection."
  387. *
  388. * -- http://tools.ietf.org/html/rfc4253#section-7.2
  389. *
  390. * @see Net_SSH2::_key_exchange()
  391. * @var String
  392. * @access private
  393. */
  394. var $session_id = false;
  395. /**
  396. * Exchange hash
  397. *
  398. * The current exchange hash
  399. *
  400. * @see Net_SSH2::_key_exchange()
  401. * @var String
  402. * @access private
  403. */
  404. var $exchange_hash = false;
  405. /**
  406. * Message Numbers
  407. *
  408. * @see Net_SSH2::Net_SSH2()
  409. * @var Array
  410. * @access private
  411. */
  412. var $message_numbers = array();
  413. /**
  414. * Disconnection Message 'reason codes' defined in RFC4253
  415. *
  416. * @see Net_SSH2::Net_SSH2()
  417. * @var Array
  418. * @access private
  419. */
  420. var $disconnect_reasons = array();
  421. /**
  422. * SSH_MSG_CHANNEL_OPEN_FAILURE 'reason codes', defined in RFC4254
  423. *
  424. * @see Net_SSH2::Net_SSH2()
  425. * @var Array
  426. * @access private
  427. */
  428. var $channel_open_failure_reasons = array();
  429. /**
  430. * Terminal Modes
  431. *
  432. * @link http://tools.ietf.org/html/rfc4254#section-8
  433. * @see Net_SSH2::Net_SSH2()
  434. * @var Array
  435. * @access private
  436. */
  437. var $terminal_modes = array();
  438. /**
  439. * SSH_MSG_CHANNEL_EXTENDED_DATA's data_type_codes
  440. *
  441. * @link http://tools.ietf.org/html/rfc4254#section-5.2
  442. * @see Net_SSH2::Net_SSH2()
  443. * @var Array
  444. * @access private
  445. */
  446. var $channel_extended_data_type_codes = array();
  447. /**
  448. * Send Sequence Number
  449. *
  450. * See 'Section 6.4. Data Integrity' of rfc4253 for more info.
  451. *
  452. * @see Net_SSH2::_send_binary_packet()
  453. * @var Integer
  454. * @access private
  455. */
  456. var $send_seq_no = 0;
  457. /**
  458. * Get Sequence Number
  459. *
  460. * See 'Section 6.4. Data Integrity' of rfc4253 for more info.
  461. *
  462. * @see Net_SSH2::_get_binary_packet()
  463. * @var Integer
  464. * @access private
  465. */
  466. var $get_seq_no = 0;
  467. /**
  468. * Server Channels
  469. *
  470. * Maps client channels to server channels
  471. *
  472. * @see Net_SSH2::_get_channel_packet()
  473. * @see Net_SSH2::exec()
  474. * @var Array
  475. * @access private
  476. */
  477. var $server_channels = array();
  478. /**
  479. * Channel Buffers
  480. *
  481. * If a client requests a packet from one channel but receives two packets from another those packets should
  482. * be placed in a buffer
  483. *
  484. * @see Net_SSH2::_get_channel_packet()
  485. * @see Net_SSH2::exec()
  486. * @var Array
  487. * @access private
  488. */
  489. var $channel_buffers = array();
  490. /**
  491. * Channel Status
  492. *
  493. * Contains the type of the last sent message
  494. *
  495. * @see Net_SSH2::_get_channel_packet()
  496. * @var Array
  497. * @access private
  498. */
  499. var $channel_status = array();
  500. /**
  501. * Packet Size
  502. *
  503. * Maximum packet size indexed by channel
  504. *
  505. * @see Net_SSH2::_send_channel_packet()
  506. * @var Array
  507. * @access private
  508. */
  509. var $packet_size_client_to_server = array();
  510. /**
  511. * Message Number Log
  512. *
  513. * @see Net_SSH2::getLog()
  514. * @var Array
  515. * @access private
  516. */
  517. var $message_number_log = array();
  518. /**
  519. * Message Log
  520. *
  521. * @see Net_SSH2::getLog()
  522. * @var Array
  523. * @access private
  524. */
  525. var $message_log = array();
  526. /**
  527. * The Window Size
  528. *
  529. * Bytes the other party can send before it must wait for the window to be adjusted (0x7FFFFFFF = 4GB)
  530. *
  531. * @var Integer
  532. * @see Net_SSH2::_send_channel_packet()
  533. * @see Net_SSH2::exec()
  534. * @access private
  535. */
  536. var $window_size = 0x7FFFFFFF;
  537. /**
  538. * Window size
  539. *
  540. * Window size indexed by channel
  541. *
  542. * @see Net_SSH2::_send_channel_packet()
  543. * @var Array
  544. * @access private
  545. */
  546. var $window_size_client_to_server = array();
  547. /**
  548. * Server signature
  549. *
  550. * Verified against $this->session_id
  551. *
  552. * @see Net_SSH2::getServerPublicHostKey()
  553. * @var String
  554. * @access private
  555. */
  556. var $signature = '';
  557. /**
  558. * Server signature format
  559. *
  560. * ssh-rsa or ssh-dss.
  561. *
  562. * @see Net_SSH2::getServerPublicHostKey()
  563. * @var String
  564. * @access private
  565. */
  566. var $signature_format = '';
  567. /**
  568. * Interactive Buffer
  569. *
  570. * @see Net_SSH2::read()
  571. * @var Array
  572. * @access private
  573. */
  574. var $interactiveBuffer = '';
  575. /**
  576. * Current log size
  577. *
  578. * Should never exceed NET_SSH2_LOG_MAX_SIZE
  579. *
  580. * @see Net_SSH2::_send_binary_packet()
  581. * @see Net_SSH2::_get_binary_packet()
  582. * @var Integer
  583. * @access private
  584. */
  585. var $log_size;
  586. /**
  587. * Timeout
  588. *
  589. * @see Net_SSH2::setTimeout()
  590. * @access private
  591. */
  592. var $timeout;
  593. /**
  594. * Current Timeout
  595. *
  596. * @see Net_SSH2::_get_channel_packet()
  597. * @access private
  598. */
  599. var $curTimeout;
  600. /**
  601. * Real-time log file pointer
  602. *
  603. * @see Net_SSH2::_append_log()
  604. * @access private
  605. */
  606. var $realtime_log_file;
  607. /**
  608. * Real-time log file size
  609. *
  610. * @see Net_SSH2::_append_log()
  611. * @access private
  612. */
  613. var $realtime_log_size;
  614. /**
  615. * Has the signature been validated?
  616. *
  617. * @see Net_SSH2::getServerPublicHostKey()
  618. * @access private
  619. */
  620. var $signature_validated = false;
  621. /**
  622. * Real-time log file wrap boolean
  623. *
  624. * @see Net_SSH2::_append_log()
  625. * @access private
  626. */
  627. var $realtime_log_wrap;
  628. /**
  629. * Default Constructor.
  630. *
  631. * Connects to an SSHv2 server
  632. *
  633. * @param String $host
  634. * @param optional Integer $port
  635. * @param optional Integer $timeout
  636. * @return Net_SSH2
  637. * @access public
  638. */
  639. function Net_SSH2($host, $port = 22, $timeout = 10)
  640. {
  641. $this->message_numbers = array(
  642. 1 => 'NET_SSH2_MSG_DISCONNECT',
  643. 2 => 'NET_SSH2_MSG_IGNORE',
  644. 3 => 'NET_SSH2_MSG_UNIMPLEMENTED',
  645. 4 => 'NET_SSH2_MSG_DEBUG',
  646. 5 => 'NET_SSH2_MSG_SERVICE_REQUEST',
  647. 6 => 'NET_SSH2_MSG_SERVICE_ACCEPT',
  648. 20 => 'NET_SSH2_MSG_KEXINIT',
  649. 21 => 'NET_SSH2_MSG_NEWKEYS',
  650. 30 => 'NET_SSH2_MSG_KEXDH_INIT',
  651. 31 => 'NET_SSH2_MSG_KEXDH_REPLY',
  652. 50 => 'NET_SSH2_MSG_USERAUTH_REQUEST',
  653. 51 => 'NET_SSH2_MSG_USERAUTH_FAILURE',
  654. 52 => 'NET_SSH2_MSG_USERAUTH_SUCCESS',
  655. 53 => 'NET_SSH2_MSG_USERAUTH_BANNER',
  656. 80 => 'NET_SSH2_MSG_GLOBAL_REQUEST',
  657. 81 => 'NET_SSH2_MSG_REQUEST_SUCCESS',
  658. 82 => 'NET_SSH2_MSG_REQUEST_FAILURE',
  659. 90 => 'NET_SSH2_MSG_CHANNEL_OPEN',
  660. 91 => 'NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION',
  661. 92 => 'NET_SSH2_MSG_CHANNEL_OPEN_FAILURE',
  662. 93 => 'NET_SSH2_MSG_CHANNEL_WINDOW_ADJUST',
  663. 94 => 'NET_SSH2_MSG_CHANNEL_DATA',
  664. 95 => 'NET_SSH2_MSG_CHANNEL_EXTENDED_DATA',
  665. 96 => 'NET_SSH2_MSG_CHANNEL_EOF',
  666. 97 => 'NET_SSH2_MSG_CHANNEL_CLOSE',
  667. 98 => 'NET_SSH2_MSG_CHANNEL_REQUEST',
  668. 99 => 'NET_SSH2_MSG_CHANNEL_SUCCESS',
  669. 100 => 'NET_SSH2_MSG_CHANNEL_FAILURE'
  670. );
  671. $this->disconnect_reasons = array(
  672. 1 => 'NET_SSH2_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT',
  673. 2 => 'NET_SSH2_DISCONNECT_PROTOCOL_ERROR',
  674. 3 => 'NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED',
  675. 4 => 'NET_SSH2_DISCONNECT_RESERVED',
  676. 5 => 'NET_SSH2_DISCONNECT_MAC_ERROR',
  677. 6 => 'NET_SSH2_DISCONNECT_COMPRESSION_ERROR',
  678. 7 => 'NET_SSH2_DISCONNECT_SERVICE_NOT_AVAILABLE',
  679. 8 => 'NET_SSH2_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED',
  680. 9 => 'NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE',
  681. 10 => 'NET_SSH2_DISCONNECT_CONNECTION_LOST',
  682. 11 => 'NET_SSH2_DISCONNECT_BY_APPLICATION',
  683. 12 => 'NET_SSH2_DISCONNECT_TOO_MANY_CONNECTIONS',
  684. 13 => 'NET_SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER',
  685. 14 => 'NET_SSH2_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE',
  686. 15 => 'NET_SSH2_DISCONNECT_ILLEGAL_USER_NAME'
  687. );
  688. $this->channel_open_failure_reasons = array(
  689. 1 => 'NET_SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED'
  690. );
  691. $this->terminal_modes = array(
  692. 0 => 'NET_SSH2_TTY_OP_END'
  693. );
  694. $this->channel_extended_data_type_codes = array(
  695. 1 => 'NET_SSH2_EXTENDED_DATA_STDERR'
  696. );
  697. $this->_define_array(
  698. $this->message_numbers,
  699. $this->disconnect_reasons,
  700. $this->channel_open_failure_reasons,
  701. $this->terminal_modes,
  702. $this->channel_extended_data_type_codes,
  703. array(60 => 'NET_SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ'),
  704. array(60 => 'NET_SSH2_MSG_USERAUTH_PK_OK'),
  705. array(60 => 'NET_SSH2_MSG_USERAUTH_INFO_REQUEST',
  706. 61 => 'NET_SSH2_MSG_USERAUTH_INFO_RESPONSE')
  707. );
  708. $start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838
  709. $this->fsock = @fsockopen($host, $port, $errno, $errstr, $timeout);
  710. if (!$this->fsock) {
  711. user_error(rtrim("Cannot connect to $host. Error $errno. $errstr"), E_USER_NOTICE);
  712. return;
  713. }
  714. $elapsed = strtok(microtime(), ' ') + strtok('') - $start;
  715. if ($timeout - $elapsed <= 0) {
  716. user_error(rtrim("Cannot connect to $host. Timeout error"), E_USER_NOTICE);
  717. return;
  718. }
  719. $read = array($this->fsock);
  720. $write = $except = NULL;
  721. stream_set_blocking($this->fsock, false);
  722. // on windows this returns a "Warning: Invalid CRT parameters detected" error
  723. if (!@stream_select($read, $write, $except, $timeout - $elapsed)) {
  724. user_error(rtrim("Cannot connect to $host. Banner timeout"), E_USER_NOTICE);
  725. return;
  726. }
  727. stream_set_blocking($this->fsock, true);
  728. /* According to the SSH2 specs,
  729. "The server MAY send other lines of data before sending the version
  730. string. Each line SHOULD be terminated by a Carriage Return and Line
  731. Feed. Such lines MUST NOT begin with "SSH-", and SHOULD be encoded
  732. in ISO-10646 UTF-8 [RFC3629] (language is not specified). Clients
  733. MUST be able to process such lines." */
  734. $temp = '';
  735. $extra = '';
  736. while (!feof($this->fsock) && !preg_match('#^SSH-(\d\.\d+)#', $temp, $matches)) {
  737. if (substr($temp, -2) == "\r\n") {
  738. $extra.= $temp;
  739. $temp = '';
  740. }
  741. $temp.= fgets($this->fsock, 255);
  742. }
  743. if (feof($this->fsock)) {
  744. user_error('Connection closed by server', E_USER_NOTICE);
  745. return false;
  746. }
  747. $ext = array();
  748. if (extension_loaded('mcrypt')) {
  749. $ext[] = 'mcrypt';
  750. }
  751. if (extension_loaded('gmp')) {
  752. $ext[] = 'gmp';
  753. } else if (extension_loaded('bcmath')) {
  754. $ext[] = 'bcmath';
  755. }
  756. if (!empty($ext)) {
  757. $this->identifier.= ' (' . implode(', ', $ext) . ')';
  758. }
  759. if (defined('NET_SSH2_LOGGING')) {
  760. $this->message_number_log[] = '<-';
  761. $this->message_number_log[] = '->';
  762. if (NET_SSH2_LOGGING == NET_SSH2_LOG_COMPLEX) {
  763. $this->message_log[] = $temp;
  764. $this->message_log[] = $this->identifier . "\r\n";
  765. }
  766. }
  767. $this->server_identifier = trim($temp, "\r\n");
  768. if (!empty($extra)) {
  769. $this->errors[] = utf8_decode($extra);
  770. }
  771. if ($matches[1] != '1.99' && $matches[1] != '2.0') {
  772. user_error("Cannot connect to SSH $matches[1] servers", E_USER_NOTICE);
  773. return;
  774. }
  775. fputs($this->fsock, $this->identifier . "\r\n");
  776. $response = $this->_get_binary_packet();
  777. if ($response === false) {
  778. user_error('Connection closed by server', E_USER_NOTICE);
  779. return;
  780. }
  781. if (ord($response[0]) != NET_SSH2_MSG_KEXINIT) {
  782. user_error('Expected SSH_MSG_KEXINIT', E_USER_NOTICE);
  783. return;
  784. }
  785. if (!$this->_key_exchange($response)) {
  786. return;
  787. }
  788. $this->bitmap = NET_SSH2_MASK_CONSTRUCTOR;
  789. }
  790. /**
  791. * Key Exchange
  792. *
  793. * @param String $kexinit_payload_server
  794. * @access private
  795. */
  796. function _key_exchange($kexinit_payload_server)
  797. {
  798. static $kex_algorithms = array(
  799. 'diffie-hellman-group1-sha1', // REQUIRED
  800. 'diffie-hellman-group14-sha1' // REQUIRED
  801. );
  802. static $server_host_key_algorithms = array(
  803. 'ssh-rsa', // RECOMMENDED sign Raw RSA Key
  804. 'ssh-dss' // REQUIRED sign Raw DSS Key
  805. );
  806. static $encryption_algorithms = array(
  807. // from <http://tools.ietf.org/html/rfc4345#section-4>:
  808. 'arcfour256',
  809. 'arcfour128',
  810. 'arcfour', // OPTIONAL the ARCFOUR stream cipher with a 128-bit key
  811. 'aes128-cbc', // RECOMMENDED AES with a 128-bit key
  812. 'aes192-cbc', // OPTIONAL AES with a 192-bit key
  813. 'aes256-cbc', // OPTIONAL AES in CBC mode, with a 256-bit key
  814. // from <http://tools.ietf.org/html/rfc4344#section-4>:
  815. 'aes128-ctr', // RECOMMENDED AES (Rijndael) in SDCTR mode, with 128-bit key
  816. 'aes192-ctr', // RECOMMENDED AES with 192-bit key
  817. 'aes256-ctr', // RECOMMENDED AES with 256-bit key
  818. '3des-ctr', // RECOMMENDED Three-key 3DES in SDCTR mode
  819. '3des-cbc', // REQUIRED three-key 3DES in CBC mode
  820. 'none' // OPTIONAL no encryption; NOT RECOMMENDED
  821. );
  822. static $mac_algorithms = array(
  823. 'hmac-sha1-96', // RECOMMENDED first 96 bits of HMAC-SHA1 (digest length = 12, key length = 20)
  824. 'hmac-sha1', // REQUIRED HMAC-SHA1 (digest length = key length = 20)
  825. 'hmac-md5-96', // OPTIONAL first 96 bits of HMAC-MD5 (digest length = 12, key length = 16)
  826. 'hmac-md5', // OPTIONAL HMAC-MD5 (digest length = key length = 16)
  827. 'none' // OPTIONAL no MAC; NOT RECOMMENDED
  828. );
  829. static $compression_algorithms = array(
  830. 'none' // REQUIRED no compression
  831. //'zlib' // OPTIONAL ZLIB (LZ77) compression
  832. );
  833. static $str_kex_algorithms, $str_server_host_key_algorithms,
  834. $encryption_algorithms_server_to_client, $mac_algorithms_server_to_client, $compression_algorithms_server_to_client,
  835. $encryption_algorithms_client_to_server, $mac_algorithms_client_to_server, $compression_algorithms_client_to_server;
  836. if (empty($str_kex_algorithms)) {
  837. $str_kex_algorithms = implode(',', $kex_algorithms);
  838. $str_server_host_key_algorithms = implode(',', $server_host_key_algorithms);
  839. $encryption_algorithms_server_to_client = $encryption_algorithms_client_to_server = implode(',', $encryption_algorithms);
  840. $mac_algorithms_server_to_client = $mac_algorithms_client_to_server = implode(',', $mac_algorithms);
  841. $compression_algorithms_server_to_client = $compression_algorithms_client_to_server = implode(',', $compression_algorithms);
  842. }
  843. $client_cookie = '';
  844. for ($i = 0; $i < 16; $i++) {
  845. $client_cookie.= chr(crypt_random(0, 255));
  846. }
  847. $response = $kexinit_payload_server;
  848. $this->_string_shift($response, 1); // skip past the message number (it should be SSH_MSG_KEXINIT)
  849. $server_cookie = $this->_string_shift($response, 16);
  850. $temp = unpack('Nlength', $this->_string_shift($response, 4));
  851. $this->kex_algorithms = explode(',', $this->_string_shift($response, $temp['length']));
  852. $temp = unpack('Nlength', $this->_string_shift($response, 4));
  853. $this->server_host_key_algorithms = explode(',', $this->_string_shift($response, $temp['length']));
  854. $temp = unpack('Nlength', $this->_string_shift($response, 4));
  855. $this->encryption_algorithms_client_to_server = explode(',', $this->_string_shift($response, $temp['length']));
  856. $temp = unpack('Nlength', $this->_string_shift($response, 4));
  857. $this->encryption_algorithms_server_to_client = explode(',', $this->_string_shift($response, $temp['length']));
  858. $temp = unpack('Nlength', $this->_string_shift($response, 4));
  859. $this->mac_algorithms_client_to_server = explode(',', $this->_string_shift($response, $temp['length']));
  860. $temp = unpack('Nlength', $this->_string_shift($response, 4));
  861. $this->mac_algorithms_server_to_client = explode(',', $this->_string_shift($response, $temp['length']));
  862. $temp = unpack('Nlength', $this->_string_shift($response, 4));
  863. $this->compression_algorithms_client_to_server = explode(',', $this->_string_shift($response, $temp['length']));
  864. $temp = unpack('Nlength', $this->_string_shift($response, 4));
  865. $this->compression_algorithms_server_to_client = explode(',', $this->_string_shift($response, $temp['length']));
  866. $temp = unpack('Nlength', $this->_string_shift($response, 4));
  867. $this->languages_client_to_server = explode(',', $this->_string_shift($response, $temp['length']));
  868. $temp = unpack('Nlength', $this->_string_shift($response, 4));
  869. $this->languages_server_to_client = explode(',', $this->_string_shift($response, $temp['length']));
  870. extract(unpack('Cfirst_kex_packet_follows', $this->_string_shift($response, 1)));
  871. $first_kex_packet_follows = $first_kex_packet_follows != 0;
  872. // the sending of SSH2_MSG_KEXINIT could go in one of two places. this is the second place.
  873. $kexinit_payload_client = pack('Ca*Na*Na*Na*Na*Na*Na*Na*Na*Na*Na*CN',
  874. NET_SSH2_MSG_KEXINIT, $client_cookie, strlen($str_kex_algorithms), $str_kex_algorithms,
  875. strlen($str_server_host_key_algorithms), $str_server_host_key_algorithms, strlen($encryption_algorithms_client_to_server),
  876. $encryption_algorithms_client_to_server, strlen($encryption_algorithms_server_to_client), $encryption_algorithms_server_to_client,
  877. strlen($mac_algorithms_client_to_server), $mac_algorithms_client_to_server, strlen($mac_algorithms_server_to_client),
  878. $mac_algorithms_server_to_client, strlen($compression_algorithms_client_to_server), $compression_algorithms_client_to_server,
  879. strlen($compression_algorithms_server_to_client), $compression_algorithms_server_to_client, 0, '', 0, '',
  880. 0, 0
  881. );
  882. if (!$this->_send_binary_packet($kexinit_payload_client)) {
  883. return false;
  884. }
  885. // here ends the second place.
  886. // we need to decide upon the symmetric encryption algorithms before we do the diffie-hellman key exchange
  887. for ($i = 0; $i < count($encryption_algorithms) && !in_array($encryption_algorithms[$i], $this->encryption_algorithms_server_to_client); $i++);
  888. if ($i == count($encryption_algorithms)) {
  889. user_error('No compatible server to client encryption algorithms found', E_USER_NOTICE);
  890. return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
  891. }
  892. // we don't initialize any crypto-objects, yet - we do that, later. for now, we need the lengths to make the
  893. // diffie-hellman key exchange as fast as possible
  894. $decrypt = $encryption_algorithms[$i];
  895. switch ($decrypt) {
  896. case '3des-cbc':
  897. case '3des-ctr':
  898. $decryptKeyLength = 24; // eg. 192 / 8
  899. break;
  900. case 'aes256-cbc':
  901. case 'aes256-ctr':
  902. $decryptKeyLength = 32; // eg. 256 / 8
  903. break;
  904. case 'aes192-cbc':
  905. case 'aes192-ctr':
  906. $decryptKeyLength = 24; // eg. 192 / 8
  907. break;
  908. case 'aes128-cbc':
  909. case 'aes128-ctr':
  910. $decryptKeyLength = 16; // eg. 128 / 8
  911. break;
  912. case 'arcfour':
  913. case 'arcfour128':
  914. $decryptKeyLength = 16; // eg. 128 / 8
  915. break;
  916. case 'arcfour256':
  917. $decryptKeyLength = 32; // eg. 128 / 8
  918. break;
  919. case 'none';
  920. $decryptKeyLength = 0;
  921. }
  922. for ($i = 0; $i < count($encryption_algorithms) && !in_array($encryption_algorithms[$i], $this->encryption_algorithms_client_to_server); $i++);
  923. if ($i == count($encryption_algorithms)) {
  924. user_error('No compatible client to server encryption algorithms found', E_USER_NOTICE);
  925. return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
  926. }
  927. $encrypt = $encryption_algorithms[$i];
  928. switch ($encrypt) {
  929. case '3des-cbc':
  930. case '3des-ctr':
  931. $encryptKeyLength = 24;
  932. break;
  933. case 'aes256-cbc':
  934. case 'aes256-ctr':
  935. $encryptKeyLength = 32;
  936. break;
  937. case 'aes192-cbc':
  938. case 'aes192-ctr':
  939. $encryptKeyLength = 24;
  940. break;
  941. case 'aes128-cbc':
  942. case 'aes128-ctr':
  943. $encryptKeyLength = 16;
  944. break;
  945. case 'arcfour':
  946. case 'arcfour128':
  947. $encryptKeyLength = 16;
  948. break;
  949. case 'arcfour256':
  950. $encryptKeyLength = 32;
  951. break;
  952. case 'none';
  953. $encryptKeyLength = 0;
  954. }
  955. $keyLength = $decryptKeyLength > $encryptKeyLength ? $decryptKeyLength : $encryptKeyLength;
  956. // through diffie-hellman key exchange a symmetric key is obtained
  957. for ($i = 0; $i < count($kex_algorithms) && !in_array($kex_algorithms[$i], $this->kex_algorithms); $i++);
  958. if ($i == count($kex_algorithms)) {
  959. user_error('No compatible key exchange algorithms found', E_USER_NOTICE);
  960. return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
  961. }
  962. switch ($kex_algorithms[$i]) {
  963. // see http://tools.ietf.org/html/rfc2409#section-6.2 and
  964. // http://tools.ietf.org/html/rfc2412, appendex E
  965. case 'diffie-hellman-group1-sha1':
  966. $p = pack('H256', 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' .
  967. '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' .
  968. '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' .
  969. 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF');
  970. $keyLength = $keyLength < 160 ? $keyLength : 160;
  971. $hash = 'sha1';
  972. break;
  973. // see http://tools.ietf.org/html/rfc3526#section-3
  974. case 'diffie-hellman-group14-sha1':
  975. $p = pack('H512', 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' .
  976. '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' .
  977. '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' .
  978. 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05' .
  979. '98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB' .
  980. '9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B' .
  981. 'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718' .
  982. '3995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF');
  983. $keyLength = $keyLength < 160 ? $keyLength : 160;
  984. $hash = 'sha1';
  985. }
  986. $p = new Math_BigInteger($p, 256);
  987. //$q = $p->bitwise_rightShift(1);
  988. /* To increase the speed of the key exchange, both client and server may
  989. reduce the size of their private exponents. It should be at least
  990. twice as long as the key material that is generated from the shared
  991. secret. For more details, see the paper by van Oorschot and Wiener
  992. [VAN-OORSCHOT].
  993. -- http://tools.ietf.org/html/rfc4419#section-6.2 */
  994. $q = new Math_BigInteger(1);
  995. $q = $q->bitwise_leftShift(2 * $keyLength);
  996. $q = $q->subtract(new Math_BigInteger(1));
  997. $g = new Math_BigInteger(2);
  998. $x = new Math_BigInteger();
  999. $x->setRandomGenerator('crypt_random');
  1000. $x = $x->random(new Math_BigInteger(1), $q);
  1001. $e = $g->modPow($x, $p);
  1002. $eBytes = $e->toBytes(true);
  1003. $data = pack('CNa*', NET_SSH2_MSG_KEXDH_INIT, strlen($eBytes), $eBytes);
  1004. if (!$this->_send_binary_packet($data)) {
  1005. user_error('Connection closed by server', E_USER_NOTICE);
  1006. return false;
  1007. }
  1008. $response = $this->_get_binary_packet();
  1009. if ($response === false) {
  1010. user_error('Connection closed by server', E_USER_NOTICE);
  1011. return false;
  1012. }
  1013. extract(unpack('Ctype', $this->_string_shift($response, 1)));
  1014. if ($type != NET_SSH2_MSG_KEXDH_REPLY) {
  1015. user_error('Expected SSH_MSG_KEXDH_REPLY', E_USER_NOTICE);
  1016. return false;
  1017. }
  1018. $temp = unpack('Nlength', $this->_string_shift($response, 4));
  1019. $this->server_public_host_key = $server_public_host_key = $this->_string_shift($response, $temp['length']);
  1020. $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
  1021. $public_key_format = $this->_string_shift($server_public_host_key, $temp['length']);
  1022. $temp = unpack('Nlength', $this->_string_shift($response, 4));
  1023. $fBytes = $this->_string_shift($response, $temp['length']);
  1024. $f = new Math_BigInteger($fBytes, -256);
  1025. $temp = unpack('Nlength', $this->_string_shift($response, 4));
  1026. $this->signature = $this->_string_shift($response, $temp['length']);
  1027. $temp = unpack('Nlength', $this->_string_shift($this->signature, 4));
  1028. $this->signature_format = $this->_string_shift($this->signature, $temp['length']);
  1029. $key = $f->modPow($x, $p);
  1030. $keyBytes = $key->toBytes(true);
  1031. $this->exchange_hash = pack('Na*Na*Na*Na*Na*Na*Na*Na*',
  1032. strlen($this->identifier), $this->identifier, strlen($this->server_identifier), $this->server_identifier,
  1033. strlen($kexinit_payload_client), $kexinit_payload_client, strlen($kexinit_payload_server),
  1034. $kexinit_payload_server, strlen($this->server_public_host_key), $this->server_public_host_key, strlen($eBytes),
  1035. $eBytes, strlen($fBytes), $fBytes, strlen($keyBytes), $keyBytes
  1036. );
  1037. $this->exchange_hash = pack('H*', $hash($this->exchange_hash));
  1038. if ($this->session_id === false) {
  1039. $this->session_id = $this->exchange_hash;
  1040. }
  1041. for ($i = 0; $i < count($server_host_key_algorithms) && !in_array($server_host_key_algorithms[$i], $this->server_host_key_algorithms); $i++);
  1042. if ($i == count($server_host_key_algorithms)) {
  1043. user_error('No compatible server host key algorithms found', E_USER_NOTICE);
  1044. return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
  1045. }
  1046. if ($public_key_format != $server_host_key_algorithms[$i] || $this->signature_format != $server_host_key_algorithms[$i]) {
  1047. user_error('Sever Host Key Algorithm Mismatch', E_USER_NOTICE);
  1048. return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
  1049. }
  1050. $packet = pack('C',
  1051. NET_SSH2_MSG_NEWKEYS
  1052. );
  1053. if (!$this->_send_binary_packet($packet)) {
  1054. return false;
  1055. }
  1056. $response = $this->_get_binary_packet();
  1057. if ($response === false) {
  1058. user_error('Connection closed by server', E_USER_NOTICE);
  1059. return false;
  1060. }
  1061. extract(unpack('Ctype', $this->_string_shift($response, 1)));
  1062. if ($type != NET_SSH2_MSG_NEWKEYS) {
  1063. user_error('Expected SSH_MSG_NEWKEYS', E_USER_NOTICE);
  1064. return false;
  1065. }
  1066. switch ($encrypt) {
  1067. case '3des-cbc':
  1068. $this->encrypt = new Crypt_TripleDES();
  1069. // $this->encrypt_block_size = 64 / 8 == the default
  1070. break;
  1071. case '3des-ctr':
  1072. $this->encrypt = new Crypt_TripleDES(CRYPT_DES_MODE_CTR);
  1073. // $this->encrypt_block_size = 64 / 8 == the default
  1074. break;
  1075. case 'aes256-cbc':
  1076. case 'aes192-cbc':
  1077. case 'aes128-cbc':
  1078. $this->encrypt = new Crypt_AES();
  1079. $this->encrypt_block_size = 16; // eg. 128 / 8
  1080. break;
  1081. case 'aes256-ctr':
  1082. case 'aes192-ctr':
  1083. case 'aes128-ctr':
  1084. $this->encrypt = new Crypt_AES(CRYPT_AES_MODE_CTR);
  1085. $this->encrypt_block_size = 16; // eg. 128 / 8
  1086. break;
  1087. case 'arcfour':
  1088. case 'arcfour128':
  1089. case 'arcfour256':
  1090. $this->encrypt = new Crypt_RC4();
  1091. break;
  1092. case 'none';
  1093. //$this->encrypt = new Crypt_Null();
  1094. }
  1095. switch ($decrypt) {
  1096. case '3des-cbc':
  1097. $this->decrypt = new Crypt_TripleDES();
  1098. break;
  1099. case '3des-ctr':
  1100. $this->decrypt = new Crypt_TripleDES(CRYPT_DES_MODE_CTR);
  1101. break;
  1102. case 'aes256-cbc':
  1103. case 'aes192-cbc':
  1104. case 'aes128-cbc':
  1105. $this->decrypt = new Crypt_AES();
  1106. $this->decrypt_block_size = 16;
  1107. break;
  1108. case 'aes256-ctr':
  1109. case 'aes192-ctr':
  1110. case 'aes128-ctr':
  1111. $this->decrypt = new Crypt_AES(CRYPT_AES_MODE_CTR);
  1112. $this->decrypt_block_size = 16;
  1113. break;
  1114. case 'arcfour':
  1115. case 'arcfour128':
  1116. case 'arcfour256':
  1117. $this->decrypt = new Crypt_RC4();
  1118. break;
  1119. case 'none';
  1120. //$this->decrypt = new Crypt_Null();
  1121. }
  1122. $keyBytes = pack('Na*', strlen($keyBytes), $keyBytes);
  1123. if ($this->encrypt) {
  1124. $this->encrypt->enableContinuousBuffer();
  1125. $this->encrypt->disablePadding();
  1126. $iv = pack('H*', $hash($keyBytes . $this->exchange_hash . 'A' . $this->session_id));
  1127. while ($this->encrypt_block_size > strlen($iv)) {
  1128. $iv.= pack('H*', $hash($keyBytes . $this->exchange_hash . $iv));
  1129. }
  1130. $this->encrypt->setIV(substr($iv, 0, $this->encrypt_block_size));
  1131. $key = pack('H*', $hash($keyBytes . $this->exchange_hash . 'C' . $this->session_id));
  1132. while ($encryptKeyLength > strlen($key)) {
  1133. $key.= pack('H*', $hash($keyBytes . $this->exchange_hash . $key));
  1134. }
  1135. $this->encrypt->setKey(substr($key, 0, $encryptKeyLength));
  1136. }
  1137. if ($this->decrypt) {
  1138. $this->decrypt->enableContinuousBuffer();
  1139. $this->decrypt->disablePadding();
  1140. $iv = pack('H*', $hash($keyBytes . $this->exchange_hash . 'B' . $this->session_id));
  1141. while ($this->decrypt_block_size > strlen($iv)) {
  1142. $iv.= pack('H*', $hash($keyBytes . $this->exchange_hash . $iv));
  1143. }
  1144. $this->decrypt->setIV(substr($iv, 0, $this->decrypt_block_size));
  1145. $key = pack('H*', $hash($keyBytes . $this->exchange_hash . 'D' . $this->session_id));
  1146. while ($decryptKeyLength > strlen($key)) {
  1147. $key.= pack('H*', $hash($keyBytes . $this->exchange_hash . $key));
  1148. }
  1149. $this->decrypt->setKey(substr($key, 0, $decryptKeyLength));
  1150. }
  1151. /* The "arcfour128" algorithm is the RC4 cipher, as described in
  1152. [SCHNEIER], using a 128-bit key. The first 1536 bytes of keystream
  1153. generated by the cipher MUST be discarded, and the first byte of the
  1154. first encrypted packet MUST be encrypted using the 1537th byte of
  1155. keystream.
  1156. -- http://tools.ietf.org/html/rfc4345#section-4 */
  1157. if ($encrypt == 'arcfour128' || $encrypt == 'arcfour256') {
  1158. $this->encrypt->encrypt(str_repeat("\0", 1536));
  1159. }
  1160. if ($decrypt == 'arcfour128' || $decrypt == 'arcfour256') {
  1161. $this->decrypt->decrypt(str_repeat("\0", 1536));
  1162. }
  1163. for ($i = 0; $i < count($mac_algorithms) && !in_array($mac_algorithms[$i], $this->mac_algorithms_client_to_server); $i++);
  1164. if ($i == count($mac_algorithms)) {
  1165. user_error('No compatible client to server message authentication algorithms found', E_USER_NOTICE);
  1166. return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
  1167. }
  1168. $createKeyLength = 0; // ie. $mac_algorithms[$i] == 'none'
  1169. switch ($mac_algorithms[$i]) {
  1170. case 'hmac-sha1':
  1171. $this->hmac_create = new Crypt_Hash('sha1');
  1172. $createKeyLength = 20;
  1173. break;
  1174. case 'hmac-sha1-96':
  1175. $this->hmac_create = new Crypt_Hash('sha1-96');
  1176. $createKeyLength = 20;
  1177. break;
  1178. case 'hmac-md5':
  1179. $this->hmac_create = new Crypt_Hash('md5');
  1180. $createKeyLength = 16;
  1181. break;
  1182. case 'hmac-md5-96':
  1183. $this->hmac_create = new Crypt_Hash('md5-96');
  1184. $createKeyLength = 16;
  1185. }
  1186. for ($i = 0; $i < count($mac_algorithms) && !in_array($mac_algorithms[$i], $this->mac_algorithms_server_to_client); $i++);
  1187. if ($i == count($mac_algorithms)) {
  1188. user_error('No compatible server to client message authentication algorithms found', E_USER_NOTICE);
  1189. return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
  1190. }
  1191. $checkKeyLength = 0;
  1192. $this->hmac_size = 0;
  1193. switch ($mac_algorithms[$i]) {
  1194. case 'hmac-sha1':
  1195. $this->hmac_check = new Crypt_Hash('sha1');
  1196. $checkKeyLength = 20;
  1197. $this->hmac_size = 20;
  1198. break;
  1199. case 'hmac-sha1-96':
  1200. $this->hmac_check = new Crypt_Hash('sha1-96');
  1201. $checkKeyLength = 20;
  1202. $this->hmac_size = 12;
  1203. break;
  1204. case 'hmac-md5':
  1205. $this->hmac_check = new Crypt_Hash('md5');
  1206. $checkKeyLength = 16;
  1207. $this->hmac_size = 16;
  1208. break;
  1209. case 'hmac-md5-96':
  1210. $this->hmac_check = new Crypt_Hash('md5-96');
  1211. $checkKeyLength = 16;
  1212. $this->hmac_size = 12;
  1213. }
  1214. $key = pack('H*', $hash($keyBytes . $this->exchange_hash . 'E' . $this->session_id));
  1215. while ($createKeyLength > strlen($key)) {
  1216. $key.= pack('H*', $hash($keyBytes . $this->exchange_hash . $key));
  1217. }
  1218. $this->hmac_create->setKey(substr($key, 0, $createKeyLength));
  1219. $key = pack('H*', $hash($keyBytes . $this->exchange_hash . 'F' . $this->session_id));
  1220. while ($checkKeyLength > strlen($key)) {
  1221. $key.= pack('H*', $hash($keyBytes . $this->exchange_hash . $key));
  1222. }
  1223. $this->hmac_check->setKey(substr($key, 0, $checkKeyLength));
  1224. for ($i = 0; $i < count($compression_algorithms) && !in_array($compression_algorithms[$i], $this->compression_algorithms_server_to_client); $i++);
  1225. if ($i == count($compression_algorithms)) {
  1226. user_error('No compatible server to client compression algorithms found', E_USER_NOTICE);
  1227. return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
  1228. }
  1229. $this->decompress = $compression_algorithms[$i] == 'zlib';
  1230. for ($i = 0; $i < count($compression_algorithms) && !in_array($compression_algorithms[$i], $this->compression_algorithms_client_to_server); $i++);
  1231. if ($i == count($compression_algorithms)) {
  1232. user_error('No compatible client to server compression algorithms found', E_USER_NOTICE);
  1233. return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
  1234. }
  1235. $this->compress = $compression_algorithms[$i] == 'zlib';
  1236. return true;
  1237. }
  1238. /**
  1239. * Login
  1240. *
  1241. * The $password parameter can be a plaintext password or a Crypt_RSA object.
  1242. *
  1243. * @param String $username
  1244. * @param optional String $password
  1245. * @return Boolean
  1246. * @access public
  1247. * @internal It might be worthwhile, at some point, to protect against {@link http://tools.ietf.org/html/rfc4251#section-9.3.9 traffic analysis}
  1248. * by sending dummy SSH_MSG_IGNORE messages.
  1249. */
  1250. function login($username, $password = '')
  1251. {
  1252. if (!($this->bitmap & NET_SSH2_MASK_CONSTRUCTOR)) {
  1253. return false;
  1254. }
  1255. $packet = pack('CNa*',
  1256. NET_SSH2_MSG_SERVICE_REQUEST, strlen('ssh-userauth'), 'ssh-userauth'
  1257. );
  1258. i

Large files files are truncated, but you can click here to view the full file