KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > ch > ethz > ssh2 > transport > TransportConnection


1
2 package ch.ethz.ssh2.transport;
3
4 import java.io.IOException JavaDoc;
5 import java.io.InputStream JavaDoc;
6 import java.io.OutputStream JavaDoc;
7 import java.security.SecureRandom JavaDoc;
8
9 import ch.ethz.ssh2.crypto.cipher.BlockCipher;
10 import ch.ethz.ssh2.crypto.cipher.CipherInputStream;
11 import ch.ethz.ssh2.crypto.cipher.CipherOutputStream;
12 import ch.ethz.ssh2.crypto.cipher.NullCipher;
13 import ch.ethz.ssh2.crypto.digest.MAC;
14 import ch.ethz.ssh2.log.Logger;
15 import ch.ethz.ssh2.packets.Packets;
16
17 /**
18  * TransportConnection.
19  *
20  * @author Christian Plattner, plattner@inf.ethz.ch
21  * @version $Id: TransportConnection.java,v 1.8 2006/02/14 19:43:15 cplattne Exp $
22  */

23 public class TransportConnection
24 {
25     private static final Logger log = Logger.getLogger(TransportConnection.class);
26
27     int send_seq_number = 0;
28
29     int recv_seq_number = 0;
30
31     CipherInputStream cis;
32
33     CipherOutputStream cos;
34
35     boolean useRandomPadding = false;
36
37     /* Depends on current MAC and CIPHER */
38
39     MAC send_mac;
40
41     byte[] send_mac_buffer;
42
43     int send_padd_blocksize = 8;
44
45     MAC recv_mac;
46
47     byte[] recv_mac_buffer;
48
49     byte[] recv_mac_buffer_cmp;
50
51     int recv_padd_blocksize = 8;
52
53     /* won't change */
54
55     final byte[] send_padding_buffer = new byte[256];
56
57     final byte[] send_packet_header_buffer = new byte[5];
58
59     final byte[] recv_padding_buffer = new byte[256];
60
61     final byte[] recv_packet_header_buffer = new byte[5];
62
63     boolean recv_packet_header_present = false;
64
65     ClientServerHello csh;
66
67     final SecureRandom JavaDoc rnd;
68
69     public TransportConnection(InputStream JavaDoc is, OutputStream JavaDoc os, SecureRandom JavaDoc rnd)
70     {
71         this.cis = new CipherInputStream(new NullCipher(), is);
72         this.cos = new CipherOutputStream(new NullCipher(), os);
73         this.rnd = rnd;
74     }
75
76     public void changeRecvCipher(BlockCipher bc, MAC mac)
77     {
78         cis.changeCipher(bc);
79         recv_mac = mac;
80         recv_mac_buffer = (mac != null) ? new byte[mac.size()] : null;
81         recv_mac_buffer_cmp = (mac != null) ? new byte[mac.size()] : null;
82         recv_padd_blocksize = bc.getBlockSize();
83         if (recv_padd_blocksize < 8)
84             recv_padd_blocksize = 8;
85     }
86
87     public void changeSendCipher(BlockCipher bc, MAC mac)
88     {
89         if ((bc instanceof NullCipher) == false)
90         {
91             /* Only use zero byte padding for the first few packets */
92             useRandomPadding = true;
93             /* Once we start encrypting, there is no way back */
94         }
95
96         cos.changeCipher(bc);
97         send_mac = mac;
98         send_mac_buffer = (mac != null) ? new byte[mac.size()] : null;
99         send_padd_blocksize = bc.getBlockSize();
100         if (send_padd_blocksize < 8)
101             send_padd_blocksize = 8;
102     }
103
104     public void sendMessage(byte[] message) throws IOException JavaDoc
105     {
106         sendMessage(message, 0, message.length, 0);
107     }
108
109     public void sendMessage(byte[] message, int off, int len) throws IOException JavaDoc
110     {
111         sendMessage(message, off, len, 0);
112     }
113
114     public int getPacketOverheadEstimate()
115     {
116         // return an estimate for the paket overhead (for send operations)
117
return 5 + 4 + (send_padd_blocksize - 1) + send_mac_buffer.length;
118     }
119
120     public void sendMessage(byte[] message, int off, int len, int padd) throws IOException JavaDoc
121     {
122         if (padd < 4)
123             padd = 4;
124         else if (padd > 64)
125             padd = 64;
126
127         int packet_len = 5 + len + padd; /* Minimum allowed padding is 4 */
128
129         int slack = packet_len % send_padd_blocksize;
130
131         if (slack != 0)
132         {
133             packet_len += (send_padd_blocksize - slack);
134         }
135
136         if (packet_len < 16)
137             packet_len = 16;
138
139         int padd_len = packet_len - (5 + len);
140
141         if (useRandomPadding)
142         {
143             for (int i = 0; i < padd_len; i = i + 4)
144             {
145                 /*
146                  * don't waste calls to rnd.nextInt() (by using only 8bit of the
147                  * output). just believe me: even though we may write here up to 3
148                  * bytes which won't be used, there is no "buffer overflow" (i.e.,
149                  * arrayindexoutofbounds). the padding buffer is big enough =) (256
150                  * bytes, and that is bigger than any current cipher block size + 64).
151                  */

152
153                 int r = rnd.nextInt();
154                 send_padding_buffer[i] = (byte) r;
155                 send_padding_buffer[i + 1] = (byte) (r >> 8);
156                 send_padding_buffer[i + 2] = (byte) (r >> 16);
157                 send_padding_buffer[i + 3] = (byte) (r >> 24);
158             }
159         }
160         else
161         {
162             /* use zero padding for unencrypted traffic */
163             for (int i = 0; i < padd_len; i++)
164                 send_padding_buffer[i] = 0;
165             /* Actually this code is paranoid: we never filled any
166              * bytes into the padding buffer so far, therefore it should
167              * consist of zeros only.
168              */

169         }
170
171         send_packet_header_buffer[0] = (byte) ((packet_len - 4) >> 24);
172         send_packet_header_buffer[1] = (byte) ((packet_len - 4) >> 16);
173         send_packet_header_buffer[2] = (byte) ((packet_len - 4) >> 8);
174         send_packet_header_buffer[3] = (byte) ((packet_len - 4));
175         send_packet_header_buffer[4] = (byte) padd_len;
176
177         cos.write(send_packet_header_buffer, 0, 5);
178         cos.write(message, off, len);
179         cos.write(send_padding_buffer, 0, padd_len);
180
181         if (send_mac != null)
182         {
183             send_mac.initMac(send_seq_number);
184             send_mac.update(send_packet_header_buffer, 0, 5);
185             send_mac.update(message, off, len);
186             send_mac.update(send_padding_buffer, 0, padd_len);
187
188             send_mac.getMac(send_mac_buffer, 0);
189             cos.writePlain(send_mac_buffer, 0, send_mac_buffer.length);
190         }
191
192         cos.flush();
193
194         if (log.isEnabled())
195         {
196             log.log(90, "Sent " + Packets.getMessageName(message[off] & 0xff) + " " + len + " bytes payload");
197         }
198
199         send_seq_number++;
200     }
201
202     public int peekNextMessageLength() throws IOException JavaDoc
203     {
204         if (recv_packet_header_present == false)
205         {
206             cis.read(recv_packet_header_buffer, 0, 5);
207             recv_packet_header_present = true;
208         }
209
210         int packet_length = ((recv_packet_header_buffer[0] & 0xff) << 24)
211                 | ((recv_packet_header_buffer[1] & 0xff) << 16) | ((recv_packet_header_buffer[2] & 0xff) << 8)
212                 | ((recv_packet_header_buffer[3] & 0xff));
213
214         int padding_length = recv_packet_header_buffer[4] & 0xff;
215
216         if (packet_length > 35000 || packet_length < 12)
217             throw new IOException JavaDoc("Illegal packet size! (" + packet_length + ")");
218
219         int payload_length = packet_length - padding_length - 1;
220
221         if (payload_length < 0)
222             throw new IOException JavaDoc("Illegal padding_length in packet from remote (" + padding_length + ")");
223
224         return payload_length;
225     }
226
227     public int receiveMessage(byte buffer[], int off, int len) throws IOException JavaDoc
228     {
229         if (recv_packet_header_present == false)
230         {
231             cis.read(recv_packet_header_buffer, 0, 5);
232         }
233         else
234             recv_packet_header_present = false;
235
236         int packet_length = ((recv_packet_header_buffer[0] & 0xff) << 24)
237                 | ((recv_packet_header_buffer[1] & 0xff) << 16) | ((recv_packet_header_buffer[2] & 0xff) << 8)
238                 | ((recv_packet_header_buffer[3] & 0xff));
239
240         int padding_length = recv_packet_header_buffer[4] & 0xff;
241
242         if (packet_length > 35000 || packet_length < 12)
243             throw new IOException JavaDoc("Illegal packet size! (" + packet_length + ")");
244
245         int payload_length = packet_length - padding_length - 1;
246
247         if (payload_length < 0)
248             throw new IOException JavaDoc("Illegal padding_length in packet from remote (" + padding_length + ")");
249
250         if (payload_length >= len)
251             throw new IOException JavaDoc("Receive buffer too small (" + len + ", need " + payload_length + ")");
252
253         cis.read(buffer, off, payload_length);
254         cis.read(recv_padding_buffer, 0, padding_length);
255
256         if (recv_mac != null)
257         {
258             cis.readPlain(recv_mac_buffer, 0, recv_mac_buffer.length);
259
260             recv_mac.initMac(recv_seq_number);
261             recv_mac.update(recv_packet_header_buffer, 0, 5);
262             recv_mac.update(buffer, off, payload_length);
263             recv_mac.update(recv_padding_buffer, 0, padding_length);
264             recv_mac.getMac(recv_mac_buffer_cmp, 0);
265
266             for (int i = 0; i < recv_mac_buffer.length; i++)
267             {
268                 if (recv_mac_buffer[i] != recv_mac_buffer_cmp[i])
269                     throw new IOException JavaDoc("Remote sent corrupt MAC.");
270             }
271         }
272
273         recv_seq_number++;
274
275         if (log.isEnabled())
276         {
277             log.log(90, "Received " + Packets.getMessageName(buffer[off] & 0xff) + " " + payload_length
278                     + " bytes payload");
279         }
280
281         return payload_length;
282     }
283 }
284
Popular Tags