ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
SSH1.php
Go to the documentation of this file.
1<?php
2
49namespace phpseclib\Net;
50
55
63class SSH1
64{
76 const CIPHER_NONE = 0;
82 const CIPHER_IDEA = 1;
86 const CIPHER_DES = 2;
92 const CIPHER_3DES = 3;
115 const CIPHER_RC4 = 5;
134 const AUTH_RHOSTS = 1;
138 const AUTH_RSA = 2;
144 const AUTH_PASSWORD = 3;
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;
217 const READ_SIMPLE = 1;
221 const READ_REGEX = 2;
230 var $identifier = 'SSH-1.5-phpseclib';
231
239
246 var $crypto = false;
247
257 var $bitmap = 0;
258
269
280
291
302
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
417
425
432 var $log_boundary = ':';
433
441
449
458 var $host;
459
468 var $port;
469
484
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
620 $double_encrypted_session_key = $this->_rsa_crypt(
621 $double_encrypted_session_key,
622 array(
625 )
626 );
627 $double_encrypted_session_key = $this->_rsa_crypt(
628 $double_encrypted_session_key,
629 array(
632 )
633 );
634 } else {
635 $double_encrypted_session_key = $this->_rsa_crypt(
636 $double_encrypted_session_key,
637 array(
640 )
641 );
642 $double_encrypted_session_key = $this->_rsa_crypt(
643 $double_encrypted_session_key,
644 array(
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;
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
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.
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
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
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
1590 if (!isset($this->realtime_log_file)) {
1591 // PHP doesn't seem to like using constants in fopen()
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}
$result
$filename
Definition: buildRTE.php:89
An exception for terminatinating execution or to throw for unit testing.
static string($length)
Generate a random string.
Definition: Random.php:54
const MODE_3CBC
Encrypt / decrypt using inner chaining.
Definition: TripleDES.php:56
getHostKeyPublicModulus($raw_output=false)
Return the host key public modulus.
Definition: SSH1.php:1503
__destruct()
Destructor.
Definition: SSH1.php:1021
_define_array()
Define Array.
Definition: SSH1.php:1360
_crc($data)
Cyclic Redundancy Check (CRC)
Definition: SSH1.php:1195
const READ_REGEX
Returns when a string matching the regular expression $expect is found.
Definition: SSH1.php:221
const LOG_REALTIME
Outputs the content real-time.
Definition: SSH1.php:203
const MASK_LOGIN
Definition: SSH1.php:184
const AUTH_PASSWORD
password authentication
Definition: SSH1.php:144
setTimeout($timeout)
Set Timeout.
Definition: SSH1.php:772
$curTimeout
Current Timeout.
Definition: SSH1.php:424
const CIPHER_3DES
Triple-DES in CBC mode.
Definition: SSH1.php:92
const AUTH_RHOSTS
#-
Definition: SSH1.php:134
const AUTH_RHOSTS_RSA
.rhosts with RSA host authentication
Definition: SSH1.php:148
getHostKeyPublicExponent($raw_output=false)
Return the host key public exponent.
Definition: SSH1.php:1488
disconnect()
Disconnect.
Definition: SSH1.php:1008
write($cmd)
Inputs a command into an interactive shell.
Definition: SSH1.php:890
const LOG_SIMPLE
#-
Definition: SSH1.php:195
const AUTH_RSA
pure RSA authentication
Definition: SSH1.php:138
const LOG_COMPLEX
Returns the message content.
Definition: SSH1.php:199
getSupportedAuthentications($raw_output=false)
Return a list of authentications supported by SSH1 server.
Definition: SSH1.php:1535
const CIPHER_IDEA
IDEA in CFB mode.
Definition: SSH1.php:82
const MASK_CONNECTED
Definition: SSH1.php:183
const MASK_SHELL
Definition: SSH1.php:185
read($expect, $mode=self::READ__SIMPLE)
Returns the output of an interactive shell when there's a match for $expect.
Definition: SSH1.php:907
_format_log($message_log, $message_number_log)
Formats a log for printing.
Definition: SSH1.php:1408
const LOG_REALTIME_FILE
Dumps the content real-time to a file.
Definition: SSH1.php:207
_initShell()
Creates an interactive shell.
Definition: SSH1.php:846
__construct($host, $port=22, $timeout=10, $cipher=self::CIPHER_3DES)
Default Constructor.
Definition: SSH1.php:507
$server_key_public_modulus
Definition: SSH1.php:279
const CIPHER_NONE
#+ Encryption Methods
Definition: SSH1.php:76
$log_short_width
Log Short Width.
Definition: SSH1.php:448
$timeout
Timeout.
Definition: SSH1.php:416
$log_long_width
Log Long Width.
Definition: SSH1.php:440
interactiveRead()
Returns the output of an interactive shell when no more output is available.
Definition: SSH1.php:981
interactiveWrite($cmd)
Inputs a command into an interactive shell.
Definition: SSH1.php:946
_get_binary_packet()
Gets Binary Packets.
Definition: SSH1.php:1070
const RESPONSE_DATA
The Response Data.
Definition: SSH1.php:174
_disconnect($msg='Client Quit')
Disconnect.
Definition: SSH1.php:1032
const MASK_CONSTRUCTOR
#+ Execution Bitmap Masks
Definition: SSH1.php:182
const CIPHER_DES
DES in CBC mode.
Definition: SSH1.php:86
getServerKeyPublicModulus($raw_output=false)
Return the server key public modulus.
Definition: SSH1.php:1473
getLog()
Returns a log of the packets that have been sent and received.
Definition: SSH1.php:1382
login($username, $password='')
Login.
Definition: SSH1.php:702
_append_log($protocol_flags, $message)
Logs data packets.
Definition: SSH1.php:1559
$log_boundary
Log Boundary.
Definition: SSH1.php:432
_connect()
Connect to an SSHv1 server.
Definition: SSH1.php:542
const READ_SIMPLE
#-
Definition: SSH1.php:217
exec($cmd, $block=true)
Executes a command on a non-interactive shell, returns the output, and quits.
Definition: SSH1.php:797
const CIPHER_BROKEN_TSS
TRI's Simple Stream encryption CBC.
Definition: SSH1.php:99
getServerKeyPublicExponent($raw_output=false)
Return the server key public exponent.
Definition: SSH1.php:1458
const TTY_OP_END
#-
Definition: SSH1.php:157
$server_key_public_exponent
Definition: SSH1.php:268
_string_shift(&$string, $index=1)
String Shift.
Definition: SSH1.php:1292
$supported_authentications
Definition: SSH1.php:331
getSupportedCiphers($raw_output=false)
Return a list of ciphers supported by SSH1 server.
Definition: SSH1.php:1519
const CIPHER_BLOWFISH
Blowfish.
Definition: SSH1.php:122
_send_binary_packet($data)
Sends Binary Packets.
Definition: SSH1.php:1147
const CIPHER_RC4
RC4.
Definition: SSH1.php:115
_format_log_helper($matches)
Helper function for _format_log.
Definition: SSH1.php:1443
getServerIdentification()
Return the server identification.
Definition: SSH1.php:1546
_rsa_crypt($m, $key)
RSA Encrypt.
Definition: SSH1.php:1312
const RESPONSE_TYPE
#-
Definition: SSH1.php:166
$password
Definition: cron.php:14
$key
Definition: croninfo.php:18
$i
Definition: disco.tpl.php:19
$mask
Definition: example_042.php:90
$index
Definition: metadata.php:60
catch(Exception $e) $message
Pure-PHP arbitrary precision integer arithmetic library.
Pure-PHP implementation of DES.
Pure-PHP implementation of SSHv1.
Pure-PHP implementation of Triple DES.
$type
$response
$start
Definition: bench.php:8
$data
Definition: bench.php:6