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 Lockwoodimport java.security.SecureRandom; 1148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 1248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport ch.ethz.ssh2.crypto.cipher.BlockCipher; 1348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport ch.ethz.ssh2.crypto.cipher.CipherInputStream; 1448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport ch.ethz.ssh2.crypto.cipher.CipherOutputStream; 1548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport ch.ethz.ssh2.crypto.cipher.NullCipher; 1648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport ch.ethz.ssh2.crypto.digest.MAC; 1748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport ch.ethz.ssh2.log.Logger; 1848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport ch.ethz.ssh2.packets.Packets; 1948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 2048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood/** 2148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * TransportConnection. 2248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 2348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @author Christian Plattner 2448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * @version $Id: TransportConnection.java 41 2011-06-02 10:36:41Z dkocher@sudo.ch $ 2548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 2648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodpublic class TransportConnection 2748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood{ 2848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood private static final Logger log = Logger.getLogger(TransportConnection.class); 2948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 3048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int send_seq_number = 0; 3148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 3248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int recv_seq_number = 0; 3348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 3448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood CipherInputStream cis; 3548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 3648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood CipherOutputStream cos; 3748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 3848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood boolean useRandomPadding = false; 3948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 4048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* Depends on current MAC and CIPHER */ 4148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 4248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood MAC send_mac; 4348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 4448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood byte[] send_mac_buffer; 4548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 4648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int send_padd_blocksize = 8; 4748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 4848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood MAC recv_mac; 4948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 5048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood byte[] recv_mac_buffer; 5148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 5248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood byte[] recv_mac_buffer_cmp; 5348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 5448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int recv_padd_blocksize = 8; 5548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 5648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* won't change */ 5748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 5848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood final byte[] send_padding_buffer = new byte[256]; 5948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 6048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood final byte[] send_packet_header_buffer = new byte[5]; 6148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 6248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood final byte[] recv_padding_buffer = new byte[256]; 6348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 6448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood final byte[] recv_packet_header_buffer = new byte[5]; 6548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 6648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood boolean recv_packet_header_present = false; 6748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 6848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood ClientServerHello csh; 6948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 7048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood final SecureRandom rnd; 7148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 7248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public TransportConnection(InputStream is, OutputStream os, SecureRandom rnd) 7348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 7448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood this.cis = new CipherInputStream(new NullCipher(), is); 7548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood this.cos = new CipherOutputStream(new NullCipher(), os); 7648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood this.rnd = rnd; 7748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 7848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 7948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public void changeRecvCipher(BlockCipher bc, MAC mac) 8048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 8148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood cis.changeCipher(bc); 8248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood recv_mac = mac; 8348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood recv_mac_buffer = (mac != null) ? new byte[mac.size()] : null; 8448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood recv_mac_buffer_cmp = (mac != null) ? new byte[mac.size()] : null; 8548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood recv_padd_blocksize = bc.getBlockSize(); 8648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (recv_padd_blocksize < 8) 8748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood recv_padd_blocksize = 8; 8848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 8948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 9048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public void changeSendCipher(BlockCipher bc, MAC mac) 9148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 9248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if ((bc instanceof NullCipher) == false) 9348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 9448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* Only use zero byte padding for the first few packets */ 9548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood useRandomPadding = true; 9648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* Once we start encrypting, there is no way back */ 9748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 9848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 9948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood cos.changeCipher(bc); 10048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood send_mac = mac; 10148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood send_mac_buffer = (mac != null) ? new byte[mac.size()] : null; 10248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood send_padd_blocksize = bc.getBlockSize(); 10348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (send_padd_blocksize < 8) 10448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood send_padd_blocksize = 8; 10548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 10648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 10748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public void sendMessage(byte[] message) throws IOException 10848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 10948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood sendMessage(message, 0, message.length, 0); 11048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 11148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 11248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public void sendMessage(byte[] message, int off, int len) throws IOException 11348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 11448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood sendMessage(message, off, len, 0); 11548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 11648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 11748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public int getPacketOverheadEstimate() 11848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 11948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood // return an estimate for the paket overhead (for send operations) 12048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return 5 + 4 + (send_padd_blocksize - 1) + send_mac_buffer.length; 12148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 12248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 12348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public void sendMessage(byte[] message, int off, int len, int padd) throws IOException 12448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 12548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (padd < 4) 12648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood padd = 4; 12748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood else if (padd > 64) 12848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood padd = 64; 12948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 13048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int packet_len = 5 + len + padd; /* Minimum allowed padding is 4 */ 13148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 13248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int slack = packet_len % send_padd_blocksize; 13348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 13448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (slack != 0) 13548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 13648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood packet_len += (send_padd_blocksize - slack); 13748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 13848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 13948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (packet_len < 16) 14048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood packet_len = 16; 14148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 14248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int padd_len = packet_len - (5 + len); 14348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 14448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (useRandomPadding) 14548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 14648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood for (int i = 0; i < padd_len; i = i + 4) 14748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 14848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* 14948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * don't waste calls to rnd.nextInt() (by using only 8bit of the 15048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * output). just believe me: even though we may write here up to 3 15148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * bytes which won't be used, there is no "buffer overflow" (i.e., 15248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * arrayindexoutofbounds). the padding buffer is big enough =) (256 15348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * bytes, and that is bigger than any current cipher block size + 64). 15448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 15548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 15648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int r = rnd.nextInt(); 15748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood send_padding_buffer[i] = (byte) r; 15848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood send_padding_buffer[i + 1] = (byte) (r >> 8); 15948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood send_padding_buffer[i + 2] = (byte) (r >> 16); 16048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood send_padding_buffer[i + 3] = (byte) (r >> 24); 16148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 16248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 16348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood else 16448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 16548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* use zero padding for unencrypted traffic */ 16648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood for (int i = 0; i < padd_len; i++) 16748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood send_padding_buffer[i] = 0; 16848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* Actually this code is paranoid: we never filled any 16948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * bytes into the padding buffer so far, therefore it should 17048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * consist of zeros only. 17148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 17248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 17348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 17448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood send_packet_header_buffer[0] = (byte) ((packet_len - 4) >> 24); 17548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood send_packet_header_buffer[1] = (byte) ((packet_len - 4) >> 16); 17648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood send_packet_header_buffer[2] = (byte) ((packet_len - 4) >> 8); 17748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood send_packet_header_buffer[3] = (byte) ((packet_len - 4)); 17848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood send_packet_header_buffer[4] = (byte) padd_len; 17948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 18048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood cos.write(send_packet_header_buffer, 0, 5); 18148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood cos.write(message, off, len); 18248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood cos.write(send_padding_buffer, 0, padd_len); 18348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 18448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (send_mac != null) 18548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 18648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood send_mac.initMac(send_seq_number); 18748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood send_mac.update(send_packet_header_buffer, 0, 5); 18848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood send_mac.update(message, off, len); 18948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood send_mac.update(send_padding_buffer, 0, padd_len); 19048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 19148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood send_mac.getMac(send_mac_buffer, 0); 19248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood cos.writePlain(send_mac_buffer, 0, send_mac_buffer.length); 19348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 19448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 19548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood cos.flush(); 19648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 19748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (log.isDebugEnabled()) 19848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 19948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood log.debug("Sent " + Packets.getMessageName(message[off] & 0xff) + " " + len + " bytes payload"); 20048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 20148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 20248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood send_seq_number++; 20348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 20448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 20548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public int peekNextMessageLength() throws IOException 20648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 20748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (recv_packet_header_present == false) 20848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 20948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood cis.read(recv_packet_header_buffer, 0, 5); 21048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood recv_packet_header_present = true; 21148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 21248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 21348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int packet_length = ((recv_packet_header_buffer[0] & 0xff) << 24) 21448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood | ((recv_packet_header_buffer[1] & 0xff) << 16) | ((recv_packet_header_buffer[2] & 0xff) << 8) 21548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood | ((recv_packet_header_buffer[3] & 0xff)); 21648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 21748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int padding_length = recv_packet_header_buffer[4] & 0xff; 21848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 21948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (packet_length > 35000 || packet_length < 12) 22048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IOException("Illegal packet size! (" + packet_length + ")"); 22148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 22248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int payload_length = packet_length - padding_length - 1; 22348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 22448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (payload_length < 0) 22548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IOException("Illegal padding_length in packet from remote (" + padding_length + ")"); 22648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 22748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return payload_length; 22848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 22948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 23048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public int receiveMessage(byte buffer[], int off, int len) throws IOException 23148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 23248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (recv_packet_header_present == false) 23348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 23448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood cis.read(recv_packet_header_buffer, 0, 5); 23548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 23648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood else 23748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood recv_packet_header_present = false; 23848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 23948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int packet_length = ((recv_packet_header_buffer[0] & 0xff) << 24) 24048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood | ((recv_packet_header_buffer[1] & 0xff) << 16) | ((recv_packet_header_buffer[2] & 0xff) << 8) 24148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood | ((recv_packet_header_buffer[3] & 0xff)); 24248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 24348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int padding_length = recv_packet_header_buffer[4] & 0xff; 24448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 24548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (packet_length > 35000 || packet_length < 12) 24648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IOException("Illegal packet size! (" + packet_length + ")"); 24748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 24848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int payload_length = packet_length - padding_length - 1; 24948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 25048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (payload_length < 0) 25148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IOException("Illegal padding_length in packet from remote (" + padding_length + ")"); 25248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 25348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (payload_length >= len) 25448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IOException("Receive buffer too small (" + len + ", need " + payload_length + ")"); 25548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 25648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood cis.read(buffer, off, payload_length); 25748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood cis.read(recv_padding_buffer, 0, padding_length); 25848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 25948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (recv_mac != null) 26048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 26148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood cis.readPlain(recv_mac_buffer, 0, recv_mac_buffer.length); 26248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 26348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood recv_mac.initMac(recv_seq_number); 26448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood recv_mac.update(recv_packet_header_buffer, 0, 5); 26548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood recv_mac.update(buffer, off, payload_length); 26648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood recv_mac.update(recv_padding_buffer, 0, padding_length); 26748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood recv_mac.getMac(recv_mac_buffer_cmp, 0); 26848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 26948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood for (int i = 0; i < recv_mac_buffer.length; i++) 27048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 27148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (recv_mac_buffer[i] != recv_mac_buffer_cmp[i]) 27248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IOException("Remote sent corrupt MAC."); 27348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 27448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 27548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 27648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood recv_seq_number++; 27748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 27848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (log.isDebugEnabled()) 27948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 28048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood log.debug("Received " + Packets.getMessageName(buffer[off] & 0xff) + " " + payload_length 28148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood + " bytes payload"); 28248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 28348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 28448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return payload_length; 28548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 28648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood} 287