ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
SSH1.php
Go to the documentation of this file.
1 <?php
2 
49 namespace phpseclib\Net;
50 
55 
63 class SSH1
64 {
76  const CIPHER_NONE = 0;
82  const CIPHER_IDEA = 1;
86  const CIPHER_DES = 2;
92  const CIPHER_3DES = 3;
99  const CIPHER_BROKEN_TSS = 4;
115  const CIPHER_RC4 = 5;
122  const CIPHER_BLOWFISH = 6;
134  const AUTH_RHOSTS = 1;
138  const AUTH_RSA = 2;
144  const AUTH_PASSWORD = 3;
148  const AUTH_RHOSTS_RSA = 4;
157  const TTY_OP_END = 0;
166  const RESPONSE_TYPE = 1;
167 
174  const RESPONSE_DATA = 2;
175 
182  const MASK_CONSTRUCTOR = 0x00000001;
183  const MASK_CONNECTED = 0x00000002;
184  const MASK_LOGIN = 0x00000004;
185  const MASK_SHELL = 0x00000008;
195  const LOG_SIMPLE = 1;
199  const LOG_COMPLEX = 2;
203  const LOG_REALTIME = 3;
207  const LOG_REALTIME_FILE = 4;
217  const READ_SIMPLE = 1;
221  const READ_REGEX = 2;
230  var $identifier = 'SSH-1.5-phpseclib';
231 
238  var $fsock;
239 
246  var $crypto = false;
247 
257  var $bitmap = 0;
258 
269 
280 
291 
302 
312  var $supported_ciphers = array(
313  self::CIPHER_NONE => 'No encryption',
314  self::CIPHER_IDEA => 'IDEA in CFB mode',
315  self::CIPHER_DES => 'DES in CBC mode',
316  self::CIPHER_3DES => 'Triple-DES in CBC mode',
317  self::CIPHER_BROKEN_TSS => 'TRI\'s Simple Stream encryption CBC',
318  self::CIPHER_RC4 => 'RC4',
319  self::CIPHER_BLOWFISH => 'Blowfish'
320  );
321 
332  self::AUTH_RHOSTS => '.rhosts or /etc/hosts.equiv',
333  self::AUTH_RSA => 'pure RSA authentication',
334  self::AUTH_PASSWORD => 'password authentication',
335  self::AUTH_RHOSTS_RSA => '.rhosts with RSA host authentication'
336  );
337 
346 
354  var $protocol_flags = array();
355 
363  var $protocol_flag_log = array();
364 
372  var $message_log = array();
373 
382 
391 
400 
409 
416  var $timeout;
417 
425 
432  var $log_boundary = ':';
433 
440  var $log_long_width = 65;
441 
449 
458  var $host;
459 
468  var $port;
469 
484 
493  var $cipher;
494 
507  function __construct($host, $port = 22, $timeout = 10, $cipher = self::CIPHER_3DES)
508  {
509  $this->protocol_flags = array(
510  1 => 'NET_SSH1_MSG_DISCONNECT',
511  2 => 'NET_SSH1_SMSG_PUBLIC_KEY',
512  3 => 'NET_SSH1_CMSG_SESSION_KEY',
513  4 => 'NET_SSH1_CMSG_USER',
514  9 => 'NET_SSH1_CMSG_AUTH_PASSWORD',
515  10 => 'NET_SSH1_CMSG_REQUEST_PTY',
516  12 => 'NET_SSH1_CMSG_EXEC_SHELL',
517  13 => 'NET_SSH1_CMSG_EXEC_CMD',
518  14 => 'NET_SSH1_SMSG_SUCCESS',
519  15 => 'NET_SSH1_SMSG_FAILURE',
520  16 => 'NET_SSH1_CMSG_STDIN_DATA',
521  17 => 'NET_SSH1_SMSG_STDOUT_DATA',
522  18 => 'NET_SSH1_SMSG_STDERR_DATA',
523  19 => 'NET_SSH1_CMSG_EOF',
524  20 => 'NET_SSH1_SMSG_EXITSTATUS',
525  33 => 'NET_SSH1_CMSG_EXIT_CONFIRMATION'
526  );
527 
528  $this->_define_array($this->protocol_flags);
529 
530  $this->host = $host;
531  $this->port = $port;
532  $this->connectionTimeout = $timeout;
533  $this->cipher = $cipher;
534  }
535 
542  function _connect()
543  {
544  $this->fsock = @fsockopen($this->host, $this->port, $errno, $errstr, $this->connectionTimeout);
545  if (!$this->fsock) {
546  user_error(rtrim("Cannot connect to {$this->host}:{$this->port}. Error $errno. $errstr"));
547  return false;
548  }
549 
550  $this->server_identification = $init_line = fgets($this->fsock, 255);
551 
552  if (defined('NET_SSH1_LOGGING')) {
553  $this->_append_log('<-', $this->server_identification);
554  $this->_append_log('->', $this->identifier . "\r\n");
555  }
556 
557  if (!preg_match('#SSH-([0-9\.]+)-(.+)#', $init_line, $parts)) {
558  user_error('Can only connect to SSH servers');
559  return false;
560  }
561  if ($parts[1][0] != 1) {
562  user_error("Cannot connect to SSH $parts[1] servers");
563  return false;
564  }
565 
566  fputs($this->fsock, $this->identifier."\r\n");
567 
568  $response = $this->_get_binary_packet();
569  if ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_PUBLIC_KEY) {
570  user_error('Expected SSH_SMSG_PUBLIC_KEY');
571  return false;
572  }
573 
574  $anti_spoofing_cookie = $this->_string_shift($response[self::RESPONSE_DATA], 8);
575 
576  $this->_string_shift($response[self::RESPONSE_DATA], 4);
577 
578  $temp = unpack('nlen', $this->_string_shift($response[self::RESPONSE_DATA], 2));
579  $server_key_public_exponent = new BigInteger($this->_string_shift($response[self::RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
580  $this->server_key_public_exponent = $server_key_public_exponent;
581 
582  $temp = unpack('nlen', $this->_string_shift($response[self::RESPONSE_DATA], 2));
583  $server_key_public_modulus = new BigInteger($this->_string_shift($response[self::RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
584  $this->server_key_public_modulus = $server_key_public_modulus;
585 
586  $this->_string_shift($response[self::RESPONSE_DATA], 4);
587 
588  $temp = unpack('nlen', $this->_string_shift($response[self::RESPONSE_DATA], 2));
589  $host_key_public_exponent = new BigInteger($this->_string_shift($response[self::RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
590  $this->host_key_public_exponent = $host_key_public_exponent;
591 
592  $temp = unpack('nlen', $this->_string_shift($response[self::RESPONSE_DATA], 2));
593  $host_key_public_modulus = new BigInteger($this->_string_shift($response[self::RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
594  $this->host_key_public_modulus = $host_key_public_modulus;
595 
596  $this->_string_shift($response[self::RESPONSE_DATA], 4);
597 
598  // get a list of the supported ciphers
599  extract(unpack('Nsupported_ciphers_mask', $this->_string_shift($response[self::RESPONSE_DATA], 4)));
600  foreach ($this->supported_ciphers as $mask => $name) {
601  if (($supported_ciphers_mask & (1 << $mask)) == 0) {
602  unset($this->supported_ciphers[$mask]);
603  }
604  }
605 
606  // get a list of the supported authentications
607  extract(unpack('Nsupported_authentications_mask', $this->_string_shift($response[self::RESPONSE_DATA], 4)));
608  foreach ($this->supported_authentications as $mask => $name) {
609  if (($supported_authentications_mask & (1 << $mask)) == 0) {
610  unset($this->supported_authentications[$mask]);
611  }
612  }
613 
614  $session_id = pack('H*', md5($host_key_public_modulus->toBytes() . $server_key_public_modulus->toBytes() . $anti_spoofing_cookie));
615 
616  $session_key = Random::string(32);
617  $double_encrypted_session_key = $session_key ^ str_pad($session_id, 32, chr(0));
618 
619  if ($server_key_public_modulus->compare($host_key_public_modulus) < 0) {
620  $double_encrypted_session_key = $this->_rsa_crypt(
621  $double_encrypted_session_key,
622  array(
623  $server_key_public_exponent,
624  $server_key_public_modulus
625  )
626  );
627  $double_encrypted_session_key = $this->_rsa_crypt(
628  $double_encrypted_session_key,
629  array(
630  $host_key_public_exponent,
631  $host_key_public_modulus
632  )
633  );
634  } else {
635  $double_encrypted_session_key = $this->_rsa_crypt(
636  $double_encrypted_session_key,
637  array(
638  $host_key_public_exponent,
639  $host_key_public_modulus
640  )
641  );
642  $double_encrypted_session_key = $this->_rsa_crypt(
643  $double_encrypted_session_key,
644  array(
645  $server_key_public_exponent,
646  $server_key_public_modulus
647  )
648  );
649  }
650 
651  $cipher = isset($this->supported_ciphers[$this->cipher]) ? $this->cipher : self::CIPHER_3DES;
652  $data = pack('C2a*na*N', NET_SSH1_CMSG_SESSION_KEY, $cipher, $anti_spoofing_cookie, 8 * strlen($double_encrypted_session_key), $double_encrypted_session_key, 0);
653 
654  if (!$this->_send_binary_packet($data)) {
655  user_error('Error sending SSH_CMSG_SESSION_KEY');
656  return false;
657  }
658 
659  switch ($cipher) {
660  //case self::CIPHER_NONE:
661  // $this->crypto = new \phpseclib\Crypt\Null();
662  // break;
663  case self::CIPHER_DES:
664  $this->crypto = new DES();
665  $this->crypto->disablePadding();
666  $this->crypto->enableContinuousBuffer();
667  $this->crypto->setKey(substr($session_key, 0, 8));
668  break;
669  case self::CIPHER_3DES:
670  $this->crypto = new TripleDES(TripleDES::MODE_3CBC);
671  $this->crypto->disablePadding();
672  $this->crypto->enableContinuousBuffer();
673  $this->crypto->setKey(substr($session_key, 0, 24));
674  break;
675  //case self::CIPHER_RC4:
676  // $this->crypto = new RC4();
677  // $this->crypto->enableContinuousBuffer();
678  // $this->crypto->setKey(substr($session_key, 0, 16));
679  // break;
680  }
681 
682  $response = $this->_get_binary_packet();
683 
684  if ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) {
685  user_error('Expected SSH_SMSG_SUCCESS');
686  return false;
687  }
688 
689  $this->bitmap = self::MASK_CONNECTED;
690 
691  return true;
692  }
693 
702  function login($username, $password = '')
703  {
704  if (!($this->bitmap & self::MASK_CONSTRUCTOR)) {
705  $this->bitmap |= self::MASK_CONSTRUCTOR;
706  if (!$this->_connect()) {
707  return false;
708  }
709  }
710 
711  if (!($this->bitmap & self::MASK_CONNECTED)) {
712  return false;
713  }
714 
715  $data = pack('CNa*', NET_SSH1_CMSG_USER, strlen($username), $username);
716 
717  if (!$this->_send_binary_packet($data)) {
718  user_error('Error sending SSH_CMSG_USER');
719  return false;
720  }
721 
722  $response = $this->_get_binary_packet();
723 
724  if ($response === true) {
725  return false;
726  }
727  if ($response[self::RESPONSE_TYPE] == NET_SSH1_SMSG_SUCCESS) {
728  $this->bitmap |= self::MASK_LOGIN;
729  return true;
730  } elseif ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_FAILURE) {
731  user_error('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE');
732  return false;
733  }
734 
735  $data = pack('CNa*', NET_SSH1_CMSG_AUTH_PASSWORD, strlen($password), $password);
736 
737  if (!$this->_send_binary_packet($data)) {
738  user_error('Error sending SSH_CMSG_AUTH_PASSWORD');
739  return false;
740  }
741 
742  // remove the username and password from the last logged packet
743  if (defined('NET_SSH1_LOGGING') && NET_SSH1_LOGGING == self::LOG_COMPLEX) {
744  $data = pack('CNa*', NET_SSH1_CMSG_AUTH_PASSWORD, strlen('password'), 'password');
745  $this->message_log[count($this->message_log) - 1] = $data;
746  }
747 
748  $response = $this->_get_binary_packet();
749 
750  if ($response === true) {
751  return false;
752  }
753  if ($response[self::RESPONSE_TYPE] == NET_SSH1_SMSG_SUCCESS) {
754  $this->bitmap |= self::MASK_LOGIN;
755  return true;
756  } elseif ($response[self::RESPONSE_TYPE] == NET_SSH1_SMSG_FAILURE) {
757  return false;
758  } else {
759  user_error('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE');
760  return false;
761  }
762  }
763 
772  function setTimeout($timeout)
773  {
774  $this->timeout = $this->curTimeout = $timeout;
775  }
776 
797  function exec($cmd, $block = true)
798  {
799  if (!($this->bitmap & self::MASK_LOGIN)) {
800  user_error('Operation disallowed prior to login()');
801  return false;
802  }
803 
804  $data = pack('CNa*', NET_SSH1_CMSG_EXEC_CMD, strlen($cmd), $cmd);
805 
806  if (!$this->_send_binary_packet($data)) {
807  user_error('Error sending SSH_CMSG_EXEC_CMD');
808  return false;
809  }
810 
811  if (!$block) {
812  return true;
813  }
814 
815  $output = '';
816  $response = $this->_get_binary_packet();
817 
818  if ($response !== false) {
819  do {
820  $output.= substr($response[self::RESPONSE_DATA], 4);
821  $response = $this->_get_binary_packet();
822  } while (is_array($response) && $response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_EXITSTATUS);
823  }
824 
825  $data = pack('C', NET_SSH1_CMSG_EXIT_CONFIRMATION);
826 
827  // i don't think it's really all that important if this packet gets sent or not.
828  $this->_send_binary_packet($data);
829 
830  fclose($this->fsock);
831 
832  // reset the execution bitmap - a new \phpseclib\Net\SSH1 object needs to be created.
833  $this->bitmap = 0;
834 
835  return $output;
836  }
837 
846  function _initShell()
847  {
848  // connect using the sample parameters in protocol-1.5.txt.
849  // according to wikipedia.org's entry on text terminals, "the fundamental type of application running on a text
850  // terminal is a command line interpreter or shell". thus, opening a terminal session to run the shell.
851  $data = pack('CNa*N4C', NET_SSH1_CMSG_REQUEST_PTY, strlen('vt100'), 'vt100', 24, 80, 0, 0, self::TTY_OP_END);
852 
853  if (!$this->_send_binary_packet($data)) {
854  user_error('Error sending SSH_CMSG_REQUEST_PTY');
855  return false;
856  }
857 
858  $response = $this->_get_binary_packet();
859 
860  if ($response === true) {
861  return false;
862  }
863  if ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) {
864  user_error('Expected SSH_SMSG_SUCCESS');
865  return false;
866  }
867 
868  $data = pack('C', NET_SSH1_CMSG_EXEC_SHELL);
869 
870  if (!$this->_send_binary_packet($data)) {
871  user_error('Error sending SSH_CMSG_EXEC_SHELL');
872  return false;
873  }
874 
875  $this->bitmap |= self::MASK_SHELL;
876 
877  //stream_set_blocking($this->fsock, 0);
878 
879  return true;
880  }
881 
890  function write($cmd)
891  {
892  return $this->interactiveWrite($cmd);
893  }
894 
907  function read($expect, $mode = self::READ__SIMPLE)
908  {
909  if (!($this->bitmap & self::MASK_LOGIN)) {
910  user_error('Operation disallowed prior to login()');
911  return false;
912  }
913 
914  if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) {
915  user_error('Unable to initiate an interactive shell session');
916  return false;
917  }
918 
919  $match = $expect;
920  while (true) {
921  if ($mode == self::READ__REGEX) {
922  preg_match($expect, $this->interactiveBuffer, $matches);
923  $match = isset($matches[0]) ? $matches[0] : '';
924  }
925  $pos = strlen($match) ? strpos($this->interactiveBuffer, $match) : false;
926  if ($pos !== false) {
927  return $this->_string_shift($this->interactiveBuffer, $pos + strlen($match));
928  }
929  $response = $this->_get_binary_packet();
930 
931  if ($response === true) {
932  return $this->_string_shift($this->interactiveBuffer, strlen($this->interactiveBuffer));
933  }
934  $this->interactiveBuffer.= substr($response[self::RESPONSE_DATA], 4);
935  }
936  }
937 
946  function interactiveWrite($cmd)
947  {
948  if (!($this->bitmap & self::MASK_LOGIN)) {
949  user_error('Operation disallowed prior to login()');
950  return false;
951  }
952 
953  if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) {
954  user_error('Unable to initiate an interactive shell session');
955  return false;
956  }
957 
958  $data = pack('CNa*', NET_SSH1_CMSG_STDIN_DATA, strlen($cmd), $cmd);
959 
960  if (!$this->_send_binary_packet($data)) {
961  user_error('Error sending SSH_CMSG_STDIN');
962  return false;
963  }
964 
965  return true;
966  }
967 
981  function interactiveRead()
982  {
983  if (!($this->bitmap & self::MASK_LOGIN)) {
984  user_error('Operation disallowed prior to login()');
985  return false;
986  }
987 
988  if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) {
989  user_error('Unable to initiate an interactive shell session');
990  return false;
991  }
992 
993  $read = array($this->fsock);
994  $write = $except = null;
995  if (stream_select($read, $write, $except, 0)) {
996  $response = $this->_get_binary_packet();
997  return substr($response[self::RESPONSE_DATA], 4);
998  } else {
999  return '';
1000  }
1001  }
1002 
1008  function disconnect()
1009  {
1010  $this->_disconnect();
1011  }
1012 
1021  function __destruct()
1022  {
1023  $this->_disconnect();
1024  }
1025 
1032  function _disconnect($msg = 'Client Quit')
1033  {
1034  if ($this->bitmap) {
1035  $data = pack('C', NET_SSH1_CMSG_EOF);
1036  $this->_send_binary_packet($data);
1037  /*
1038  $response = $this->_get_binary_packet();
1039  if ($response === true) {
1040  $response = array(self::RESPONSE_TYPE => -1);
1041  }
1042  switch ($response[self::RESPONSE_TYPE]) {
1043  case NET_SSH1_SMSG_EXITSTATUS:
1044  $data = pack('C', NET_SSH1_CMSG_EXIT_CONFIRMATION);
1045  break;
1046  default:
1047  $data = pack('CNa*', NET_SSH1_MSG_DISCONNECT, strlen($msg), $msg);
1048  }
1049  */
1050  $data = pack('CNa*', NET_SSH1_MSG_DISCONNECT, strlen($msg), $msg);
1051 
1052  $this->_send_binary_packet($data);
1053  fclose($this->fsock);
1054  $this->bitmap = 0;
1055  }
1056  }
1057 
1071  {
1072  if (feof($this->fsock)) {
1073  //user_error('connection closed prematurely');
1074  return false;
1075  }
1076 
1077  if ($this->curTimeout) {
1078  $read = array($this->fsock);
1079  $write = $except = null;
1080 
1081  $start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838
1082  $sec = floor($this->curTimeout);
1083  $usec = 1000000 * ($this->curTimeout - $sec);
1084  // on windows this returns a "Warning: Invalid CRT parameters detected" error
1085  if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) {
1086  //$this->_disconnect('Timeout');
1087  return true;
1088  }
1089  $elapsed = strtok(microtime(), ' ') + strtok('') - $start;
1090  $this->curTimeout-= $elapsed;
1091  }
1092 
1093  $start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838
1094  $temp = unpack('Nlength', fread($this->fsock, 4));
1095 
1096  $padding_length = 8 - ($temp['length'] & 7);
1097  $length = $temp['length'] + $padding_length;
1098  $raw = '';
1099 
1100  while ($length > 0) {
1101  $temp = fread($this->fsock, $length);
1102  $raw.= $temp;
1103  $length-= strlen($temp);
1104  }
1105  $stop = strtok(microtime(), ' ') + strtok('');
1106 
1107  if (strlen($raw) && $this->crypto !== false) {
1108  $raw = $this->crypto->decrypt($raw);
1109  }
1110 
1111  $padding = substr($raw, 0, $padding_length);
1112  $type = $raw[$padding_length];
1113  $data = substr($raw, $padding_length + 1, -4);
1114 
1115  $temp = unpack('Ncrc', substr($raw, -4));
1116 
1117  //if ( $temp['crc'] != $this->_crc($padding . $type . $data) ) {
1118  // user_error('Bad CRC in packet from server');
1119  // return false;
1120  //}
1121 
1122  $type = ord($type);
1123 
1124  if (defined('NET_SSH1_LOGGING')) {
1125  $temp = isset($this->protocol_flags[$type]) ? $this->protocol_flags[$type] : 'UNKNOWN';
1126  $temp = '<- ' . $temp .
1127  ' (' . round($stop - $start, 4) . 's)';
1128  $this->_append_log($temp, $data);
1129  }
1130 
1131  return array(
1132  self::RESPONSE_TYPE => $type,
1133  self::RESPONSE_DATA => $data
1134  );
1135  }
1136 
1148  {
1149  if (feof($this->fsock)) {
1150  //user_error('connection closed prematurely');
1151  return false;
1152  }
1153 
1154  $length = strlen($data) + 4;
1155 
1156  $padding = Random::string(8 - ($length & 7));
1157 
1158  $orig = $data;
1159  $data = $padding . $data;
1160  $data.= pack('N', $this->_crc($data));
1161 
1162  if ($this->crypto !== false) {
1163  $data = $this->crypto->encrypt($data);
1164  }
1165 
1166  $packet = pack('Na*', $length, $data);
1167 
1168  $start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838
1169  $result = strlen($packet) == fputs($this->fsock, $packet);
1170  $stop = strtok(microtime(), ' ') + strtok('');
1171 
1172  if (defined('NET_SSH1_LOGGING')) {
1173  $temp = isset($this->protocol_flags[ord($orig[0])]) ? $this->protocol_flags[ord($orig[0])] : 'UNKNOWN';
1174  $temp = '-> ' . $temp .
1175  ' (' . round($stop - $start, 4) . 's)';
1176  $this->_append_log($temp, $orig);
1177  }
1178 
1179  return $result;
1180  }
1181 
1195  function _crc($data)
1196  {
1197  static $crc_lookup_table = array(
1198  0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
1199  0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
1200  0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
1201  0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
1202  0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
1203  0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
1204  0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
1205  0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
1206  0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
1207  0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
1208  0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
1209  0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
1210  0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
1211  0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
1212  0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
1213  0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
1214  0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
1215  0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
1216  0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
1217  0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
1218  0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
1219  0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
1220  0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
1221  0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
1222  0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
1223  0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
1224  0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
1225  0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
1226  0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
1227  0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
1228  0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
1229  0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
1230  0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
1231  0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
1232  0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
1233  0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
1234  0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
1235  0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
1236  0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
1237  0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
1238  0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
1239  0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
1240  0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
1241  0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
1242  0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
1243  0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
1244  0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
1245  0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
1246  0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
1247  0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
1248  0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
1249  0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
1250  0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
1251  0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
1252  0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
1253  0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
1254  0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
1255  0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
1256  0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
1257  0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
1258  0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
1259  0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
1260  0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
1261  0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
1262  );
1263 
1264  // For this function to yield the same output as PHP's crc32 function, $crc would have to be
1265  // set to 0xFFFFFFFF, initially - not 0x00000000 as it currently is.
1266  $crc = 0x00000000;
1267  $length = strlen($data);
1268 
1269  for ($i=0; $i<$length; $i++) {
1270  // We AND $crc >> 8 with 0x00FFFFFF because we want the eight newly added bits to all
1271  // be zero. PHP, unfortunately, doesn't always do this. 0x80000000 >> 8, as an example,
1272  // yields 0xFF800000 - not 0x00800000. The following link elaborates:
1273  // http://www.php.net/manual/en/language.operators.bitwise.php#57281
1274  $crc = (($crc >> 8) & 0x00FFFFFF) ^ $crc_lookup_table[($crc & 0xFF) ^ ord($data[$i])];
1275  }
1276 
1277  // In addition to having to set $crc to 0xFFFFFFFF, initially, the return value must be XOR'd with
1278  // 0xFFFFFFFF for this function to return the same thing that PHP's crc32 function would.
1279  return $crc;
1280  }
1281 
1292  function _string_shift(&$string, $index = 1)
1293  {
1294  $substr = substr($string, 0, $index);
1295  $string = substr($string, $index);
1296  return $substr;
1297  }
1298 
1312  function _rsa_crypt($m, $key)
1313  {
1314  /*
1315  $rsa = new RSA();
1316  $rsa->loadKey($key, RSA::PUBLIC_FORMAT_RAW);
1317  $rsa->setEncryptionMode(RSA::ENCRYPTION_PKCS1);
1318  return $rsa->encrypt($m);
1319  */
1320 
1321  // To quote from protocol-1.5.txt:
1322  // The most significant byte (which is only partial as the value must be
1323  // less than the public modulus, which is never a power of two) is zero.
1324  //
1325  // The next byte contains the value 2 (which stands for public-key
1326  // encrypted data in the PKCS standard [PKCS#1]). Then, there are non-
1327  // zero random bytes to fill any unused space, a zero byte, and the data
1328  // to be encrypted in the least significant bytes, the last byte of the
1329  // data in the least significant byte.
1330 
1331  // Presumably the part of PKCS#1 they're refering to is "Section 7.2.1 Encryption Operation",
1332  // under "7.2 RSAES-PKCS1-v1.5" and "7 Encryption schemes" of the following URL:
1333  // ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.pdf
1334  $modulus = $key[1]->toBytes();
1335  $length = strlen($modulus) - strlen($m) - 3;
1336  $random = '';
1337  while (strlen($random) != $length) {
1338  $block = Random::string($length - strlen($random));
1339  $block = str_replace("\x00", '', $block);
1340  $random.= $block;
1341  }
1342  $temp = chr(0) . chr(2) . $random . chr(0) . $m;
1343 
1344  $m = new BigInteger($temp, 256);
1345  $m = $m->modPow($key[0], $key[1]);
1346 
1347  return $m->toBytes();
1348  }
1349 
1360  function _define_array()
1361  {
1362  $args = func_get_args();
1363  foreach ($args as $arg) {
1364  foreach ($arg as $key => $value) {
1365  if (!defined($value)) {
1366  define($value, $key);
1367  } else {
1368  break 2;
1369  }
1370  }
1371  }
1372  }
1373 
1382  function getLog()
1383  {
1384  if (!defined('NET_SSH1_LOGGING')) {
1385  return false;
1386  }
1387 
1388  switch (NET_SSH1_LOGGING) {
1389  case self::LOG_SIMPLE:
1390  return $this->message_number_log;
1391  break;
1392  case self::LOG_COMPLEX:
1393  return $this->_format_log($this->message_log, $this->protocol_flags_log);
1394  break;
1395  default:
1396  return false;
1397  }
1398  }
1399 
1408  function _format_log($message_log, $message_number_log)
1409  {
1410  $output = '';
1411  for ($i = 0; $i < count($message_log); $i++) {
1412  $output.= $message_number_log[$i] . "\r\n";
1413  $current_log = $message_log[$i];
1414  $j = 0;
1415  do {
1416  if (strlen($current_log)) {
1417  $output.= str_pad(dechex($j), 7, '0', STR_PAD_LEFT) . '0 ';
1418  }
1419  $fragment = $this->_string_shift($current_log, $this->log_short_width);
1420  $hex = substr(preg_replace_callback('#.#s', array($this, '_format_log_helper'), $fragment), strlen($this->log_boundary));
1421  // replace non ASCII printable characters with dots
1422  // http://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters
1423  // also replace < with a . since < messes up the output on web browsers
1424  $raw = preg_replace('#[^\x20-\x7E]|<#', '.', $fragment);
1425  $output.= str_pad($hex, $this->log_long_width - $this->log_short_width, ' ') . $raw . "\r\n";
1426  $j++;
1427  } while (strlen($current_log));
1428  $output.= "\r\n";
1429  }
1430 
1431  return $output;
1432  }
1433 
1443  function _format_log_helper($matches)
1444  {
1445  return $this->log_boundary . str_pad(dechex(ord($matches[0])), 2, '0', STR_PAD_LEFT);
1446  }
1447 
1458  function getServerKeyPublicExponent($raw_output = false)
1459  {
1460  return $raw_output ? $this->server_key_public_exponent->toBytes() : $this->server_key_public_exponent->toString();
1461  }
1462 
1473  function getServerKeyPublicModulus($raw_output = false)
1474  {
1475  return $raw_output ? $this->server_key_public_modulus->toBytes() : $this->server_key_public_modulus->toString();
1476  }
1477 
1488  function getHostKeyPublicExponent($raw_output = false)
1489  {
1490  return $raw_output ? $this->host_key_public_exponent->toBytes() : $this->host_key_public_exponent->toString();
1491  }
1492 
1503  function getHostKeyPublicModulus($raw_output = false)
1504  {
1505  return $raw_output ? $this->host_key_public_modulus->toBytes() : $this->host_key_public_modulus->toString();
1506  }
1507 
1519  function getSupportedCiphers($raw_output = false)
1520  {
1521  return $raw_output ? array_keys($this->supported_ciphers) : array_values($this->supported_ciphers);
1522  }
1523 
1535  function getSupportedAuthentications($raw_output = false)
1536  {
1537  return $raw_output ? array_keys($this->supported_authentications) : array_values($this->supported_authentications);
1538  }
1539 
1547  {
1548  return rtrim($this->server_identification);
1549  }
1550 
1559  function _append_log($protocol_flags, $message)
1560  {
1561  switch (NET_SSH1_LOGGING) {
1562  // useful for benchmarks
1563  case self::LOG_SIMPLE:
1564  $this->protocol_flags_log[] = $protocol_flags;
1565  break;
1566  // the most useful log for SSH1
1567  case self::LOG_COMPLEX:
1568  $this->protocol_flags_log[] = $protocol_flags;
1569  $this->_string_shift($message);
1570  $this->log_size+= strlen($message);
1571  $this->message_log[] = $message;
1572  while ($this->log_size > self::LOG_MAX_SIZE) {
1573  $this->log_size-= strlen(array_shift($this->message_log));
1574  array_shift($this->protocol_flags_log);
1575  }
1576  break;
1577  // dump the output out realtime; packets may be interspersed with non packets,
1578  // passwords won't be filtered out and select other packets may not be correctly
1579  // identified
1580  case self::LOG_REALTIME:
1581  echo "<pre>\r\n" . $this->_format_log(array($message), array($protocol_flags)) . "\r\n</pre>\r\n";
1582  @flush();
1583  @ob_flush();
1584  break;
1585  // basically the same thing as self::LOG_REALTIME with the caveat that self::LOG_REALTIME_FILE
1586  // needs to be defined and that the resultant log file will be capped out at self::LOG_MAX_SIZE.
1587  // the earliest part of the log file is denoted by the first <<< START >>> and is not going to necessarily
1588  // at the beginning of the file
1589  case self::LOG_REALTIME_FILE:
1590  if (!isset($this->realtime_log_file)) {
1591  // PHP doesn't seem to like using constants in fopen()
1592  $filename = self::LOG_REALTIME_FILE;
1593  $fp = fopen($filename, 'w');
1594  $this->realtime_log_file = $fp;
1595  }
1596  if (!is_resource($this->realtime_log_file)) {
1597  break;
1598  }
1599  $entry = $this->_format_log(array($message), array($protocol_flags));
1600  if ($this->realtime_log_wrap) {
1601  $temp = "<<< START >>>\r\n";
1602  $entry.= $temp;
1603  fseek($this->realtime_log_file, ftell($this->realtime_log_file) - strlen($temp));
1604  }
1605  $this->realtime_log_size+= strlen($entry);
1606  if ($this->realtime_log_size > self::LOG_MAX_SIZE) {
1607  fseek($this->realtime_log_file, 0);
1608  $this->realtime_log_size = strlen($entry);
1609  $this->realtime_log_wrap = true;
1610  }
1611  fputs($this->realtime_log_file, $entry);
1612  }
1613  }
1614 }
$timeout
Timeout.
Definition: SSH1.php:416
_send_binary_packet($data)
Sends Binary Packets.
Definition: SSH1.php:1147
const TTY_OP_END
#-
Definition: SSH1.php:157
const CIPHER_RC4
RC4.
Definition: SSH1.php:115
const RESPONSE_TYPE
#-
Definition: SSH1.php:166
login($username, $password='')
Login.
Definition: SSH1.php:702
_append_log($protocol_flags, $message)
Logs data packets.
Definition: SSH1.php:1559
const MODE_3CBC
Encrypt / decrypt using inner chaining.
Definition: TripleDES.php:56
_crc($data)
Cyclic Redundancy Check (CRC)
Definition: SSH1.php:1195
$log_boundary
Log Boundary.
Definition: SSH1.php:432
const MASK_CONSTRUCTOR
#+ Execution Bitmap Masks
Definition: SSH1.php:182
getServerKeyPublicModulus($raw_output=false)
Return the server key public modulus.
Definition: SSH1.php:1473
$result
_connect()
Connect to an SSHv1 server.
Definition: SSH1.php:542
$type
const MASK_CONNECTED
Definition: SSH1.php:183
interactiveRead()
Returns the output of an interactive shell when no more output is available.
Definition: SSH1.php:981
getServerKeyPublicExponent($raw_output=false)
Return the server key public exponent.
Definition: SSH1.php:1458
const AUTH_RHOSTS
#-
Definition: SSH1.php:134
write($cmd)
Inputs a command into an interactive shell.
Definition: SSH1.php:890
$log_long_width
Log Long Width.
Definition: SSH1.php:440
$log_short_width
Log Short Width.
Definition: SSH1.php:448
$server_key_public_modulus
Definition: SSH1.php:279
const LOG_REALTIME
Outputs the content real-time.
Definition: SSH1.php:203
$curTimeout
Current Timeout.
Definition: SSH1.php:424
Pure-PHP implementation of SSHv1.
const CIPHER_IDEA
IDEA in CFB mode.
Definition: SSH1.php:82
getSupportedAuthentications($raw_output=false)
Return a list of authentications supported by SSH1 server.
Definition: SSH1.php:1535
getSupportedCiphers($raw_output=false)
Return a list of ciphers supported by SSH1 server.
Definition: SSH1.php:1519
$index
Definition: metadata.php:60
const AUTH_RHOSTS_RSA
.rhosts with RSA host authentication
Definition: SSH1.php:148
$server_key_public_exponent
Definition: SSH1.php:268
const CIPHER_BROKEN_TSS
TRI&#39;s Simple Stream encryption CBC.
Definition: SSH1.php:99
exec($cmd, $block=true)
Executes a command on a non-interactive shell, returns the output, and quits.
Definition: SSH1.php:797
$start
Definition: bench.php:8
__construct($host, $port=22, $timeout=10, $cipher=self::CIPHER_3DES)
Default Constructor.
Definition: SSH1.php:507
_initShell()
Creates an interactive shell.
Definition: SSH1.php:846
disconnect()
Disconnect.
Definition: SSH1.php:1008
catch(Exception $e) $message
$mask
Definition: example_042.php:90
const LOG_COMPLEX
Returns the message content.
Definition: SSH1.php:199
const LOG_REALTIME_FILE
Dumps the content real-time to a file.
Definition: SSH1.php:207
const CIPHER_BLOWFISH
Blowfish.
Definition: SSH1.php:122
read($expect, $mode=self::READ__SIMPLE)
Returns the output of an interactive shell when there&#39;s a match for $expect.
Definition: SSH1.php:907
const MASK_SHELL
Definition: SSH1.php:185
setTimeout($timeout)
Set Timeout.
Definition: SSH1.php:772
_define_array()
Define Array.
Definition: SSH1.php:1360
Pure-PHP implementation of Triple DES.
const CIPHER_NONE
#+ Encryption Methods
Definition: SSH1.php:76
_get_binary_packet()
Gets Binary Packets.
Definition: SSH1.php:1070
getHostKeyPublicExponent($raw_output=false)
Return the host key public exponent.
Definition: SSH1.php:1488
$filename
Definition: buildRTE.php:89
_rsa_crypt($m, $key)
RSA Encrypt.
Definition: SSH1.php:1312
const READ_SIMPLE
#-
Definition: SSH1.php:217
$supported_authentications
Definition: SSH1.php:331
_string_shift(&$string, $index=1)
String Shift.
Definition: SSH1.php:1292
$password
Definition: cron.php:14
const AUTH_RSA
pure RSA authentication
Definition: SSH1.php:138
Pure-PHP arbitrary precision integer arithmetic library.
getHostKeyPublicModulus($raw_output=false)
Return the host key public modulus.
Definition: SSH1.php:1503
const RESPONSE_DATA
The Response Data.
Definition: SSH1.php:174
__destruct()
Destructor.
Definition: SSH1.php:1021
$i
Definition: disco.tpl.php:19
_disconnect($msg='Client Quit')
Disconnect.
Definition: SSH1.php:1032
const LOG_SIMPLE
#-
Definition: SSH1.php:195
getLog()
Returns a log of the packets that have been sent and received.
Definition: SSH1.php:1382
static string($length)
Generate a random string.
Definition: Random.php:54
const AUTH_PASSWORD
password authentication
Definition: SSH1.php:144
interactiveWrite($cmd)
Inputs a command into an interactive shell.
Definition: SSH1.php:946
const CIPHER_3DES
Triple-DES in CBC mode.
Definition: SSH1.php:92
const MASK_LOGIN
Definition: SSH1.php:184
Pure-PHP implementation of DES.
$response
getServerIdentification()
Return the server identification.
Definition: SSH1.php:1546
$key
Definition: croninfo.php:18
_format_log($message_log, $message_number_log)
Formats a log for printing.
Definition: SSH1.php:1408
const READ_REGEX
Returns when a string matching the regular expression $expect is found.
Definition: SSH1.php:221
const CIPHER_DES
DES in CBC mode.
Definition: SSH1.php:86
$data
Definition: bench.php:6
_format_log_helper($matches)
Helper function for _format_log.
Definition: SSH1.php:1443