PageRenderTime 65ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 1ms

/vendors/phpseclib/Net/SSH2.php

https://bitbucket.org/ttalov/fgcu_pci
PHP | 2902 lines | 1539 code | 348 blank | 1015 comment | 253 complexity | 778117004b5b747467821b7ef7b95e52 MD5 | raw file

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

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

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