148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood/* 248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Please refer to the LICENSE.txt for licensing details. 448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodpackage ch.ethz.ssh2.transport; 648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport java.io.IOException; 848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport java.io.InputStream; 948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport java.io.OutputStream; 1048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 1148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport ch.ethz.ssh2.util.StringEncoder; 1248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 1348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood/** 1448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * ClientServerHello. 1548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 1648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @author Christian Plattner 1748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @version $Id: ClientServerHello.java 33 2011-05-28 21:59:37Z dkocher@sudo.ch $ 1848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 1948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodpublic class ClientServerHello 2048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood{ 2148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood String server_line; 2248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood String client_line; 2348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 2448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood String server_versioncomment; 2548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 2648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public static int readLineRN(InputStream is, byte[] buffer) throws IOException 2748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 2848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int pos = 0; 2948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood boolean need10 = false; 3048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int len = 0; 3148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood while (true) 3248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 3348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int c = is.read(); 3448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (c == -1) 3548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IOException("Premature connection close"); 3648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 3748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood buffer[pos++] = (byte) c; 3848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 3948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (c == 13) 4048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 4148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood need10 = true; 4248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood continue; 4348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 4448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 4548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (c == 10) 4648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood break; 4748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 4848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (need10 == true) 4948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IOException("Malformed line sent by the server, the line does not end correctly."); 5048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 5148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood len++; 5248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (pos >= buffer.length) 5348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IOException("The server sent a too long line."); 5448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 5548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 5648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return len; 5748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 5848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 5948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public ClientServerHello(String identification, InputStream bi, OutputStream bo) throws IOException 6048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 6148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood client_line = "SSH-2.0-" + identification; 6248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 6348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood bo.write(StringEncoder.GetBytes(client_line + "\r\n")); 6448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood bo.flush(); 6548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 6648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood byte[] serverVersion = new byte[512]; 6748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 6848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood for (int i = 0; i < 50; i++) 6948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 7048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int len = readLineRN(bi, serverVersion); 7148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 7248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood server_line = StringEncoder.GetString(serverVersion, 0, len); 7348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 7448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (server_line.startsWith("SSH-")) 7548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood break; 7648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 7748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 7848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (server_line.startsWith("SSH-") == false) 7948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IOException( 8048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood "Malformed server identification string. There was no line starting with 'SSH-' amongst the first 50 lines."); 8148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 8248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (server_line.startsWith("SSH-1.99-")) 8348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood server_versioncomment = server_line.substring(9); 8448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood else if (server_line.startsWith("SSH-2.0-")) 8548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood server_versioncomment = server_line.substring(8); 8648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood else 8748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IOException("Server uses incompatible protocol, it is not SSH-2 compatible."); 8848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 8948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 9048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 9148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @return Returns the client_versioncomment. 9248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 9348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public byte[] getClientString() 9448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 9548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return StringEncoder.GetBytes(client_line); 9648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 9748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 9848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 9948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @return Returns the server_versioncomment. 10048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 10148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public byte[] getServerString() 10248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 10348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return StringEncoder.GetBytes(server_line); 10448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 10548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood} 106