KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > team > internal > ccvs > ssh > Client


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.team.internal.ccvs.ssh;
12
13 /**
14  * An SSH 1.5 client..
15  */

16
17 import java.io.BufferedInputStream JavaDoc;
18 import java.io.IOException JavaDoc;
19 import java.io.InputStream JavaDoc;
20 import java.io.InterruptedIOException JavaDoc;
21 import java.io.OutputStream JavaDoc;
22 import java.math.BigInteger JavaDoc;
23 import java.net.Socket JavaDoc;
24
25 import org.eclipse.core.runtime.IProgressMonitor;
26 import org.eclipse.osgi.util.NLS;
27 import org.eclipse.team.internal.ccvs.core.connection.CVSAuthenticationException;
28 import org.eclipse.team.internal.ccvs.core.util.Util;
29 import org.eclipse.team.internal.core.streams.PollingInputStream;
30 import org.eclipse.team.internal.core.streams.PollingOutputStream;
31 import org.eclipse.team.internal.core.streams.TimeoutOutputStream;
32
33 public class Client {
34     // client identification string
35
private static final String JavaDoc clientId = "SSH-1.5-Java 1.2.2\n"; //$NON-NLS-1$
36

37     // server identification string
38
private static String JavaDoc serverId = null;
39
40     // maximum outgoing packet size
41
private static final int MAX_CLIENT_PACKET_SIZE = 1024;
42
43     // packet types
44
private static final int SSH_MSG_DISCONNECT = 1;
45     private static final int SSH_SMSG_PUBLIC_KEY = 2;
46     private static final int SSH_CMSG_SESSION_KEY = 3;
47     private static final int SSH_CMSG_USER = 4;
48     private static final int SSH_CMSG_AUTH_PASSWORD = 9;
49     private static final int SSH_CMSG_REQUEST_PTY = 10;
50     private static final int SSH_CMSG_EXEC_SHELL = 12;
51     private static final int SSH_CMSG_EXEC_CMD = 13;
52     private static final int SSH_SMSG_SUCCESS = 14;
53     private static final int SSH_SMSG_FAILURE = 15;
54     private static final int SSH_CMSG_STDIN_DATA = 16;
55     private static final int SSH_SMSG_STDOUT_DATA = 17;
56     private static final int SSH_SMSG_STDERR_DATA = 18;
57     private static final int SSH_SMSG_EXITSTATUS = 20;
58     private static final int SSH_CMSG_EXIT_CONFIRMATION = 33;
59     private static final int SSH_MSG_DEBUG = 36;
60
61     // cipher names
62
private static String JavaDoc[] cipherNames = { "None", "IDEA", "DES", "3DES", "TSS", "RC4", "Blowfish" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$
63

64     // cipher types
65
private static int SSH_CIPHER_BLOWFISH = 6;
66
67     // preferred cipher types
68
private int[] preferredCipherTypes = { SSH_CIPHER_BLOWFISH };
69
70     private String JavaDoc host;
71     private int port;
72     private String JavaDoc username;
73     private String JavaDoc password;
74     private String JavaDoc command;
75
76     private Socket JavaDoc socket;
77     private InputStream JavaDoc socketIn;
78     private PollingOutputStream socketOut;
79     private InputStream JavaDoc is;
80     private OutputStream JavaDoc os;
81     private boolean connected = false;
82     private int timeout = -1;
83
84     private Cipher cipher = null;
85
86     private class StandardInputStream extends InputStream JavaDoc {
87         private ServerPacket packet = null;
88         private InputStream JavaDoc buffer = null;
89         private boolean atEnd = false;
90         private boolean closed = false;
91
92         public int available() throws IOException JavaDoc {
93             if (closed) {
94                 throw new IOException JavaDoc(CVSSSHMessages.closed);
95             }
96
97             int available = buffer == null ? 0 : buffer.available();
98
99             if (available == 0 && socketIn.available() > 0) {
100                 fill();
101                 if (atEnd) {
102                     return 0;
103                 }
104                 available = buffer.available();
105             }
106
107             return available;
108         }
109
110         public void close() throws IOException JavaDoc {
111             if (!closed) {
112                 closed = true;
113                 if (packet != null) {
114                     packet.close(false);
115                     buffer = null;
116                     packet = null;
117                 }
118             }
119         }
120
121         public int read() throws IOException JavaDoc {
122             if (closed) {
123                 throw new IOException JavaDoc(CVSSSHMessages.closed);
124             }
125
126             if (atEnd) {
127                 return -1;
128             }
129
130             if (buffer == null || buffer.available() == 0) {
131                 fill();
132                 if (atEnd) {
133                     return -1;
134                 }
135             }
136
137             return buffer.read();
138         }
139
140         public int read(byte b[], int off, int len) throws IOException JavaDoc {
141             if (closed) {
142                 throw new IOException JavaDoc(CVSSSHMessages.closed);
143             }
144
145             if (atEnd) {
146                 return -1;
147             }
148
149             if (buffer == null || buffer.available() == 0) {
150                 fill();
151                 if (atEnd) {
152                     return -1;
153                 }
154             }
155
156             return buffer.read(b, off, len);
157         }
158
159         private void fill() throws IOException JavaDoc {
160             if (buffer != null) {
161                 buffer.close();
162             }
163
164             packet = skip_SSH_MSG_DEBUG();
165             int packetType = packet.getType();
166
167             switch (packetType) {
168                 case SSH_SMSG_STDOUT_DATA :
169                 case SSH_SMSG_STDERR_DATA :
170                 case SSH_MSG_DEBUG :
171                     buffer = packet.getInputStream();
172                     Misc.readInt(buffer);
173                     break;
174                 case SSH_SMSG_EXITSTATUS :
175                     buffer = null;
176                     atEnd = true;
177                     InputStream JavaDoc pis = packet.getInputStream();
178                     Misc.readInt(pis);
179                     pis.close();
180                     send(SSH_CMSG_EXIT_CONFIRMATION, null);
181                     break;
182                 case SSH_MSG_DISCONNECT :
183                     buffer = null;
184                     atEnd = true;
185                     handleDisconnect(packet.getInputStream());
186                     break;
187                 default :
188                     throw new IOException JavaDoc(NLS.bind(CVSSSHMessages.Client_packetType, (new Object JavaDoc[] {new Integer JavaDoc(packetType)})));
189             }
190         }
191         
192         private void handleDisconnect(InputStream JavaDoc in) throws IOException JavaDoc {
193             String JavaDoc description = null;
194             try {
195                 description = Misc.readString(in);
196             } catch (IOException JavaDoc e) {
197             } finally {
198                 in.close();
199             }
200             
201             // Log the description provided by the server
202
if (description == null) {
203                 description = CVSSSHMessages.Client_noDisconnectDescription;
204             }
205             
206             // Throw an IOException with the proper text
207
throw new IOException JavaDoc(NLS.bind(CVSSSHMessages.Client_disconnectDescription, (new Object JavaDoc[] {description})));
208         }
209     }
210
211     private class StandardOutputStream extends OutputStream JavaDoc {
212         private int MAX_BUFFER_SIZE = MAX_CLIENT_PACKET_SIZE;
213         private byte[] buffer = new byte[MAX_BUFFER_SIZE];
214         private int bufpos = 0;
215         private boolean closed = false;
216
217         public void close() throws IOException JavaDoc {
218             if (!closed) {
219                 try {
220                     flush();
221                 } finally {
222                     closed = true;
223                 }
224             }
225         }
226
227         public void flush() throws IOException JavaDoc {
228             if (closed) {
229                 throw new IOException JavaDoc(CVSSSHMessages.closed);
230             }
231
232             if (bufpos > 0) {
233                 send(SSH_CMSG_STDIN_DATA, buffer, 0, bufpos);
234                 bufpos = 0;
235             }
236         }
237
238         public void write(int b) throws IOException JavaDoc {
239             if (closed) {
240                 throw new IOException JavaDoc(CVSSSHMessages.closed);
241             }
242
243             buffer[bufpos++] = (byte) b;
244
245             if (bufpos == MAX_BUFFER_SIZE) {
246                 flush();
247             }
248         }
249
250         public void write(byte b[], int off, int len) throws IOException JavaDoc {
251             if (closed) {
252                 throw new IOException JavaDoc(CVSSSHMessages.closed);
253             }
254
255             int bytesWritten = 0;
256             int totalBytesWritten = 0;
257
258             if (bufpos > 0) {
259                 bytesWritten = Math.min(MAX_BUFFER_SIZE - bufpos, len);
260                 System.arraycopy(b, off, buffer, bufpos, bytesWritten);
261                 bufpos += bytesWritten;
262                 totalBytesWritten += bytesWritten;
263
264                 if (bufpos == MAX_BUFFER_SIZE) {
265                     flush();
266                 }
267             }
268
269             while (len - totalBytesWritten >= MAX_BUFFER_SIZE) {
270                 send(SSH_CMSG_STDIN_DATA, b, off + totalBytesWritten, MAX_BUFFER_SIZE);
271                 totalBytesWritten += MAX_BUFFER_SIZE;
272             }
273
274             if (totalBytesWritten < len) {
275                 bytesWritten = len - totalBytesWritten;
276                 System.arraycopy(b, off + totalBytesWritten, buffer, 0, bytesWritten);
277                 bufpos += bytesWritten;
278             }
279         }
280     }
281 public Client(String JavaDoc host, int port, String JavaDoc username, String JavaDoc password) {
282     this.host = host;
283     this.port = port;
284     this.username = username;
285     this.password = password;
286 }
287 public Client(String JavaDoc host, int port, String JavaDoc username, String JavaDoc password, String JavaDoc command) {
288     this(host, port, username, password);
289     this.command = command;
290 }
291 public Client(String JavaDoc host, int port, String JavaDoc username, String JavaDoc password, String JavaDoc command, int timeout) {
292     this(host, port, username, password, command);
293     this.timeout = timeout;
294 }
295 /**
296  * Close all streams and sockets.
297  */

298 private void cleanup() throws IOException JavaDoc {
299     try {
300         if (is != null)
301             is.close();
302     } finally {
303         try {
304             if (os != null)
305                 os.close();
306         } finally {
307             try {
308                 if (socketIn != null)
309                     socketIn.close();
310             } finally {
311                 try {
312                     if (socketOut != null)
313                         socketOut.close();
314                 } finally {
315                     try {
316                         if (socket != null)
317                             socket.close();
318                     } finally {
319                         socket = null;
320                     }
321                 }
322             }
323         }
324     }
325 }
326 /**
327  * Connect to the remote server. If an exception is thrown, the caller
328  * can asssume that all streams and sockets are closed.
329  */

330 public void connect(IProgressMonitor monitor) throws IOException JavaDoc, CVSAuthenticationException {
331     // If we're already connected, just ignore the invokation
332
if (connected || monitor.isCanceled())
333         return;
334         
335     // Otherwise, set up the connection
336
try {
337         PollingInputStream pollingInputStream = null;
338         // Create the socket (the socket should always be null here)
339
if (socket == null) {
340             try {
341                 socket = Util.createSocket(host, port, monitor);
342                 // Bug 36351: disable buffering and send bytes immediately
343
socket.setTcpNoDelay(true);
344             } catch (InterruptedIOException JavaDoc e) {
345                 // If we get this exception, chances are the host is not responding
346
throw new InterruptedIOException JavaDoc(NLS.bind(CVSSSHMessages.Client_socket, (new Object JavaDoc[] {host})));
347
348             }
349             if (timeout >= 0) {
350                 socket.setSoTimeout(1000);
351             }
352             pollingInputStream = new PollingInputStream(socket.getInputStream(),
353                 timeout > 0 ? timeout : 1, monitor);
354             socketIn = new BufferedInputStream JavaDoc(pollingInputStream);
355             
356             socketOut = new PollingOutputStream(new TimeoutOutputStream(
357                 socket.getOutputStream(), 8192 /*bufferSize*/, 1000 /*writeTimeout*/, 1000 /*closeTimeout*/),
358                 timeout > 0 ? timeout : 1, monitor);
359         }
360
361         // read the ssh server id. The socket creation may of failed if the
362
// server cannot accept our connection request. We don't expect the
363
// socket to be closed at this point.
364
// Don't allow cancellation during the initial handshake and login since this
365
// can potentially cause the SSH server to think that it is being hacked and
366
// disable the account.
367
socketOut.setIsCancellable(false /* don't allow cancellation */);
368         pollingInputStream.setIsCancellable(false);
369         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
370         int c;
371         while ((c = socketIn.read()) != '\n') {
372             if (c == -1)
373                 throw new IOException JavaDoc(CVSSSHMessages.Client_socketClosed);
374             buf.append((char) c);
375         }
376         serverId = buf.toString();
377         
378         if (Policy.DEBUG_SSH_PROTOCOL) {
379             System.out.println("SSH > server ID: " + serverId); //$NON-NLS-1$
380
System.out.println("SSH > client ID: " + clientId); //$NON-NLS-1$
381
}
382         
383         if (!serverId.startsWith("SSH-1.")) { //$NON-NLS-1$
384
String JavaDoc sshVersion = (serverId.startsWith("SSH-")? serverId:""); //$NON-NLS-1$ //$NON-NLS-2$
385
throw new IOException JavaDoc(NLS.bind(CVSSSHMessages.Client_sshProtocolVersion, new String JavaDoc[] { sshVersion }));
386         }
387         
388         // send our id.
389
socketOut.write(clientId.getBytes());
390         socketOut.flush();
391
392         login();
393
394         socketOut.setIsCancellable(true /* allow cancellation */);
395         pollingInputStream.setIsCancellable(true);
396         
397         // start a shell and enter interactive session or start by
398
// executing the given command.
399
if( command == null ) {
400             startShell();
401         } else {
402             executeCommand();
403         }
404
405         is = new StandardInputStream();
406         os = new StandardOutputStream();
407         connected = true;
408     // If an exception occurs while connected, make sure we disconnect before passing the exception on
409
} finally {
410         if (! connected) cleanup();
411     }
412 }
413 /**
414  * Terminate the connection to the server.
415  */

416 public void disconnect() throws IOException JavaDoc {
417     if (Policy.DEBUG_SSH_PROTOCOL) {
418         System.out.println("Disconnecting."); //$NON-NLS-1$
419
}
420     if (connected) {
421         connected = false;
422         try {
423             send(SSH_MSG_DISCONNECT, null);
424         } finally {
425             cleanup();
426         }
427     }
428 }
429 public InputStream JavaDoc getInputStream() throws IOException JavaDoc {
430     if (!connected) {
431         throw new IOException JavaDoc(CVSSSHMessages.Client_notConnected);
432     }
433
434     return is;
435 }
436 public OutputStream JavaDoc getOutputStream() throws IOException JavaDoc {
437     if (!connected) {
438         throw new IOException JavaDoc(CVSSSHMessages.Client_notConnected);
439     }
440
441     return os;
442 }
443
444 private void startShell() throws IOException JavaDoc {
445     ServerPacket packet = null;
446     int packetType;
447
448     send_SSH_CMSG_REQUEST_PTY();
449
450     try {
451         packet = skip_SSH_MSG_DEBUG();
452         packetType = packet.getType();
453
454         if (packetType != SSH_SMSG_SUCCESS) {
455             throw new IOException JavaDoc(NLS.bind(CVSSSHMessages.Client_packetType, (new Object JavaDoc[] {new Integer JavaDoc(packetType)})));
456         }
457     } finally {
458         if (packet != null) {
459             packet.close(true /*perform crc check*/);
460         }
461     }
462
463     send(SSH_CMSG_EXEC_SHELL, null);
464 }
465
466 private void executeCommand() throws IOException JavaDoc {
467     send(SSH_CMSG_EXEC_CMD, command);
468 }
469
470 private void login() throws IOException JavaDoc, CVSAuthenticationException {
471     ServerPacket packet = null;
472     int packetType;
473
474     try {
475         packet = skip_SSH_MSG_DEBUG();
476         packetType = packet.getType();
477
478         if (packetType != SSH_SMSG_PUBLIC_KEY) {
479             throw new IOException JavaDoc(NLS.bind(CVSSSHMessages.Client_packetType, (new Object JavaDoc[] {new Integer JavaDoc(packetType)})));
480         }
481
482         receive_SSH_SMSG_PUBLIC_KEY(packet);
483     } finally {
484         if (packet != null) {
485             packet.close(true);
486         }
487     }
488
489     try {
490         packet = skip_SSH_MSG_DEBUG();
491         packetType = packet.getType();
492
493         if (packetType != SSH_SMSG_SUCCESS) {
494             throw new IOException JavaDoc(NLS.bind(CVSSSHMessages.Client_packetType, (new Object JavaDoc[] {new Integer JavaDoc(packetType)})));
495         }
496     } finally {
497         if (packet != null) {
498             packet.close(true);
499         }
500     }
501
502     send(SSH_CMSG_USER, username);
503
504     try {
505         packet = skip_SSH_MSG_DEBUG();
506         packetType = packet.getType();
507
508         if (packetType != SSH_SMSG_FAILURE) {
509             throw new IOException JavaDoc(NLS.bind(CVSSSHMessages.Client_packetType, (new Object JavaDoc[] {new Integer JavaDoc(packetType)})));
510         }
511     } finally {
512         if (packet != null) {
513             packet.close(true);
514         }
515     }
516
517     send(SSH_CMSG_AUTH_PASSWORD, password);
518
519     try {
520         packet = skip_SSH_MSG_DEBUG();
521         packetType = packet.getType();
522
523         if (packetType == SSH_SMSG_FAILURE) {
524             throw new CVSAuthenticationException(CVSSSHMessages.Client_authenticationFailed, CVSAuthenticationException.RETRY);
525         }
526
527         if (packetType != SSH_SMSG_SUCCESS) {
528             throw new IOException JavaDoc(NLS.bind(CVSSSHMessages.Client_packetType, (new Object JavaDoc[] {new Integer JavaDoc(packetType)})));
529         }
530     } finally {
531         if (packet != null) {
532             packet.close(true);
533         }
534     }
535 }
536 private void receive_SSH_SMSG_PUBLIC_KEY(ServerPacket packet) throws IOException JavaDoc, CVSAuthenticationException {
537     InputStream JavaDoc pis = packet.getInputStream();
538
539     byte[] anti_spoofing_cookie = new byte[8];
540     Misc.readFully(pis, anti_spoofing_cookie);
541
542     byte[] server_key_bits = new byte[4];
543     Misc.readFully(pis, server_key_bits);
544
545     byte[] server_key_public_exponent = Misc.readMpInt(pis);
546     byte[] server_key_public_modulus = Misc.readMpInt(pis);
547
548     byte[] host_key_bits = new byte[4];
549     Misc.readFully(pis, host_key_bits);
550
551     byte[] host_key_public_exponent = Misc.readMpInt(pis);
552     byte[] host_key_public_modulus = Misc.readMpInt(pis);
553
554     byte[] protocol_flags = new byte[4];
555     Misc.readFully(pis, protocol_flags);
556
557     byte[] supported_ciphers_mask = new byte[4];
558     Misc.readFully(pis, supported_ciphers_mask);
559
560     byte[] supported_authentications_mask = new byte[4];
561     Misc.readFully(pis, supported_authentications_mask);
562
563     pis.close();
564
565     send_SSH_CMSG_SESSION_KEY(anti_spoofing_cookie, host_key_bits, server_key_public_modulus, host_key_public_modulus, supported_ciphers_mask, server_key_public_exponent, host_key_public_exponent);
566 }
567 private void send(int packetType, String JavaDoc s) throws IOException JavaDoc {
568     byte[] data = s == null ? new byte[0] : s.getBytes("UTF-8"); //$NON-NLS-1$
569
send(packetType, data, 0, data.length);
570 }
571 private void send(int packetType, byte[] data, int off, int len) throws IOException JavaDoc {
572     data = data == null ? null : Misc.lengthEncode(data, off, len);
573     ClientPacket packet = new ClientPacket(packetType, data, cipher);
574     socketOut.write(packet.getBytes());
575     socketOut.flush();
576 }
577 private void send_SSH_CMSG_REQUEST_PTY() throws IOException JavaDoc {
578     byte packet_type = SSH_CMSG_REQUEST_PTY;
579
580     byte[] termType = Misc.lengthEncode("dumb".getBytes(), 0, 4);//$NON-NLS-1$
581
byte[] row = {0, 0, 0, 0};
582     byte[] col = {0, 0, 0, 0};
583     byte[] XPixels = {0, 0, 0, 0};
584     byte[] YPixels = {0, 0, 0, 0};
585     byte[] terminalModes = {0};
586
587     byte[] data = new byte[termType.length + row.length + col.length + XPixels.length + YPixels.length + terminalModes.length];
588
589     int offset = 0;
590     System.arraycopy(termType, 0, data, offset, termType.length);
591
592     offset += termType.length;
593     System.arraycopy(row, 0, data, offset, row.length);
594
595     offset += row.length;
596     System.arraycopy(col, 0, data, offset, col.length);
597
598     offset += col.length;
599     System.arraycopy(XPixels, 0, data, offset, XPixels.length);
600
601     offset += XPixels.length;
602     System.arraycopy(YPixels, 0, data, offset, YPixels.length);
603
604     offset += YPixels.length;
605     System.arraycopy(terminalModes, 0, data, offset, terminalModes.length);
606
607     ClientPacket packet = new ClientPacket(packet_type, data, cipher);
608     socketOut.write(packet.getBytes());
609     socketOut.flush();
610 }
611 private void send_SSH_CMSG_SESSION_KEY(byte[] anti_spoofing_cookie, byte[] host_key_bits, byte[] server_key_public_modulus, byte[] host_key_public_modulus, byte[] supported_ciphers_mask, byte[] server_key_public_exponent, byte[] host_key_public_exponent) throws IOException JavaDoc, CVSAuthenticationException {
612     byte packet_type = SSH_CMSG_SESSION_KEY;
613
614     // session_id
615
byte[] session_id = new byte[host_key_public_modulus.length + server_key_public_modulus.length + anti_spoofing_cookie.length];
616
617     int offset = 0;
618     System.arraycopy(host_key_public_modulus, 0, session_id, offset, host_key_public_modulus.length);
619
620     offset += host_key_public_modulus.length;
621     System.arraycopy(server_key_public_modulus, 0, session_id, offset, server_key_public_modulus.length);
622
623     offset += server_key_public_modulus.length;
624     System.arraycopy(anti_spoofing_cookie, 0, session_id, offset, anti_spoofing_cookie.length);
625
626     session_id = Misc.md5(session_id);
627
628     // cipher_type
629
byte cipher_type = 0;
630     boolean foundSupportedCipher = false;
631
632     for (int i = 0; i < preferredCipherTypes.length && !foundSupportedCipher; ++i) {
633         cipher_type = (byte) preferredCipherTypes[i];
634         foundSupportedCipher = (supported_ciphers_mask[3] & (byte) (1 << cipher_type)) != 0;
635     }
636
637     if (!foundSupportedCipher) {
638         throw new IOException JavaDoc(CVSSSHMessages.Client_cipher);
639     }
640
641     // session_key
642
byte[] session_key = new byte[32];
643     byte[] session_key_xored = new byte[32];
644     byte[] session_key_encrypted = null;
645
646     Misc.random(session_key, 0, session_key.length, true);
647     System.arraycopy(session_key, 0, session_key_xored, 0, session_key.length);
648     Misc.xor(session_key_xored, 0, session_id, 0, session_key_xored, 0, session_id.length);
649
650     BigInteger JavaDoc host_e = new BigInteger JavaDoc(1, host_key_public_exponent);
651     BigInteger JavaDoc host_n = new BigInteger JavaDoc(1, host_key_public_modulus);
652     if (!new KnownHosts().verifyKey(host, host_key_bits, host_e, host_n)) {
653         throw new CVSAuthenticationException(CVSSSHMessages.Client_hostIdChanged, CVSAuthenticationException.NO_RETRY);
654     };
655     byte[] result;
656     if (new BigInteger JavaDoc(1,server_key_public_modulus).compareTo(host_n) == -1) {
657         result = Misc.encryptRSAPkcs1(session_key_xored, server_key_public_exponent, server_key_public_modulus);
658         result = Misc.encryptRSAPkcs1(result, host_key_public_exponent, host_key_public_modulus);
659     } else {
660         result = Misc.encryptRSAPkcs1(session_key_xored, host_key_public_exponent, host_key_public_modulus);
661         result = Misc.encryptRSAPkcs1(result, server_key_public_exponent, server_key_public_modulus);
662     }
663
664     session_key_encrypted = new byte[result.length + 2];
665     session_key_encrypted[1] = (byte) ((8 * result.length) & 0xff);
666     session_key_encrypted[0] = (byte) (((8 * result.length) >> 8) & 0xff);
667
668     for (int i = 0; i < result.length; i++) {
669         session_key_encrypted[i + 2] = result[i];
670     }
671
672     // protocol_flags
673
byte[] protocol_flags = {0, 0, 0, 0};
674
675     // data
676
byte[] data = new byte[1 + anti_spoofing_cookie.length + session_key_encrypted.length + protocol_flags.length];
677
678     offset = 0;
679     data[offset++] = cipher_type;
680
681     System.arraycopy(anti_spoofing_cookie, 0, data, offset, anti_spoofing_cookie.length);
682
683     offset += anti_spoofing_cookie.length;
684     System.arraycopy(session_key_encrypted, 0, data, offset, session_key_encrypted.length);
685
686     offset += session_key_encrypted.length;
687     System.arraycopy(protocol_flags, 0, data, offset, protocol_flags.length);
688
689     // cipher
690
cipher = Cipher.getInstance(cipherNames[cipher_type]);
691     cipher.setKey(session_key);
692
693     // packet
694
ClientPacket packet = new ClientPacket(packet_type, data, null);
695     socketOut.write(packet.getBytes());
696     socketOut.flush();
697 }
698
699 private ServerPacket skip_SSH_MSG_DEBUG() throws IOException JavaDoc {
700     ServerPacket packet = new ServerPacket(socketIn, cipher);
701     while (packet.getType() == SSH_MSG_DEBUG) {
702         packet.close(true);
703         packet = new ServerPacket(socketIn, cipher);
704     }
705     
706     return packet;
707 }
708 }
709
Popular Tags