source: other-projects/trunk/gs3-release-maker/tasks/sshtaskdef/src/mindbright/ssh/SSH.java@ 14627

Last change on this file since 14627 was 14627, checked in by oranfry, 17 years ago

initial import of the gs3-release-maker

File size: 19.2 KB
Line 
1/******************************************************************************
2 *
3 * Copyright (c) 1998,99 by Mindbright Technology AB, Stockholm, Sweden.
4 * www.mindbright.se, [email protected]
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 *****************************************************************************
17 * $Author: mats $
18 * $Date: 2000/08/01 22:30:52 $
19 * $Name: rel1-2-1 $
20 *****************************************************************************/
21package mindbright.ssh;
22
23import java.io.*;
24import java.math.BigInteger;
25
26import mindbright.security.*;
27
28public abstract class SSH {
29
30 public static boolean DEBUG = false;
31 public static boolean DEBUGMORE = false;
32
33 public final static boolean NETSCAPE_SECURITY_MODEL = false;
34
35 public final static int SSH_VER_MAJOR = 1;
36 public final static int SSH_VER_MINOR = 5;
37 public final static String VER_SSHPKG = "v1.2.1";
38 public final static String VER_MINDTERM = "MindTerm " + VER_SSHPKG;
39 public final static String VER_MINDTUNL = "MindTunnel " + VER_SSHPKG;
40 public final static String CVS_NAME = "$Name: rel1-2-1 $";
41 public final static String CVS_DATE = "$Date: 2000/08/01 22:30:52 $";
42
43 public final static int DEFAULTPORT = 22;
44 public final static int SESSION_KEY_LENGTH = 256; // !!! Must be multiple of 8
45 public final static int SERVER_KEY_LENGTH = 768;
46 public final static int HOST_KEY_LENGTH = 1024;
47
48 public final static int PROTOFLAG_SCREEN_NUMBER = 1;
49 public final static int PROTOFLAG_HOST_IN_FWD_OPEN = 2;
50
51 public final static int MSG_ANY = -1; // !!! Not part of protocol
52 public final static int MSG_NONE = 0;
53 public final static int MSG_DISCONNECT = 1;
54 public final static int SMSG_PUBLIC_KEY = 2;
55 public final static int CMSG_SESSION_KEY = 3;
56 public final static int CMSG_USER = 4;
57 public final static int CMSG_AUTH_RHOSTS = 5;
58 public final static int CMSG_AUTH_RSA = 6;
59 public final static int SMSG_AUTH_RSA_CHALLENGE = 7;
60 public final static int CMSG_AUTH_RSA_RESPONSE = 8;
61 public final static int CMSG_AUTH_PASSWORD = 9;
62 public final static int CMSG_REQUEST_PTY = 10;
63 public final static int CMSG_WINDOW_SIZE = 11;
64 public final static int CMSG_EXEC_SHELL = 12;
65 public final static int CMSG_EXEC_CMD = 13;
66 public final static int SMSG_SUCCESS = 14;
67 public final static int SMSG_FAILURE = 15;
68 public final static int CMSG_STDIN_DATA = 16;
69 public final static int SMSG_STDOUT_DATA = 17;
70 public final static int SMSG_STDERR_DATA = 18;
71 public final static int CMSG_EOF = 19;
72 public final static int SMSG_EXITSTATUS = 20;
73 public final static int MSG_CHANNEL_OPEN_CONFIRMATION = 21;
74 public final static int MSG_CHANNEL_OPEN_FAILURE = 22;
75 public final static int MSG_CHANNEL_DATA = 23;
76 public final static int MSG_CHANNEL_CLOSE = 24;
77 public final static int MSG_CHANNEL_CLOSE_CONFIRMATION = 25;
78 public final static int MSG_CHANNEL_INPUT_EOF = 24;
79 public final static int MSG_CHANNEL_OUTPUT_CLOSED = 25;
80 // OBSOLETE CMSG_X11_REQUEST_FORWARDING = 26;
81 public final static int SMSG_X11_OPEN = 27;
82 public final static int CMSG_PORT_FORWARD_REQUEST = 28;
83 public final static int MSG_PORT_OPEN = 29;
84 public final static int CMSG_AGENT_REQUEST_FORWARDING = 30;
85 public final static int SMSG_AGENT_OPEN = 31;
86 public final static int MSG_IGNORE = 32;
87 public final static int CMSG_EXIT_CONFIRMATION = 33;
88 public final static int CMSG_X11_REQUEST_FORWARDING = 34;
89 public final static int CMSG_AUTH_RHOSTS_RSA = 35;
90 public final static int MSG_DEBUG = 36;
91 public final static int CMSG_REQUEST_COMPRESSION = 37;
92 public final static int CMSG_MAX_PACKET_SIZE = 38;
93 public final static int CMSG_AUTH_TIS = 39;
94 public final static int SMSG_AUTH_TIS_CHALLENGE = 40;
95 public final static int CMSG_AUTH_TIS_RESPONSE = 41;
96
97 public final static int CMSG_AUTH_SDI = 16; // !!! OUCH
98 public final static int CMSG_ACM_OK = 64;
99 public final static int CMSG_ACM_ACCESS_DENIED = 65;
100 public final static int CMSG_ACM_NEXT_CODE_REQUIRED = 66;
101 public final static int CMSG_ACM_NEXT_CODE = 67;
102 public final static int CMSG_ACM_NEW_PIN_REQUIRED = 68;
103 public final static int CMSG_ACM_NEW_PIN_ACCEPTED = 69;
104 public final static int CMSG_ACM_NEW_PIN_REJECTED = 70;
105 public final static int CMSG_ACM_NEW_PIN = 71;
106
107 public final static int IDX_CIPHER_CLASS = 0;
108 public final static int IDX_CIPHER_NAME = 1;
109
110 public final static String[][] cipherClasses = {
111 { "NoEncrypt", "none" }, // No encryption
112 { "IDEA", "idea" }, // IDEA in CFB mode
113 { "DES", "des" }, // DES in CBC mode
114 { "DES3", "3des" }, // Triple-DES in CBC mode
115 { null, "tss" }, // An experimental stream cipher
116 { "RC4", "rc4" }, // RC4
117 { "Blowfish", "blowfish" }, // Bruce Schneier's Blowfish
118 { null, "reserved" } // (not implemented now, might be though... see above)
119 };
120 public final static int CIPHER_NONE = 0; // No encryption
121 public final static int CIPHER_IDEA = 1; // IDEA in CFB mode
122 public final static int CIPHER_DES = 2; // DES in CBC mode
123 public final static int CIPHER_3DES = 3; // Triple-DES in CBC mode
124 public final static int CIPHER_TSS = 4; // An experimental stream cipher
125 public final static int CIPHER_RC4 = 5; // RC4
126 public final static int CIPHER_BLOWFISH = 6; // Bruce Schneier's Blowfish */
127 public final static int CIPHER_RESERVED = 7; // Reserved for 40 bit crippled encryption,
128 // Bernard Perrot <[email protected]>
129 public final static int CIPHER_NOTSUPPORTED = 8; // Indicates an unsupported cipher
130 public final static int CIPHER_DEFAULT = CIPHER_3DES; // Triple-DES is default block-cipher
131
132 public final static String[] authTypeDesc = {
133 "_N/A_",
134 "rhosts",
135 "rsa",
136 "passwd",
137 "rhostsrsa",
138 "tis",
139 "kerberos",
140 "kerbtgt",
141 "sdi-token"
142 };
143 public final static int AUTH_RHOSTS = 1;
144 public final static int AUTH_RSA = 2;
145 public final static int AUTH_PASSWORD = 3;
146 public final static int AUTH_RHOSTS_RSA = 4;
147 public final static int AUTH_TIS = 5;
148 public final static int AUTH_KERBEROS = 6;
149 public final static int PASS_KERBEROS_TGT = 7;
150
151 public final static int AUTH_SDI = 8;
152
153
154 public final static int AUTH_NOTSUPPORTED = authTypeDesc.length;
155 public final static int AUTH_DEFAULT = AUTH_PASSWORD;
156
157
158 final static String[] proxyTypes = { "none", "http", "socks4",
159 "socks5-proxy-dns",
160 "socks5-local-dns" };
161
162 final static int[] defaultProxyPorts = { 0, 8080, 1080, 1080, 1080 };
163
164
165 public final static int PROXY_NONE = 0;
166 public final static int PROXY_HTTP = 1;
167 public final static int PROXY_SOCKS4 = 2;
168 public final static int PROXY_SOCKS5_DNS = 3;
169 public final static int PROXY_SOCKS5_IP = 4;
170 public final static int PROXY_NOTSUPPORTED = proxyTypes.length;
171
172
173 public final static int TTY_OP_END = 0;
174 public final static int TTY_OP_ISPEED = 192;
175 public final static int TTY_OP_OSPEED = 193;
176
177 // These are special "channels" not associated with a channel-number
178 // in "SSH-sense".
179 //
180 public final static int MAIN_CHAN_NUM = -1;
181 public final static int CONNECT_CHAN_NUM = -2;
182 public final static int LISTEN_CHAN_NUM = -3;
183 public final static int UNKNOWN_CHAN_NUM = -4;
184
185 // Default name of file containing set of known hosts
186 //
187 public final static String KNOWN_HOSTS_FILE = "known_hosts";
188
189 // When verifying the server's host-key to the set of known hosts, the
190 // possible outcome is one of these.
191 //
192 public final static int SRV_HOSTKEY_KNOWN = 0;
193 public final static int SRV_HOSTKEY_NEW = 1;
194 public final static int SRV_HOSTKEY_CHANGED = 2;
195
196 public static SecureRandom secureRandom;
197
198 //
199 //
200 protected byte[] sessionKey;
201 protected byte[] sessionId;
202
203 //
204 //
205 protected Cipher sndCipher;
206 protected Cipher rcvCipher;
207 protected int cipherType;
208
209 // Server data fields
210 //
211 protected byte[] srvCookie;
212 protected KeyPair srvServerKey;
213 protected KeyPair srvHostKey;
214 protected int protocolFlags;
215 protected int supportedCiphers;
216 protected int supportedAuthTypes;
217
218 protected boolean isAnSSHClient = true;
219
220 public static String getVersionId(boolean client) {
221 String idStr = "SSH-" + SSH_VER_MAJOR + "." + SSH_VER_MINOR + "-";
222 idStr += (client ? VER_MINDTERM : VER_MINDTUNL);
223 return idStr;
224 }
225
226 public static String[] getProxyTypes() {
227 return proxyTypes;
228 }
229
230 public static int getProxyType(String typeName) throws IllegalArgumentException {
231 int i;
232 for(i = 0; i < proxyTypes.length; i++) {
233 if(proxyTypes[i].equalsIgnoreCase(typeName))
234 break;
235 }
236 if(i == PROXY_NOTSUPPORTED)
237 throw new IllegalArgumentException("Proxytype " + typeName + " not supported");
238
239 return i;
240 }
241
242 public static String listSupportedProxyTypes() {
243 String list = "";
244 int i;
245 for(i = 0; i < proxyTypes.length; i++) {
246 list += proxyTypes[i] + " ";
247 }
248 return list;
249 }
250
251 public static String getCipherName(int cipherType) {
252 return cipherClasses[cipherType][IDX_CIPHER_NAME];
253 }
254
255 public static int getCipherType(String cipherName) {
256 int i;
257 for(i = 0; i < cipherClasses.length; i++) {
258 String clN = cipherClasses[i][IDX_CIPHER_CLASS];
259 String ciN = cipherClasses[i][IDX_CIPHER_NAME];
260 if(ciN.equalsIgnoreCase(cipherName)) {
261 if(cipherClasses[i][0] == null)
262 i = cipherClasses.length;
263 break;
264 }
265 }
266 return i;
267 }
268
269 public static String getAuthName(int authType) {
270 return authTypeDesc[authType];
271 }
272
273 public static int getAuthType(String authName) throws IllegalArgumentException {
274 int i;
275 for(i = 1; i < SSH.authTypeDesc.length; i++) {
276 if(SSH.authTypeDesc[i].equalsIgnoreCase(authName))
277 break;
278 }
279 if(i == AUTH_NOTSUPPORTED)
280 throw new IllegalArgumentException("Authtype " + authName + " not supported");
281
282 return i;
283 }
284
285 static int cntListSize(String authList) {
286 int cnt = 1;
287 int i = 0, n;
288 while(i < authList.length() && (n = authList.indexOf(',', i)) != -1) {
289 i = n + 1;
290 cnt++;
291 }
292 return cnt;
293 }
294
295 public static int[] getAuthTypes(String authList) throws IllegalArgumentException {
296 int len = cntListSize(authList);
297 int[] authTypes = new int[len];
298 int r, l = 0;
299 String type;
300
301 for(int i = 0; i < len; i++) {
302 r = authList.indexOf(',', l);
303 if(r == -1)
304 r = authList.length();
305 type = authList.substring(l, r).trim();
306 authTypes[i] = getAuthType(type);
307 l = r + 1;
308 }
309
310 return authTypes;
311 }
312
313 public static String listSupportedCiphers() {
314 String list = "";
315 int i;
316 for(i = 0; i < cipherClasses.length; i++) {
317 if(cipherClasses[i][0] != null)
318 list += cipherClasses[i][1] + " ";
319 }
320 return list;
321 }
322
323 public static String[] getCiphers() {
324 int i, n = 0;
325 for(i = 0; i < cipherClasses.length; i++) {
326 if(cipherClasses[i][0] != null)
327 n++;
328 }
329 String[] ciphers = new String[n];
330 n = 0;
331 for(i = 0; i < cipherClasses.length; i++) {
332 if(cipherClasses[i][0] != null)
333 ciphers[n++] = cipherClasses[i][1];
334 }
335 return ciphers;
336 }
337
338 public static String listSupportedAuthTypes() {
339 String list = "";
340 int i;
341 for(i = 1; i < authTypeDesc.length; i++) {
342 list += authTypeDesc[i] + " ";
343 }
344 return list;
345 }
346
347 public static String[] getAuthTypeList() {
348 String[] auths = new String[authTypeDesc.length];
349 for(int i = 1; i < authTypeDesc.length; i++) {
350 auths[i - 1] = authTypeDesc[i];
351 }
352 auths[authTypeDesc.length - 1] = "custom...";
353 return auths;
354 }
355
356 boolean isCipherSupported(int cipherType) {
357 int cipherMask = (0x01 << cipherType);
358 if((cipherMask & supportedCiphers) != 0)
359 return true;
360 return false;
361 }
362
363 boolean isAuthTypeSupported(int authType) {
364 int authTypeMask = (0x01 << authType);
365 if((authTypeMask & supportedAuthTypes) != 0)
366 return true;
367 return false;
368 }
369
370 boolean isProtocolFlagSet(int protFlag) {
371 int protFlagMask = (0x01 << protFlag);
372 if((protFlagMask & protocolFlags) != 0)
373 return true;
374 return false;
375 }
376
377 public static void initSeedGenerator() {
378 if(secureRandom != null)
379 return;
380 secureRandom = new SecureRandom();
381 }
382
383 public static SecureRandom secureRandom() {
384 if(secureRandom == null) {
385 secureRandom = new SecureRandom();
386 }
387 return secureRandom;
388 }
389
390 public static void log(String msg) {
391 if(DEBUG) System.out.println(msg);
392 }
393
394 public static void logExtra(String msg) {
395 if(DEBUGMORE) System.out.println(msg);
396 }
397
398 public static void logDebug(String msg) {
399 if(DEBUG) System.out.println(msg);
400 }
401
402 public static void logIgnore(SSHPduInputStream pdu) {
403 if(DEBUG) System.out.println("MSG_IGNORE received...(len = " + pdu.length + ")");
404 }
405
406 void generateSessionId() throws IOException {
407 byte[] message;
408 byte[] srvKey = ((RSAPublicKey)srvServerKey.getPublic()).getN().toByteArray();
409 byte[] hstKey = ((RSAPublicKey)srvHostKey.getPublic()).getN().toByteArray();
410 int i, len = srvKey.length + hstKey.length + srvCookie.length;
411
412 if(srvKey[0] == 0)
413 len -= 1;
414 if(hstKey[0] == 0)
415 len -= 1;
416
417 message = new byte[len];
418
419 if(hstKey[0] == 0) {
420 System.arraycopy(hstKey, 1, message, 0, hstKey.length - 1);
421 len = hstKey.length - 1;
422 } else {
423 System.arraycopy(hstKey, 0, message, 0, hstKey.length);
424 len = hstKey.length;
425 }
426
427 if(srvKey[0] == 0) {
428 System.arraycopy(srvKey, 1, message, len, srvKey.length - 1);
429 len += srvKey.length - 1;
430 } else {
431 System.arraycopy(srvKey, 0, message, len, srvKey.length);
432 len += srvKey.length;
433 }
434
435 System.arraycopy(srvCookie, 0, message, len, srvCookie.length);
436
437 try {
438 MessageDigest md5;
439 md5 = MessageDigest.getInstance("MD5");
440 md5.update(message);
441 sessionId = md5.digest();
442 } catch(Exception e) {
443 throw new IOException("MD5 not implemented, can't generate session-id");
444 }
445 }
446
447 protected void initClientCipher() throws IOException {
448 initCipher(false);
449 }
450
451 protected void initServerCipher() throws IOException {
452 initCipher(true);
453 }
454
455 protected void initCipher(boolean server) throws IOException {
456 sndCipher = Cipher.getInstance(cipherClasses[cipherType][0]);
457 rcvCipher = Cipher.getInstance(cipherClasses[cipherType][0]);
458
459 if(sndCipher == null) {
460 throw new IOException("Cipher " + cipherClasses[cipherType][1] + " not found, can't use it");
461 }
462
463 if(cipherType == CIPHER_RC4) {
464 if(server) {
465 int len = sessionKey.length / 2;
466 byte[] key = new byte[len];
467 System.arraycopy(sessionKey, 0, key, 0, len);
468 sndCipher.setKey(key);
469 System.arraycopy(sessionKey, len, key, 0, len);
470 rcvCipher.setKey(key);
471 } else {
472 int len = sessionKey.length / 2;
473 byte[] key = new byte[len];
474 System.arraycopy(sessionKey, 0, key, 0, len);
475 rcvCipher.setKey(key);
476 System.arraycopy(sessionKey, len, key, 0, len);
477 sndCipher.setKey(key);
478 }
479 } else {
480 sndCipher.setKey(sessionKey);
481 rcvCipher.setKey(sessionKey);
482 }
483 }
484
485 public static String generateKeyFiles(KeyPair kp, String fileName, String passwd, String comment)
486 throws IOException {
487 SSHRSAKeyFile.createKeyFile(kp, passwd, fileName, comment);
488 RSAPublicKey pubKey = (RSAPublicKey)kp.getPublic();
489 SSHRSAPublicKeyString pks = new SSHRSAPublicKeyString("", comment,
490 pubKey.getE(), pubKey.getN());
491 pks.toFile(fileName + ".pub");
492 return pks.toString();
493 }
494
495 public static KeyPair generateRSAKeyPair(int bits, SecureRandom secRand) {
496 KeyPair kp;
497 RSACipher cipher;
498 BigInteger p;
499 BigInteger q;
500 BigInteger t;
501 BigInteger p_1;
502 BigInteger q_1;
503 BigInteger phi;
504 BigInteger G;
505 BigInteger F;
506 BigInteger e;
507 BigInteger d;
508 BigInteger u;
509 BigInteger n;
510 BigInteger one = new BigInteger("1");
511
512 for(;;) {
513 int l = secRand.secureLevel;
514 secRand.secureLevel = 2;
515 p = new BigInteger(bits / 2, 64, secRand);
516 q = new BigInteger(bits - (bits / 2), 64, secRand);
517 secRand.secureLevel = l;
518
519 if(p.compareTo(q) == 0) {
520 continue;
521 } else if(q.compareTo(p) < 0) {
522 t = q;
523 q = p;
524 p = t;
525 }
526
527 t = p.gcd(q);
528 if(t.compareTo(one) != 0) {
529 continue;
530 }
531
532 p_1 = p.subtract(one);
533 q_1 = q.subtract(one);
534 phi = p_1.multiply(q_1);
535 G = p_1.gcd(q_1);
536 F = phi.divide(G);
537
538 e = one.shiftLeft(5);
539 e = e.subtract(one);
540 do {
541 e = e.add(one.add(one));
542 t = e.gcd(phi);
543 } while(t.compareTo(one) != 0);
544
545 // !!! d = e.modInverse(F);
546 d = e.modInverse(phi);
547 n = p.multiply(q);
548 u = p.modInverse(q);
549
550 kp = new KeyPair(new RSAPublicKey(e, n),
551 new RSAPrivateKey(e, n, d, u, p, q));
552
553 // !!!
554 break;
555 }
556
557 return kp;
558 }
559
560 /* !!! USED FOR DEBUG !!!
561 void printSrvKeys() {
562 BigInteger big;
563 byte[] theId = new byte[sessionId.length + 1];
564 theId[0] = 0;
565 System.arraycopy(sessionId, 0, theId, 1, sessionId.length);
566 big = new BigInteger(theId);
567 System.out.println("sessionId: " + big.toString(16));
568 byte[] theKey = new byte[sessionKey.length + 1];
569 theKey[0] = 0;
570 System.arraycopy(sessionKey, 0, theKey, 1, sessionKey.length);
571 big = new BigInteger(theKey);
572 System.out.println("sessionkey: " + big.toString(16));
573
574 System.out.println("srvkey n: " + ((RSAPublicKey)srvServerKey.getPublic()).getN().toString(16));
575 System.out.println("srvkey e: " + ((RSAPublicKey)srvServerKey.getPublic()).getE().toString(16));
576 System.out.println("srvkey bits: " + ((RSAPublicKey)srvServerKey.getPublic()).bitLength());
577 System.out.println("hstkey n: " + ((RSAPublicKey)srvHostKey.getPublic()).getN().toString(16));
578 System.out.println("hstkey e: " + ((RSAPublicKey)srvHostKey.getPublic()).getE().toString(16));
579 System.out.println("hstkey bits: " + ((RSAPublicKey)srvHostKey.getPublic()).bitLength());
580 }
581 */
582
583}
584
Note: See TracBrowser for help on using the repository browser.