1 /* 2 * This file is part of "The Java Telnet Application". 3 * 4 * (c) Matthias L. Jugel, Marcus Meißner 1996-2002. All Rights Reserved. 5 * The file was changed by Radek Polak to work as midlet in MIDP 1.0 6 * 7 * Please visit http://javatelnet.org/ for updates and contact. 8 * 9 * --LICENSE NOTICE-- 10 * This program is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU General Public License 12 * as published by the Free Software Foundation; either version 2 13 * of the License, or (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 23 * --LICENSE NOTICE-- 24 */ 25 26 package ssh; 27 28 import telnet.Telnet; 29 import java.io.IOException; 30 31 /** 32 * Secure Shell IO 33 * @author Marcus Meissner 34 * @version $Id: SshIO.java,v 1.27 2002/10/26 19:06:30 marcus Exp $ 35 */ 36 public class SshIO { 37 38 private static MD5 md5 = new MD5(); 39 40 /** 41 * variables for the connection 42 */ 43 private String idstr = ""; //("SSH-<protocolmajor>.<protocolminor>-<version>\n") 44 private String idstr_sent = "SSH/JTA (c) Marcus Meissner, Matthias L. Jugel\n"; 45 46 /** 47 * Debug level. This results in additional diagnostic messages on the 48 * java console. 49 */ 50 // private static int debug = 0; 51 52 /** 53 * State variable for Ssh negotiation reader 54 */ 55 private SshCrypto crypto = null; 56 57 String cipher_type;// = "IDEA"; 58 public static java.util.Random rnd = new java.util.Random(); 59 60 private int remotemajor, remoteminor; 61 private int mymajor, myminor; 62 private int useprotocol; 63 64 public String login, password; 65 //nobody is to access those fields : better to use pivate, nobody knows :-) 66 67 public String dataToSend = null; 68 69 public String hashHostKey = null; // equals to the applet parameter if any 70 71 byte lastPacketSentType; 72 73 74 // phase : handleBytes 75 private int phase = 0; 76 private final int PHASE_INIT = 0; 77 private final int PHASE_SSH_RECEIVE_PACKET = 1; 78 79 80 // SSH v2 RSA 81 BigInteger rsa_e, rsa_n; 82 83 //handlePacket 84 //messages 85 // The supported packet types and the corresponding message numbers are 86 // given in the following table. Messages with _MSG_ in their name may 87 // be sent by either side. Messages with _CMSG_ are only sent by the 88 // client, and messages with _SMSG_ only by the server. 89 // 90 private final byte SSH_MSG_DISCONNECT = 1; 91 private final byte SSH_SMSG_PUBLIC_KEY = 2; 92 private final byte SSH_CMSG_SESSION_KEY = 3; 93 private final byte SSH_CMSG_USER = 4; 94 private final byte SSH_CMSG_AUTH_PASSWORD = 9; 95 private final byte SSH_CMSG_REQUEST_PTY = 10; 96 private final byte SSH_CMSG_EXEC_SHELL = 12; 97 private final byte SSH_SMSG_SUCCESS = 14; 98 private final byte SSH_SMSG_FAILURE = 15; 99 private final byte SSH_CMSG_STDIN_DATA = 16; 100 private final byte SSH_SMSG_STDOUT_DATA = 17; 101 private final byte SSH_SMSG_STDERR_DATA = 18; 102 private final byte SSH_SMSG_EXITSTATUS = 20; 103 private final byte SSH_MSG_IGNORE = 32; 104 private final byte SSH_CMSG_EXIT_CONFIRMATION = 33; 105 private final byte SSH_MSG_DEBUG = 36; 106 107 108 /* SSH v2 stuff */ 109 110 private final byte SSH2_MSG_DISCONNECT = 1; 111 private final byte SSH2_MSG_IGNORE = 2; 112 private final byte SSH2_MSG_SERVICE_REQUEST = 5; 113 private final byte SSH2_MSG_SERVICE_ACCEPT = 6; 114 115 private final byte SSH2_MSG_KEXINIT = 20; 116 private final byte SSH2_MSG_NEWKEYS = 21; 117 118 private final byte SSH2_MSG_KEXDH_INIT = 30; 119 private final byte SSH2_MSG_KEXDH_REPLY = 31; 120 121 private String kexalgs, hostkeyalgs, encalgs2c, encalgc2s, macalgs2c, macalgc2s, compalgc2s, compalgs2c, langc2s, langs2; 122 123 private int outgoingseq = 0, incomingseq = 0; 124 125 // 126 // encryption types 127 // 128 private int SSH_CIPHER_NONE = 0; // No encryption 129 private int SSH_CIPHER_IDEA = 1; // IDEA in CFB mode (patented) 130 private int SSH_CIPHER_DES = 2; // DES in CBC mode 131 private int SSH_CIPHER_3DES = 3; // Triple-DES in CBC mode 132 private int SSH_CIPHER_TSS = 4; // An experimental stream cipher 133 134 private int SSH_CIPHER_RC4 = 5; // RC4 (patented) 135 136 private int SSH_CIPHER_BLOWFISH = 6; // Bruce Scheiers blowfish (public d) 137 138 139 // 140 // authentication methods 141 // 142 private final int SSH_AUTH_RHOSTS = 1; //.rhosts or /etc/hosts.equiv 143 private final int SSH_AUTH_RSA = 2; //pure RSA authentication 144 private final int SSH_AUTH_PASSWORD = 3; //password authentication, implemented ! 145 private final int SSH_AUTH_RHOSTS_RSA = 4; //.rhosts with RSA host authentication 146 147 148 private boolean cansenddata = false; 149 150 /** 151 * Initialise SshIO 152 */ 153 public SshIO() { 154 crypto = null; 155 } 156 157 SshPacket currentpacket; 158 159 /** write data to our back end */ 160 public void write(byte[] b) throws IOException { 161 if( Telnet.outputCount + b.length > Telnet.output.length ) 162 { 163 byte[] newOutput = new byte[Telnet.outputCount+b.length]; 164 System.arraycopy( Telnet.output, 0, newOutput, 0, Telnet.outputCount ); 165 Telnet.output = newOutput; 166 } 167 System.arraycopy(b, 0, Telnet.output, Telnet.outputCount, b.length); 168 Telnet.outputCount += b.length; 169 } 170 171 byte[] one = new byte[1]; 172 173 private void write(byte b) throws IOException { 174 one[0] = b; 175 write(one); 176 } 177 178 public void disconnect() { 179 login = ""; 180 password = ""; 181 phase = 0; 182 crypto = null; 183 } 184 185 synchronized public void sendData(String str) throws IOException { 186 // if (debug > 1) System.out.println("SshIO.send(" + str + ")"); 187 if (dataToSend == null) 188 dataToSend = str; 189 else 190 dataToSend += str; 191 if (cansenddata) { 192 Send_SSH_CMSG_STDIN_DATA(dataToSend); 193 dataToSend = null; 194 } 195 } 196 197 /** 198 * Read data from the remote host. Blocks until data is available. 199 * 200 * Returns an array of bytes that will be displayed. 201 * 202 */ 203 public byte[] handleSSH(byte buff[]) 204 throws IOException { 205 byte[] rest; 206 String result; 207 208 // if (debug > 1) 209 // Telnet.console.append("SshIO.getPacket(" + buff + "," + buff.length + ")"); 210 211 212 if (phase == PHASE_INIT) { 213 byte b; // of course, byte is a signed entity (-128 -> 127) 214 int boffset = 0; // offset into the buffer received 215 216 while (boffset < buff.length) { 217 b = buff[boffset++]; 218 // both sides MUST send an identification string of the form 219 // "SSH-protoversion-softwareversion comments", 220 // followed by newline character(ascii 10 = '\n' or '\r') 221 idstr += (char) b; 222 if (b == '\n') { 223 phase++; 224 // if (!idstr.substring(0, 4).equals("SSH-")) { 225 // System.out.println("Received invalid ID string: " + idstr + ", (substr " + idstr.substring(0, 4) + ")"); 226 // throw (new IOException()); 227 // } 228 remotemajor = Integer.parseInt(idstr.substring(4, 5)); 229 String minorverstr = idstr.substring(6, 8); 230 if (!Character.isDigit(minorverstr.charAt(1))) 231 minorverstr = minorverstr.substring(0, 1); 232 remoteminor = Integer.parseInt(minorverstr); 233 234 // System.out.println("remotemajor " + remotemajor); 235 // System.out.println("remoteminor " + remoteminor); 236 237 if (remotemajor == 2) { 238 mymajor = 2; 239 myminor = 0; 240 useprotocol = 2; 241 } else { 242 if (false && (remoteminor == 99)) { 243 mymajor = 2; 244 myminor = 0; 245 useprotocol = 2; 246 } else { 247 mymajor = 1; 248 myminor = 5; 249 useprotocol = 1; 250 } 251 } 252 // this is how we tell the remote server what protocol we use. 253 idstr_sent = "SSH-" + mymajor + "." + myminor + "-" + idstr_sent; 254 write(idstr_sent.getBytes()); 255 256 if (useprotocol == 2) 257 currentpacket = new SshPacket2(null); 258 else 259 currentpacket = new SshPacket1(null); 260 } 261 } 262 if (boffset == buff.length) 263 return "".getBytes(); 264 return "Must not have left over data after PHASE_INIT!\n".getBytes(); 265 } 266 267 result = ""; 268 rest = currentpacket.addPayload(buff); 269 if (currentpacket.isFinished()) { 270 if (useprotocol == 1) { 271 result = result + handlePacket1((SshPacket1) currentpacket); 272 currentpacket = new SshPacket1(crypto); 273 } else { 274 result = result + handlePacket2((SshPacket2) currentpacket); 275 currentpacket = new SshPacket2(crypto); 276 } 277 } 278 while (rest != null) { 279 rest = currentpacket.addPayload(rest); 280 if (currentpacket.isFinished()) { 281 // the packet is finished, otherwise we would not have got a rest 282 if (useprotocol == 1) { 283 result = result + handlePacket1((SshPacket1) currentpacket); 284 currentpacket = new SshPacket1(crypto); 285 } else { 286 result = result + handlePacket2((SshPacket2) currentpacket); 287 currentpacket = new SshPacket2(crypto); 288 } 289 } 290 } 291 return result.getBytes(); 292 } 293 294 /** 295 * Handle SSH protocol Version 2 296 * 297 * @param p the packet we will process here. 298 * @return a array of bytes 299 */ 300 private String handlePacket2(SshPacket2 p) 301 throws IOException { 302 switch (p.getType()) { 303 case SSH2_MSG_IGNORE: 304 // System.out.println("SSH2: SSH2_MSG_IGNORE"); 305 break; 306 case SSH2_MSG_DISCONNECT: 307 int discreason = p.getInt32(); 308 String discreason1 = p.getString(); 309 /*String discreason2 = p.getString();*/ 310 // System.out.println("SSH2: SSH2_MSG_DISCONNECT(" + discreason + "," + discreason1 + "," + /*discreason2+*/")"); 311 312 return "\nSSH2 disconnect: " + discreason1 + "\n"; 313 314 case SSH2_MSG_NEWKEYS: 315 { 316 // System.out.println("SSH2: SSH2_MSG_NEWKEYS"); 317 sendPacket2(new SshPacket2(SSH2_MSG_NEWKEYS)); 318 319 byte[] session_key = new byte[16]; 320 321 crypto = new SshCrypto(cipher_type, session_key); 322 323 SshPacket2 pn = new SshPacket2(SSH2_MSG_SERVICE_REQUEST); 324 pn.putString("ssh-userauth"); 325 sendPacket2(pn); 326 break; 327 } 328 case SSH2_MSG_SERVICE_ACCEPT: 329 { 330 // System.out.println("Service Accept: " + p.getString()); 331 break; 332 } 333 case SSH2_MSG_KEXINIT: 334 { 335 byte[] fupp; 336 // System.out.println("SSH2: SSH2_MSG_KEXINIT"); 337 byte kexcookie[] = p.getBytes(16); // unused. 338 339 String kexalgs = p.getString(); 340 // System.out.println("- " + kexalgs); 341 String hostkeyalgs = p.getString(); 342 // System.out.println("- " + hostkeyalgs); 343 String encalgc2s = p.getString(); 344 // System.out.println("- " + encalgc2s); 345 String encalgs2c = p.getString(); 346 // System.out.println("- " + encalgs2c); 347 String macalgc2s = p.getString(); 348 // System.out.println("- " + macalgc2s); 349 String macalgs2c = p.getString(); 350 // System.out.println("- " + macalgs2c); 351 String compalgc2s = p.getString(); 352 // System.out.println("- " + compalgc2s); 353 String compalgs2c = p.getString(); 354 // System.out.println("- " + compalgs2c); 355 String langc2s = p.getString(); 356 // System.out.println("- " + langc2s); 357 String langs2c = p.getString(); 358 // System.out.println("- " + langs2c); 359 fupp = p.getBytes(1); 360 // System.out.println("- first_kex_follows: " + fupp[0]); 361 /* int32 reserved (0) */ 362 363 SshPacket2 pn = new SshPacket2(SSH2_MSG_KEXINIT); 364 byte[] kexsend = new byte[16]; 365 String ciphername; 366 pn.putBytes(kexsend); 367 pn.putString("diffie-hellman-group1-sha1"); 368 pn.putString("ssh-rsa"); 369 370 /* FIXME: check if it really is in the encalgc2s */ 371 cipher_type = "NONE"; 372 ciphername = "none"; 373 374 /* FIXME: dito for HMAC */ 375 376 pn.putString("none"); 377 pn.putString("none"); 378 pn.putString("hmac-md5"); 379 pn.putString("hmac-md5"); 380 pn.putString("none"); 381 pn.putString("none"); 382 pn.putString(""); 383 pn.putString(""); 384 pn.putByte((byte) 0); 385 pn.putInt32(0); 386 sendPacket2(pn); 387 388 pn = new SshPacket2(SSH2_MSG_KEXDH_INIT); 389 pn.putMpInt(BigInteger.valueOf(0xdeadbeef)); 390 sendPacket2(pn); 391 break; 392 } 393 case SSH2_MSG_KEXDH_REPLY: 394 { 395 String result; 396 397 // System.out.println("SSH2_MSG_KEXDH_REPLY"); 398 int bloblen = p.getInt32(); 399 // System.out.println("bloblen is " + bloblen); 400 /* the blob has a substructure: 401 * String type 402 * if RSA: 403 * bignum1 404 * bignum2 405 * if DSA: 406 * bignum1,2,3,4 407 */ 408 String keytype = p.getString(); 409 // System.out.println("KEXDH: " + keytype); 410 if (keytype.equals("ssh-rsa")) { 411 rsa_e = p.getMpInt(); 412 rsa_n = p.getMpInt(); 413 result = "\n\rSSH-RSA (" + rsa_n + "," + rsa_e + ")\n\r"; 414 } else { 415 return "\n\rUnsupported kexdh algorithm " + keytype + "!\n\r"; 416 } 417 BigInteger dhserverpub = p.getMpInt(); 418 result += "DH Server Pub: " + dhserverpub + "\n\r"; 419 420 /* signature is a new blob, length is Int32. */ 421 /* 422 * RSA: 423 * String type (ssh-rsa) 424 * Int32/byte[] signed signature 425 */ 426 int siglen = p.getInt32(); 427 String sigstr = p.getString(); 428 result += "Signature: ktype is " + sigstr + "\r\n"; 429 byte sigdata[] = p.getBytes(p.getInt32()); 430 431 return result; 432 } 433 default: 434 return "SSH2: handlePacket2 Unknown type " + p.getType(); 435 } 436 return ""; 437 } 438 439 440 private String handlePacket1(SshPacket1 p) 441 throws IOException { //the message to handle is data and its length is 442 443 byte b; // of course, byte is a signed entity (-128 -> 127) 444 445 //we have to deal with data.... 446 447 // if (debug > 0) 448 // System.out.println("1 packet to handle, type " + p.getType()); 449 450 451 switch (p.getType()) { 452 case SSH_MSG_IGNORE: 453 return ""; 454 455 case SSH_MSG_DISCONNECT: 456 String str = p.getString(); 457 disconnect(); 458 return str; 459 460 case SSH_SMSG_PUBLIC_KEY: 461 byte[] anti_spoofing_cookie; //8 bytes 462 byte[] server_key_bits; //32-bit int 463 byte[] server_key_public_exponent; //mp-int 464 byte[] server_key_public_modulus; //mp-int 465 byte[] host_key_bits; //32-bit int 466 byte[] host_key_public_exponent; //mp-int 467 byte[] host_key_public_modulus; //mp-int 468 byte[] protocol_flags; //32-bit int 469 byte[] supported_ciphers_mask; //32-bit int 470 byte[] supported_authentications_mask; //32-bit int 471 472 anti_spoofing_cookie = p.getBytes(8); 473 server_key_bits = p.getBytes(4); 474 server_key_public_exponent = p.getMpInt(); 475 server_key_public_modulus = p.getMpInt(); 476 host_key_bits = p.getBytes(4); 477 host_key_public_exponent = p.getMpInt(); 478 host_key_public_modulus = p.getMpInt(); 479 protocol_flags = p.getBytes(4); 480 supported_ciphers_mask = p.getBytes(4); 481 supported_authentications_mask = p.getBytes(4); 482 483 // We have completely received the PUBLIC_KEY 484 // We prepare the answer ... 485 486 String ret = Send_SSH_CMSG_SESSION_KEY( 487 anti_spoofing_cookie, server_key_public_modulus, 488 host_key_public_modulus, supported_ciphers_mask, 489 server_key_public_exponent, host_key_public_exponent 490 ); 491 if (ret != null) 492 return ret; 493 494 // we check if MD5(server_key_public_exponent) is equals to the 495 // applet parameter if any . 496 if (hashHostKey != null && hashHostKey.compareTo("") != 0) { 497 // we compute hashHostKeyBis the hash value in hexa of 498 // host_key_public_modulus 499 byte[] Md5_hostKey = md5.digest(host_key_public_modulus); 500 String hashHostKeyBis = ""; 501 for (int i = 0; i < Md5_hostKey.length; i++) { 502 String hex = ""; 503 int[] v = new int[2]; 504 v[0] = (Md5_hostKey[i] & 240) >> 4; 505 v[1] = (Md5_hostKey[i] & 15); 506 for (int j = 0; j < 1; j++) 507 switch (v[j]) { 508 case 10: 509 hex += "a"; 510 break; 511 case 11: 512 hex += "b"; 513 break; 514 case 12: 515 hex += "c"; 516 break; 517 case 13: 518 hex += "d"; 519 break; 520 case 14: 521 hex += "e"; 522 break; 523 case 15: 524 hex += "f"; 525 break; 526 default : 527 hex += String.valueOf(v[j]); 528 break; 529 } 530 hashHostKeyBis = hashHostKeyBis + hex; 531 } 532 //we compare the 2 values 533 if (hashHostKeyBis.compareTo(hashHostKey) != 0) { 534 login = password = ""; 535 return "\nHash value of the host key not correct \r\n"; 536 // + "login & password have been reset \r\n" 537 // + "- erase the 'hashHostKey' parameter in the Html\r\n" 538 // + "(it is used for auhentificating the server and " 539 // + "prevent you from connecting \r\n" 540 // + "to any other)\r\n"; 541 } 542 } 543 break; 544 545 case SSH_SMSG_SUCCESS: 546 // if (debug > 0) 547 // System.out.println("SSH_SMSG_SUCCESS (last packet was " + lastPacketSentType + ")"); 548 if (lastPacketSentType == SSH_CMSG_SESSION_KEY) { 549 //we have succefully sent the session key !! (at last :-) ) 550 Send_SSH_CMSG_USER(); 551 break; 552 } 553 554 if (lastPacketSentType == SSH_CMSG_USER) { 555 // authentication is NOT needed for this user 556 Send_SSH_CMSG_REQUEST_PTY(); //request a pseudo-terminal 557 return "\nEmpty password login.\r\n"; 558 } 559 560 if (lastPacketSentType == SSH_CMSG_AUTH_PASSWORD) {// password correct !!! 561 //yahoo 562 // if (debug > 0) 563 // System.out.println("login succesful"); 564 565 //now we have to start the interactive session ... 566 Send_SSH_CMSG_REQUEST_PTY(); //request a pseudo-terminal 567 return "\nLogin & password accepted\r\n"; 568 } 569 570 if (lastPacketSentType == SSH_CMSG_REQUEST_PTY) {// pty accepted !! 571 /* we can send data with a pty accepted ... no need for a shell. */ 572 cansenddata = true; 573 if (dataToSend != null) { 574 Send_SSH_CMSG_STDIN_DATA(dataToSend); 575 dataToSend = null; 576 } 577 Send_SSH_CMSG_EXEC_SHELL(); //we start a shell 578 break; 579 } 580 if (lastPacketSentType == SSH_CMSG_EXEC_SHELL) {// shell is running ... 581 /* empty */ 582 } 583 584 break; 585 586 case SSH_SMSG_FAILURE: 587 if (lastPacketSentType == SSH_CMSG_AUTH_PASSWORD) {// password incorrect ??? 588 // System.out.println("failed to log in"); 589 disconnect(); 590 return "\nLogin & password not accepted\r\n"; 591 } 592 if (lastPacketSentType == SSH_CMSG_USER) { 593 // authentication is needed for the given user 594 // (in most cases that's true) 595 Send_SSH_CMSG_AUTH_PASSWORD(); 596 break; 597 } 598 599 if (lastPacketSentType == SSH_CMSG_REQUEST_PTY) {// pty not accepted !! 600 break; 601 } 602 break; 603 604 case SSH_SMSG_STDOUT_DATA: //receive some data from the server 605 return p.getString(); 606 607 case SSH_SMSG_STDERR_DATA: //receive some error data from the server 608 // if(debug > 1) 609 str = "Error : " + p.getString(); 610 // System.out.println("SshIO.handlePacket : " + "STDERR_DATA " + str); 611 return str; 612 613 case SSH_SMSG_EXITSTATUS: //sent by the server to indicate that 614 // the client program has terminated. 615 //32-bit int exit status of the command 616 int value = p.getInt32(); 617 Send_SSH_CMSG_EXIT_CONFIRMATION(); 618 // System.out.println("SshIO : Exit status " + value); 619 disconnect(); 620 break; 621 622 case SSH_MSG_DEBUG: 623 str = p.getString(); 624 // if (debug > 0) { 625 // System.out.println("SshIO.handlePacket : " + " DEBUG " + str); 626 627 // bad bad bad bad bad. We should not do actions in DEBUG messages, 628 // but apparently some SSH demons does not send SSH_SMSG_FAILURE for 629 // just USER CMS. 630 /* 631 if(lastPacketSentType==SSH_CMSG_USER) { 632 Send_SSH_CMSG_AUTH_PASSWORD(); 633 break; 634 } 635 */ 636 // return str; 637 // } 638 return ""; 639 640 default: 641 // System.err.print("SshIO.handlePacket1: Packet Type unknown: " + p.getType()); 642 break; 643 644 }// switch(b) 645 return ""; 646 } // handlePacket 647 648 private void sendPacket1(SshPacket1 packet) throws IOException { 649 write(packet.getPayLoad(crypto)); 650 lastPacketSentType = packet.getType(); 651 } 652 653 private void sendPacket2(SshPacket2 packet) throws IOException { 654 write(packet.getPayLoad(crypto, outgoingseq)); 655 outgoingseq++; 656 lastPacketSentType = packet.getType(); 657 } 658 659 // 660 // Send_SSH_CMSG_SESSION_KEY 661 // Create : 662 // the session_id, 663 // the session_key, 664 // the Xored session_key, 665 // the double_encrypted session key 666 // send SSH_CMSG_SESSION_KEY 667 // Turn the encryption on (initialise the block cipher) 668 // 669 670 private String Send_SSH_CMSG_SESSION_KEY(byte[] anti_spoofing_cookie, 671 byte[] server_key_public_modulus, 672 byte[] host_key_public_modulus, 673 byte[] supported_ciphers_mask, 674 byte[] server_key_public_exponent, 675 byte[] host_key_public_exponent) 676 throws IOException { 677 678 String str; 679 int boffset; 680 681 byte cipher_types; //encryption types 682 byte[] session_key; //mp-int 683 684 // create the session id 685 // session_id = md5(hostkey->n || servkey->n || cookie) //protocol V 1.5. (we use this one) 686 // session_id = md5(servkey->n || hostkey->n || cookie) //protocol V 1.1.(Why is it different ??) 687 // 688 689 byte[] session_id_byte = new byte[host_key_public_modulus.length + server_key_public_modulus.length + anti_spoofing_cookie.length]; 690 691 System.arraycopy(host_key_public_modulus, 0, session_id_byte, 0, host_key_public_modulus.length); 692 System.arraycopy(server_key_public_modulus, 0, session_id_byte, host_key_public_modulus.length, server_key_public_modulus.length); 693 System.arraycopy(anti_spoofing_cookie, 0, session_id_byte, host_key_public_modulus.length + server_key_public_modulus.length, anti_spoofing_cookie.length); 694 695 byte[] hash_md5 = md5.digest(session_id_byte); 696 697 698 // SSH_CMSG_SESSION_KEY : Sent by the client 699 // 1 byte cipher_type (must be one of the supported values) 700 // 8 bytes anti_spoofing_cookie (must match data sent by the server) 701 // mp-int double-encrypted session key (uses the session-id) 702 // 32-bit int protocol_flags 703 // 704 if ((supported_ciphers_mask[3] & (byte) (1 << SSH_CIPHER_BLOWFISH)) != 0) { 705 cipher_types = (byte) SSH_CIPHER_BLOWFISH; 706 cipher_type = "Blowfish"; 707 } else { 708 if ((supported_ciphers_mask[3] & (1 << SSH_CIPHER_IDEA)) != 0) { 709 cipher_types = (byte) SSH_CIPHER_IDEA; 710 cipher_type = "IDEA"; 711 } else { 712 if ((supported_ciphers_mask[3] & (1 << SSH_CIPHER_3DES)) != 0) { 713 cipher_types = (byte) SSH_CIPHER_3DES; 714 cipher_type = "DES3"; 715 } else { 716 if ((supported_ciphers_mask[3] & (1 << SSH_CIPHER_DES)) != 0) { 717 cipher_types = (byte) SSH_CIPHER_DES; 718 cipher_type = "DES"; 719 } else { 720 // System.err.println("SshIO: remote server does not supported IDEA, BlowFish or 3DES, support cypher mask is " + supported_ciphers_mask[3] + ".\n"); 721 disconnect(); 722 return "\rRemote server does not support IDEA/Blowfish/3DES blockcipher, closing connection.\r\n"; 723 } 724 } 725 } 726 } 727 // if (debug > 0) 728 // System.out.println("SshIO: Using " + cipher_type + " blockcipher.\n"); 729 730 731 // anti_spoofing_cookie : the same 732 // double_encrypted_session_key : 733 // 32 bytes of random bits 734 // Xor the 16 first bytes with the session-id 735 // encrypt with the server_key_public (small) then the host_key_public(big) using RSA. 736 // 737 738 //32 bytes of random bits 739 byte[] random_bits1 = new byte[16], random_bits2 = new byte[16]; 740 741 742 /// java.util.Date date = new java.util.Date(); ////the number of milliseconds since January 1, 1970, 00:00:00 GMT. 743 //Math.random() a pseudorandom double between 0.0 and 1.0. 744 random_bits2 = random_bits1 = 745 // md5.hash("" + Math.random() * (new java.util.Date()).getDate()); 746 md5.digest(("" + rnd.nextLong() * (new java.util.Date()).getTime()).getBytes()); // RADEK - zase RANDOM 747 748 random_bits1 = md5.digest(SshMisc.addArrayOfBytes(md5.digest((password + login).getBytes()), 749 random_bits1)); 750 random_bits2 = md5.digest(SshMisc.addArrayOfBytes(md5.digest((password + login).getBytes()), 751 random_bits2)); 752 753 // SecureRandom random = new java.security.SecureRandom(random_bits1); //no supported by netscape :-( 754 // random.nextBytes(random_bits1); 755 // random.nextBytes(random_bits2); 756 757 session_key = SshMisc.addArrayOfBytes(random_bits1, random_bits2); 758 759 //Xor the 16 first bytes with the session-id 760 byte[] session_keyXored = SshMisc.XORArrayOfBytes(random_bits1, hash_md5); 761 session_keyXored = SshMisc.addArrayOfBytes(session_keyXored, random_bits2); 762 763 //We encrypt now!! 764 byte[] encrypted_session_key = 765 SshCrypto.encrypteRSAPkcs1Twice(session_keyXored, 766 server_key_public_exponent, 767 server_key_public_modulus, 768 host_key_public_exponent, 769 host_key_public_modulus); 770 771 // protocol_flags :protocol extension cf. page 18 772 int protocol_flags = 0; /* currently 0 */ 773 774 SshPacket1 packet = new SshPacket1(SSH_CMSG_SESSION_KEY); 775 packet.putByte((byte) cipher_types); 776 packet.putBytes(anti_spoofing_cookie); 777 packet.putBytes(encrypted_session_key); 778 packet.putInt32(protocol_flags); 779 sendPacket1(packet); 780 crypto = new SshCrypto(cipher_type, session_key); 781 return ""; 782 } 783 784 /** 785 * SSH_CMSG_USER 786 * string user login name on server 787 */ 788 private String Send_SSH_CMSG_USER() throws IOException { 789 // if (debug > 0) System.err.println("Send_SSH_CMSG_USER(" + login + ")"); 790 791 SshPacket1 p = new SshPacket1(SSH_CMSG_USER); 792 p.putString(login); 793 sendPacket1(p); 794 795 return ""; 796 } 797 798 /** 799 * Send_SSH_CMSG_AUTH_PASSWORD 800 * string user password 801 */ 802 private String Send_SSH_CMSG_AUTH_PASSWORD() throws IOException { 803 SshPacket1 p = new SshPacket1(SSH_CMSG_AUTH_PASSWORD); 804 p.putString(password); 805 sendPacket1(p); 806 return ""; 807 } 808 809 /** 810 * Send_SSH_CMSG_EXEC_SHELL 811 * (no arguments) 812 * Starts a shell (command interpreter), and enters interactive 813 * session mode. 814 */ 815 private String Send_SSH_CMSG_EXEC_SHELL() throws IOException { 816 SshPacket1 packet = new SshPacket1(SSH_CMSG_EXEC_SHELL); 817 sendPacket1(packet); 818 return ""; 819 } 820 821 /** 822 * Send_SSH_CMSG_STDIN_DATA 823 * 824 */ 825 private String Send_SSH_CMSG_STDIN_DATA(String str) throws IOException { 826 SshPacket1 packet = new SshPacket1(SSH_CMSG_STDIN_DATA); 827 packet.putString(str); 828 sendPacket1(packet); 829 return ""; 830 } 831 832 /** 833 * Send_SSH_CMSG_REQUEST_PTY 834 * string TERM environment variable value (e.g. vt100) 835 * 32-bit int terminal height, rows (e.g., 24) 836 * 32-bit int terminal width, columns (e.g., 80) 837 * 32-bit int terminal width, pixels (0 if no graphics) (e.g., 480) 838 */ 839 private String Send_SSH_CMSG_REQUEST_PTY() throws IOException { 840 SshPacket1 p = new SshPacket1(SSH_CMSG_REQUEST_PTY); 841 842 p.putString(Telnet.emulation.getTerminalID()); 843 p.putInt32(Telnet.emulation.height); // Int32 rows 844 p.putInt32(Telnet.emulation.width); // Int32 columns 845 p.putInt32(0); // Int32 x pixels 846 p.putInt32(0); // Int32 y pixels 847 p.putByte((byte) 0); // Int8 terminal modes 848 sendPacket1(p); 849 return ""; 850 } 851 852 private String Send_SSH_CMSG_EXIT_CONFIRMATION() throws IOException { 853 SshPacket1 packet = new SshPacket1(SSH_CMSG_EXIT_CONFIRMATION); 854 sendPacket1(packet); 855 return ""; 856 } 857 } |