Mercurial > 510Connectbot
comparison src/ch/ethz/ssh2/Connection.java @ 308:42b15aaa7ac7 ganymed
merge
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Wed, 30 Jul 2014 14:21:50 -0700 |
parents | 071eccdff8ea |
children | cdb3c9215a9b |
comparison
equal
deleted
inserted
replaced
306:90e47d99ea54 | 308:42b15aaa7ac7 |
---|---|
56 * <p/> | 56 * <p/> |
57 * <b>NOTE: As per the RFC, the "softwareversion" string MUST consist of printable | 57 * <b>NOTE: As per the RFC, the "softwareversion" string MUST consist of printable |
58 * US-ASCII characters, with the exception of whitespace characters and the minus sign (-).</b> | 58 * US-ASCII characters, with the exception of whitespace characters and the minus sign (-).</b> |
59 */ | 59 */ |
60 private String softwareversion | 60 private String softwareversion |
61 = String.format("Ganymed_%s", Version.getSpecification()); | 61 = String.format("Ganymed_%s", Version.getSpecification()); |
62 | 62 |
63 /* Will be used to generate all random data needed for the current connection. | 63 /* Will be used to generate all random data needed for the current connection. |
64 * Note: SecureRandom.nextBytes() is thread safe. | 64 * Note: SecureRandom.nextBytes() is thread safe. |
65 */ | 65 */ |
66 | 66 |
67 private SecureRandom generator; | 67 private SecureRandom generator; |
68 | 68 |
69 /** | 69 /** |
70 * Unless you know what you are doing, you will never need this. | 70 * Unless you know what you are doing, you will never need this. |
71 * | 71 * |
72 * @return The list of supported cipher algorithms by this implementation. | 72 * @return The list of supported cipher algorithms by this implementation. |
73 */ | 73 */ |
74 | |
74 public static synchronized String[] getAvailableCiphers() { | 75 public static synchronized String[] getAvailableCiphers() { |
75 return BlockCipherFactory.getDefaultCipherList(); | 76 return BlockCipherFactory.getDefaultCipherList(); |
76 } | 77 } |
77 | 78 |
78 /** | 79 /** |
79 * Unless you know what you are doing, you will never need this. | 80 * Unless you know what you are doing, you will never need this. |
80 * | 81 * |
81 * @return The list of supported MAC algorthims by this implementation. | 82 * @return The list of supported MAC algorthims by this implementation. |
82 */ | 83 */ |
84 | |
83 public static synchronized String[] getAvailableMACs() { | 85 public static synchronized String[] getAvailableMACs() { |
84 return MAC.getMacList(); | 86 return MAC.getMacList(); |
85 } | 87 } |
86 | 88 |
87 /** | 89 /** |
88 * Unless you know what you are doing, you will never need this. | 90 * Unless you know what you are doing, you will never need this. |
89 * | 91 * |
90 * @return The list of supported server host key algorthims by this implementation. | 92 * @return The list of supported server host key algorthims by this implementation. |
91 */ | 93 */ |
94 | |
92 public static synchronized String[] getAvailableServerHostKeyAlgorithms() { | 95 public static synchronized String[] getAvailableServerHostKeyAlgorithms() { |
93 return KexManager.getDefaultServerHostkeyAlgorithmList(); | 96 return KexManager.getDefaultServerHostkeyAlgorithmList(); |
94 } | 97 } |
95 | 98 |
96 private AuthenticationManager am; | 99 private AuthenticationManager am; |
97 | 100 |
98 private boolean authenticated; | 101 private boolean authenticated; |
99 private ChannelManager cm; | 102 private ChannelManager cm; |
100 | 103 |
101 private CryptoWishList cryptoWishList | 104 private CryptoWishList cryptoWishList |
102 = new CryptoWishList(); | 105 = new CryptoWishList(); |
103 | 106 |
104 private DHGexParameters dhgexpara | 107 private DHGexParameters dhgexpara |
105 = new DHGexParameters(); | 108 = new DHGexParameters(); |
106 | 109 |
107 private final String hostname; | 110 private final String hostname; |
108 | 111 |
109 private final int port; | 112 private final int port; |
110 | 113 |
113 private boolean tcpNoDelay = false; | 116 private boolean tcpNoDelay = false; |
114 | 117 |
115 private HTTPProxyData proxy; | 118 private HTTPProxyData proxy; |
116 | 119 |
117 private List<ConnectionMonitor> connectionMonitors | 120 private List<ConnectionMonitor> connectionMonitors |
118 = new ArrayList<ConnectionMonitor>(); | 121 = new ArrayList<ConnectionMonitor>(); |
119 | 122 |
120 /** | 123 /** |
121 * Prepares a fresh <code>Connection</code> object which can then be used | 124 * Prepares a fresh <code>Connection</code> object which can then be used |
122 * to establish a connection to the specified SSH-2 server. | 125 * to establish a connection to the specified SSH-2 server. |
123 * <p/> | 126 * <p/> |
194 * @deprecated You should use one of the {@link #authenticateWithPublicKey(String, File, String) authenticateWithPublicKey()} | 197 * @deprecated You should use one of the {@link #authenticateWithPublicKey(String, File, String) authenticateWithPublicKey()} |
195 * methods, this method is just a wrapper for it and will | 198 * methods, this method is just a wrapper for it and will |
196 * disappear in future builds. | 199 * disappear in future builds. |
197 */ | 200 */ |
198 @Deprecated | 201 @Deprecated |
199 public synchronized boolean authenticateWithDSA(String user, String pem, String password) throws IOException { | 202 |
200 if(tm == null) { | 203 public synchronized boolean authenticateWithDSA(String user, String pem, String password) throws IOException { |
204 if (tm == null) { | |
201 throw new IllegalStateException("Connection is not established!"); | 205 throw new IllegalStateException("Connection is not established!"); |
202 } | 206 } |
203 | 207 |
204 if(authenticated) { | 208 if (authenticated) { |
205 throw new IllegalStateException("Connection is already authenticated!"); | 209 throw new IllegalStateException("Connection is already authenticated!"); |
206 } | 210 } |
207 | 211 |
208 if(am == null) { | 212 if (am == null) { |
209 am = new AuthenticationManager(tm); | 213 am = new AuthenticationManager(tm); |
210 } | 214 } |
211 | 215 |
212 if(cm == null) { | 216 if (cm == null) { |
213 cm = new ChannelManager(tm); | 217 cm = new ChannelManager(tm); |
214 } | 218 } |
215 | 219 |
216 if(user == null) { | 220 if (user == null) { |
217 throw new IllegalArgumentException("user argument is null"); | 221 throw new IllegalArgumentException("user argument is null"); |
218 } | 222 } |
219 | 223 |
220 if(pem == null) { | 224 if (pem == null) { |
221 throw new IllegalArgumentException("pem argument is null"); | 225 throw new IllegalArgumentException("pem argument is null"); |
222 } | 226 } |
223 | 227 |
224 authenticated = am.authenticatePublicKey(user, pem.toCharArray(), password, getOrCreateSecureRND()); | 228 authenticated = am.authenticatePublicKey(user, pem.toCharArray(), password, getOrCreateSecureRND()); |
225 | |
226 return authenticated; | 229 return authenticated; |
227 } | 230 } |
228 | 231 |
229 /** | 232 /** |
230 * A wrapper that calls {@link #authenticateWithKeyboardInteractive(String, String[], InteractiveCallback) | 233 * A wrapper that calls {@link #authenticateWithKeyboardInteractive(String, String[], InteractiveCallback) |
234 * @param cb An <code>InteractiveCallback</code> which will be used to | 237 * @param cb An <code>InteractiveCallback</code> which will be used to |
235 * determine the responses to the questions asked by the server. | 238 * determine the responses to the questions asked by the server. |
236 * @return whether the connection is now authenticated. | 239 * @return whether the connection is now authenticated. |
237 * @throws IOException | 240 * @throws IOException |
238 */ | 241 */ |
242 | |
239 public synchronized boolean authenticateWithKeyboardInteractive(String user, InteractiveCallback cb) | 243 public synchronized boolean authenticateWithKeyboardInteractive(String user, InteractiveCallback cb) |
240 throws IOException { | 244 throws IOException { |
241 return authenticateWithKeyboardInteractive(user, null, cb); | 245 return authenticateWithKeyboardInteractive(user, null, cb); |
242 } | 246 } |
243 | 247 |
244 /** | 248 /** |
245 * After a successful connect, one has to authenticate oneself. This method | 249 * After a successful connect, one has to authenticate oneself. This method |
269 * @param cb An <code>InteractiveCallback</code> which will be used to | 273 * @param cb An <code>InteractiveCallback</code> which will be used to |
270 * determine the responses to the questions asked by the server. | 274 * determine the responses to the questions asked by the server. |
271 * @return whether the connection is now authenticated. | 275 * @return whether the connection is now authenticated. |
272 * @throws IOException | 276 * @throws IOException |
273 */ | 277 */ |
278 | |
274 public synchronized boolean authenticateWithKeyboardInteractive(String user, String[] submethods, | 279 public synchronized boolean authenticateWithKeyboardInteractive(String user, String[] submethods, |
275 InteractiveCallback cb) throws IOException { | 280 InteractiveCallback cb) throws IOException { |
276 if(cb == null) { | 281 if (cb == null) { |
277 throw new IllegalArgumentException("Callback may not ne NULL!"); | 282 throw new IllegalArgumentException("Callback may not ne NULL!"); |
278 } | 283 } |
279 | 284 |
280 if(tm == null) { | 285 if (tm == null) { |
281 throw new IllegalStateException("Connection is not established!"); | 286 throw new IllegalStateException("Connection is not established!"); |
282 } | 287 } |
283 | 288 |
284 if(authenticated) { | 289 if (authenticated) { |
285 throw new IllegalStateException("Connection is already authenticated!"); | 290 throw new IllegalStateException("Connection is already authenticated!"); |
286 } | 291 } |
287 | 292 |
288 if(am == null) { | 293 if (am == null) { |
289 am = new AuthenticationManager(tm); | 294 am = new AuthenticationManager(tm); |
290 } | 295 } |
291 | 296 |
292 if(cm == null) { | 297 if (cm == null) { |
293 cm = new ChannelManager(tm); | 298 cm = new ChannelManager(tm); |
294 } | 299 } |
295 | 300 |
296 if(user == null) { | 301 if (user == null) { |
297 throw new IllegalArgumentException("user argument is null"); | 302 throw new IllegalArgumentException("user argument is null"); |
298 } | 303 } |
299 | 304 |
300 authenticated = am.authenticateInteractive(user, submethods, cb); | 305 authenticated = am.authenticateInteractive(user, submethods, cb); |
301 | |
302 return authenticated; | 306 return authenticated; |
303 } | 307 } |
304 | 308 |
305 public synchronized boolean authenticateWithAgent(String user, AgentProxy proxy) throws IOException { | 309 public synchronized boolean authenticateWithAgent(String user, AgentProxy proxy) throws IOException { |
306 if(tm == null) { | 310 if (tm == null) { |
307 throw new IllegalStateException("Connection is not established!"); | 311 throw new IllegalStateException("Connection is not established!"); |
308 } | 312 } |
309 | 313 |
310 if(authenticated) { | 314 if (authenticated) { |
311 throw new IllegalStateException("Connection is already authenticated!"); | 315 throw new IllegalStateException("Connection is already authenticated!"); |
312 } | 316 } |
313 | 317 |
314 if(am == null) { | 318 if (am == null) { |
315 am = new AuthenticationManager(tm); | 319 am = new AuthenticationManager(tm); |
316 } | 320 } |
317 | 321 |
318 if(cm == null) { | 322 if (cm == null) { |
319 cm = new ChannelManager(tm); | 323 cm = new ChannelManager(tm); |
320 } | 324 } |
321 | 325 |
322 if(user == null) { | 326 if (user == null) { |
323 throw new IllegalArgumentException("user argument is null"); | 327 throw new IllegalArgumentException("user argument is null"); |
324 } | 328 } |
325 | 329 |
326 authenticated = am.authenticatePublicKey(user, proxy); | 330 authenticated = am.authenticatePublicKey(user, proxy); |
327 | |
328 return authenticated; | 331 return authenticated; |
329 } | 332 } |
330 | 333 |
331 /** | 334 /** |
332 * After a successful connect, one has to authenticate oneself. This method | 335 * After a successful connect, one has to authenticate oneself. This method |
350 * @param user | 353 * @param user |
351 * @param password | 354 * @param password |
352 * @return if the connection is now authenticated. | 355 * @return if the connection is now authenticated. |
353 * @throws IOException | 356 * @throws IOException |
354 */ | 357 */ |
358 | |
355 public synchronized boolean authenticateWithPassword(String user, String password) throws IOException { | 359 public synchronized boolean authenticateWithPassword(String user, String password) throws IOException { |
356 if(tm == null) { | 360 if (tm == null) { |
357 throw new IllegalStateException("Connection is not established!"); | 361 throw new IllegalStateException("Connection is not established!"); |
358 } | 362 } |
359 | 363 |
360 if(authenticated) { | 364 if (authenticated) { |
361 throw new IllegalStateException("Connection is already authenticated!"); | 365 throw new IllegalStateException("Connection is already authenticated!"); |
362 } | 366 } |
363 | 367 |
364 if(am == null) { | 368 if (am == null) { |
365 am = new AuthenticationManager(tm); | 369 am = new AuthenticationManager(tm); |
366 } | 370 } |
367 | 371 |
368 if(cm == null) { | 372 if (cm == null) { |
369 cm = new ChannelManager(tm); | 373 cm = new ChannelManager(tm); |
370 } | 374 } |
371 | 375 |
372 if(user == null) { | 376 if (user == null) { |
373 throw new IllegalArgumentException("user argument is null"); | 377 throw new IllegalArgumentException("user argument is null"); |
374 } | 378 } |
375 | 379 |
376 if(password == null) { | 380 if (password == null) { |
377 throw new IllegalArgumentException("password argument is null"); | 381 throw new IllegalArgumentException("password argument is null"); |
378 } | 382 } |
379 | 383 |
380 authenticated = am.authenticatePassword(user, password); | 384 authenticated = am.authenticatePassword(user, password); |
381 | |
382 return authenticated; | 385 return authenticated; |
383 } | 386 } |
384 | 387 |
385 /** | 388 /** |
386 * After a successful connect, one has to authenticate oneself. | 389 * After a successful connect, one has to authenticate oneself. |
406 * | 409 * |
407 * @param user | 410 * @param user |
408 * @return if the connection is now authenticated. | 411 * @return if the connection is now authenticated. |
409 * @throws IOException | 412 * @throws IOException |
410 */ | 413 */ |
414 | |
411 public synchronized boolean authenticateWithNone(String user) throws IOException { | 415 public synchronized boolean authenticateWithNone(String user) throws IOException { |
412 if(tm == null) { | 416 if (tm == null) { |
413 throw new IllegalStateException("Connection is not established!"); | 417 throw new IllegalStateException("Connection is not established!"); |
414 } | 418 } |
415 | 419 |
416 if(authenticated) { | 420 if (authenticated) { |
417 throw new IllegalStateException("Connection is already authenticated!"); | 421 throw new IllegalStateException("Connection is already authenticated!"); |
418 } | 422 } |
419 | 423 |
420 if(am == null) { | 424 if (am == null) { |
421 am = new AuthenticationManager(tm); | 425 am = new AuthenticationManager(tm); |
422 } | 426 } |
423 | 427 |
424 if(cm == null) { | 428 if (cm == null) { |
425 cm = new ChannelManager(tm); | 429 cm = new ChannelManager(tm); |
426 } | 430 } |
427 | 431 |
428 if(user == null) { | 432 if (user == null) { |
429 throw new IllegalArgumentException("user argument is null"); | 433 throw new IllegalArgumentException("user argument is null"); |
430 } | 434 } |
431 | 435 |
432 /* Trigger the sending of the PacketUserauthRequestNone packet */ | 436 /* Trigger the sending of the PacketUserauthRequestNone packet */ |
433 /* (if not already done) */ | 437 /* (if not already done) */ |
434 | |
435 authenticated = am.authenticateNone(user); | 438 authenticated = am.authenticateNone(user); |
436 | |
437 return authenticated; | 439 return authenticated; |
438 } | 440 } |
439 | 441 |
440 /** | 442 /** |
441 * After a successful connect, one has to authenticate oneself. | 443 * After a successful connect, one has to authenticate oneself. |
473 * you must specify a password. Otherwise, this argument will be ignored | 475 * you must specify a password. Otherwise, this argument will be ignored |
474 * and can be set to <code>null</code>. | 476 * and can be set to <code>null</code>. |
475 * @return whether the connection is now authenticated. | 477 * @return whether the connection is now authenticated. |
476 * @throws IOException | 478 * @throws IOException |
477 */ | 479 */ |
480 | |
478 public synchronized boolean authenticateWithPublicKey(String user, char[] pemPrivateKey, String password) | 481 public synchronized boolean authenticateWithPublicKey(String user, char[] pemPrivateKey, String password) |
479 throws IOException { | 482 throws IOException { |
480 if(tm == null) { | 483 if (tm == null) { |
481 throw new IllegalStateException("Connection is not established!"); | 484 throw new IllegalStateException("Connection is not established!"); |
482 } | 485 } |
483 | 486 |
484 if(authenticated) { | 487 if (authenticated) { |
485 throw new IllegalStateException("Connection is already authenticated!"); | 488 throw new IllegalStateException("Connection is already authenticated!"); |
486 } | 489 } |
487 | 490 |
488 if(am == null) { | 491 if (am == null) { |
489 am = new AuthenticationManager(tm); | 492 am = new AuthenticationManager(tm); |
490 } | 493 } |
491 | 494 |
492 if(cm == null) { | 495 if (cm == null) { |
493 cm = new ChannelManager(tm); | 496 cm = new ChannelManager(tm); |
494 } | 497 } |
495 | 498 |
496 if(user == null) { | 499 if (user == null) { |
497 throw new IllegalArgumentException("user argument is null"); | 500 throw new IllegalArgumentException("user argument is null"); |
498 } | 501 } |
499 | 502 |
500 if(pemPrivateKey == null) { | 503 if (pemPrivateKey == null) { |
501 throw new IllegalArgumentException("pemPrivateKey argument is null"); | 504 throw new IllegalArgumentException("pemPrivateKey argument is null"); |
502 } | 505 } |
503 | 506 |
504 authenticated = am.authenticatePublicKey(user, pemPrivateKey, password, getOrCreateSecureRND()); | 507 authenticated = am.authenticatePublicKey(user, pemPrivateKey, password, getOrCreateSecureRND()); |
505 | |
506 return authenticated; | 508 return authenticated; |
507 } | 509 } |
508 | 510 |
509 /** | 511 /** |
510 * After a successful connect, one has to authenticate oneself. The | 512 * After a successful connect, one has to authenticate oneself. The |
576 * @param password If the PEM file is encrypted then you must specify the password. | 578 * @param password If the PEM file is encrypted then you must specify the password. |
577 * Otherwise, this argument will be ignored and can be set to <code>null</code>. | 579 * Otherwise, this argument will be ignored and can be set to <code>null</code>. |
578 * @return whether the connection is now authenticated. | 580 * @return whether the connection is now authenticated. |
579 * @throws IOException | 581 * @throws IOException |
580 */ | 582 */ |
583 | |
581 public synchronized boolean authenticateWithPublicKey(String user, File pemFile, String password) | 584 public synchronized boolean authenticateWithPublicKey(String user, File pemFile, String password) |
582 throws IOException { | 585 throws IOException { |
583 if(pemFile == null) { | 586 if (pemFile == null) { |
584 throw new IllegalArgumentException("pemFile argument is null"); | 587 throw new IllegalArgumentException("pemFile argument is null"); |
585 } | 588 } |
586 | 589 |
587 char[] buff = new char[256]; | 590 char[] buff = new char[256]; |
588 | |
589 CharArrayWriter cw = new CharArrayWriter(); | 591 CharArrayWriter cw = new CharArrayWriter(); |
590 | |
591 FileReader fr = new FileReader(pemFile); | 592 FileReader fr = new FileReader(pemFile); |
592 | 593 |
593 while(true) { | 594 while (true) { |
594 int len = fr.read(buff); | 595 int len = fr.read(buff); |
595 if(len < 0) { | 596 |
597 if (len < 0) { | |
596 break; | 598 break; |
597 } | 599 } |
600 | |
598 cw.write(buff, 0, len); | 601 cw.write(buff, 0, len); |
599 } | 602 } |
600 | 603 |
601 fr.close(); | 604 fr.close(); |
602 | |
603 return authenticateWithPublicKey(user, cw.toCharArray(), password); | 605 return authenticateWithPublicKey(user, cw.toCharArray(), password); |
604 } | 606 } |
605 | 607 |
606 /** | 608 /** |
607 * Add a {@link ConnectionMonitor} to this connection. Can be invoked at any time, | 609 * Add a {@link ConnectionMonitor} to this connection. Can be invoked at any time, |
614 * this method does nothing. | 616 * this method does nothing. |
615 * | 617 * |
616 * @param cmon An object implementing the {@link ConnectionMonitor} interface. | 618 * @param cmon An object implementing the {@link ConnectionMonitor} interface. |
617 * @see ConnectionMonitor | 619 * @see ConnectionMonitor |
618 */ | 620 */ |
621 | |
619 public synchronized void addConnectionMonitor(ConnectionMonitor cmon) { | 622 public synchronized void addConnectionMonitor(ConnectionMonitor cmon) { |
620 if(!connectionMonitors.contains(cmon)) { | 623 if (!connectionMonitors.contains(cmon)) { |
621 connectionMonitors.add(cmon); | 624 connectionMonitors.add(cmon); |
622 if(tm != null) { | 625 |
626 if (tm != null) { | |
623 tm.setConnectionMonitors(connectionMonitors); | 627 tm.setConnectionMonitors(connectionMonitors); |
624 } | 628 } |
625 } | 629 } |
626 } | 630 } |
627 | 631 |
629 * Remove a {@link ConnectionMonitor} from this connection. | 633 * Remove a {@link ConnectionMonitor} from this connection. |
630 * | 634 * |
631 * @param cmon | 635 * @param cmon |
632 * @return whether the monitor could be removed | 636 * @return whether the monitor could be removed |
633 */ | 637 */ |
638 | |
634 public synchronized boolean removeConnectionMonitor(ConnectionMonitor cmon) { | 639 public synchronized boolean removeConnectionMonitor(ConnectionMonitor cmon) { |
635 boolean existed = connectionMonitors.remove(cmon); | 640 boolean existed = connectionMonitors.remove(cmon); |
636 if(tm != null) { | 641 |
642 if (tm != null) { | |
637 tm.setConnectionMonitors(connectionMonitors); | 643 tm.setConnectionMonitors(connectionMonitors); |
638 } | 644 } |
645 | |
639 return existed; | 646 return existed; |
640 } | 647 } |
641 | 648 |
642 /** | 649 /** |
643 * Controls whether compression is used on the link or not. | 650 * Controls whether compression is used on the link or not. |
659 * Close the connection to the SSH-2 server. All assigned sessions will be | 666 * Close the connection to the SSH-2 server. All assigned sessions will be |
660 * closed, too. Can be called at any time. Don't forget to call this once | 667 * closed, too. Can be called at any time. Don't forget to call this once |
661 * you don't need a connection anymore - otherwise the receiver thread may | 668 * you don't need a connection anymore - otherwise the receiver thread may |
662 * run forever. | 669 * run forever. |
663 */ | 670 */ |
671 | |
664 public synchronized void close() { | 672 public synchronized void close() { |
665 if(cm != null) { | 673 if (cm != null) { |
666 cm.closeAllChannels(); | 674 cm.closeAllChannels(); |
667 } | 675 } |
668 if(tm != null) { | 676 |
677 if (tm != null) { | |
669 tm.close(); | 678 tm.close(); |
670 tm = null; | 679 tm = null; |
671 } | 680 } |
681 | |
672 am = null; | 682 am = null; |
673 cm = null; | 683 cm = null; |
674 authenticated = false; | 684 authenticated = false; |
675 } | 685 } |
676 | 686 |
677 public synchronized void close(IOException t) { | 687 public synchronized void close(IOException t) { |
678 if(cm != null) { | 688 if (cm != null) { |
679 cm.closeAllChannels(); | 689 cm.closeAllChannels(); |
680 } | 690 } |
681 if(tm != null) { | 691 |
692 if (tm != null) { | |
682 tm.close(t); | 693 tm.close(t); |
683 tm = null; | 694 tm = null; |
684 } | 695 } |
696 | |
685 am = null; | 697 am = null; |
686 cm = null; | 698 cm = null; |
687 authenticated = false; | 699 authenticated = false; |
688 } | 700 } |
689 | 701 |
691 * Same as {@link #connect(ServerHostKeyVerifier, int, int) connect(null, 0, 0)}. | 703 * Same as {@link #connect(ServerHostKeyVerifier, int, int) connect(null, 0, 0)}. |
692 * | 704 * |
693 * @return see comments for the {@link #connect(ServerHostKeyVerifier, int, int) connect(ServerHostKeyVerifier, int, int)} method. | 705 * @return see comments for the {@link #connect(ServerHostKeyVerifier, int, int) connect(ServerHostKeyVerifier, int, int)} method. |
694 * @throws IOException | 706 * @throws IOException |
695 */ | 707 */ |
708 | |
696 public synchronized ConnectionInfo connect() throws IOException { | 709 public synchronized ConnectionInfo connect() throws IOException { |
697 return connect(null, 0, 0); | 710 return connect(null, 0, 0); |
698 } | 711 } |
699 | 712 |
700 /** | 713 /** |
701 * Same as {@link #connect(ServerHostKeyVerifier, int, int) connect(verifier, 0, 0)}. | 714 * Same as {@link #connect(ServerHostKeyVerifier, int, int) connect(verifier, 0, 0)}. |
702 * | 715 * |
703 * @return see comments for the {@link #connect(ServerHostKeyVerifier, int, int) connect(ServerHostKeyVerifier, int, int)} method. | 716 * @return see comments for the {@link #connect(ServerHostKeyVerifier, int, int) connect(ServerHostKeyVerifier, int, int)} method. |
704 * @throws IOException | 717 * @throws IOException |
705 */ | 718 */ |
719 | |
706 public synchronized ConnectionInfo connect(ServerHostKeyVerifier verifier) throws IOException { | 720 public synchronized ConnectionInfo connect(ServerHostKeyVerifier verifier) throws IOException { |
707 return connect(verifier, 0, 0); | 721 return connect(verifier, 0, 0); |
708 } | 722 } |
709 | 723 |
710 /** | 724 /** |
766 * If a HTTP proxy is being used and the proxy refuses the connection, | 780 * If a HTTP proxy is being used and the proxy refuses the connection, |
767 * then a {@link HTTPProxyException} may be thrown, which | 781 * then a {@link HTTPProxyException} may be thrown, which |
768 * contains the details returned by the proxy. If the proxy is buggy and does | 782 * contains the details returned by the proxy. If the proxy is buggy and does |
769 * not return a proper HTTP response, then a normal IOException is thrown instead. | 783 * not return a proper HTTP response, then a normal IOException is thrown instead. |
770 */ | 784 */ |
785 | |
771 public synchronized ConnectionInfo connect(ServerHostKeyVerifier verifier, int connectTimeout, int kexTimeout) | 786 public synchronized ConnectionInfo connect(ServerHostKeyVerifier verifier, int connectTimeout, int kexTimeout) |
772 throws IOException { | 787 throws IOException { |
773 final class TimeoutState { | 788 final class TimeoutState { |
774 boolean isCancelled = false; | 789 boolean isCancelled = false; |
775 boolean timeoutSocketClosed = false; | 790 boolean timeoutSocketClosed = false; |
776 } | 791 } |
777 | 792 |
778 if(tm != null) { | 793 if (tm != null) { |
779 throw new IllegalStateException(String.format("Connection to %s is already in connected state", hostname)); | 794 throw new IllegalStateException(String.format("Connection to %s is already in connected state", hostname)); |
780 } | 795 } |
781 | 796 |
782 if(connectTimeout < 0) { | 797 if (connectTimeout < 0) { |
783 throw new IllegalArgumentException("connectTimeout must be non-negative!"); | 798 throw new IllegalArgumentException("connectTimeout must be non-negative!"); |
784 } | 799 } |
785 | 800 |
786 if(kexTimeout < 0) { | 801 if (kexTimeout < 0) { |
787 throw new IllegalArgumentException("kexTimeout must be non-negative!"); | 802 throw new IllegalArgumentException("kexTimeout must be non-negative!"); |
788 } | 803 } |
789 | 804 |
790 final TimeoutState state = new TimeoutState(); | 805 final TimeoutState state = new TimeoutState(); |
791 | 806 |
792 if(null == proxy) { | 807 if (null == proxy) { |
793 tm = new ClientTransportManager(new Socket()); | 808 tm = new ClientTransportManager(new Socket()); |
794 } | 809 } |
795 else { | 810 else { |
796 tm = new HTTPProxyClientTransportManager(new Socket(), proxy); | 811 tm = new HTTPProxyClientTransportManager(new Socket(), proxy); |
797 } | 812 } |
813 | |
798 tm.setSoTimeout(connectTimeout); | 814 tm.setSoTimeout(connectTimeout); |
799 tm.setTcpNoDelay(tcpNoDelay); | 815 tm.setTcpNoDelay(tcpNoDelay); |
800 tm.setConnectionMonitors(connectionMonitors); | 816 tm.setConnectionMonitors(connectionMonitors); |
801 | 817 |
802 try { | 818 try { |
803 TimeoutToken token = null; | 819 TimeoutToken token = null; |
804 | 820 |
805 if(kexTimeout > 0) { | 821 if (kexTimeout > 0) { |
806 final Runnable timeoutHandler = new Runnable() { | 822 final Runnable timeoutHandler = new Runnable() { |
807 public void run() { | 823 public void run() { |
808 synchronized(state) { | 824 synchronized (state) { |
809 if(state.isCancelled) { | 825 if (state.isCancelled) { |
810 return; | 826 return; |
811 } | 827 } |
828 | |
812 state.timeoutSocketClosed = true; | 829 state.timeoutSocketClosed = true; |
813 tm.close(new SocketTimeoutException("The connect timeout expired")); | 830 tm.close(new SocketTimeoutException("The connect timeout expired")); |
814 } | 831 } |
815 } | 832 } |
816 }; | 833 }; |
817 | |
818 long timeoutHorizont = System.currentTimeMillis() + kexTimeout; | 834 long timeoutHorizont = System.currentTimeMillis() + kexTimeout; |
819 | |
820 token = TimeoutService.addTimeoutHandler(timeoutHorizont, timeoutHandler); | 835 token = TimeoutService.addTimeoutHandler(timeoutHorizont, timeoutHandler); |
821 } | 836 } |
822 | 837 |
823 tm.connect(hostname, port, softwareversion, cryptoWishList, verifier, dhgexpara, connectTimeout, | 838 tm.connect(hostname, port, softwareversion, cryptoWishList, verifier, dhgexpara, connectTimeout, |
824 getOrCreateSecureRND()); | 839 getOrCreateSecureRND()); |
825 | 840 /* Wait until first KEX has finished */ |
826 /* Wait until first KEX has finished */ | |
827 | |
828 ConnectionInfo ci = tm.getConnectionInfo(1); | 841 ConnectionInfo ci = tm.getConnectionInfo(1); |
829 | 842 |
830 /* Now try to cancel the timeout, if needed */ | 843 /* Now try to cancel the timeout, if needed */ |
831 | 844 |
832 if(token != null) { | 845 if (token != null) { |
833 TimeoutService.cancelTimeoutHandler(token); | 846 TimeoutService.cancelTimeoutHandler(token); |
834 | 847 |
835 /* Were we too late? */ | 848 /* Were we too late? */ |
836 | 849 |
837 synchronized(state) { | 850 synchronized (state) { |
838 if(state.timeoutSocketClosed) { | 851 if (state.timeoutSocketClosed) { |
839 throw new IOException("This exception will be replaced by the one below =)"); | 852 throw new IOException("This exception will be replaced by the one below =)"); |
840 } | 853 } |
854 | |
841 /* Just in case the "cancelTimeoutHandler" invocation came just a little bit | 855 /* Just in case the "cancelTimeoutHandler" invocation came just a little bit |
842 * too late but the handler did not enter the semaphore yet - we can | 856 * too late but the handler did not enter the semaphore yet - we can |
843 * still stop it. | 857 * still stop it. |
844 */ | 858 */ |
845 state.isCancelled = true; | 859 state.isCancelled = true; |
846 } | 860 } |
847 } | 861 } |
848 | 862 |
849 return ci; | 863 return ci; |
850 } | 864 } |
851 catch(SocketTimeoutException e) { | 865 catch (SocketTimeoutException e) { |
852 throw e; | 866 throw e; |
853 } | 867 } |
854 catch(HTTPProxyException e) { | 868 catch (HTTPProxyException e) { |
855 throw e; | 869 throw e; |
856 } | 870 } |
857 catch(IOException e) { | 871 catch (IOException e) { |
858 // This will also invoke any registered connection monitors | 872 // This will also invoke any registered connection monitors |
859 close(e); | 873 close(e); |
860 | 874 |
861 synchronized(state) { | 875 synchronized (state) { |
862 /* Show a clean exception, not something like "the socket is closed!?!" */ | 876 /* Show a clean exception, not something like "the socket is closed!?!" */ |
863 if(state.timeoutSocketClosed) { | 877 if (state.timeoutSocketClosed) { |
864 throw new SocketTimeoutException(String.format("The kexTimeout (%d ms) expired.", kexTimeout)); | 878 throw new SocketTimeoutException(String.format("The kexTimeout (%d ms) expired.", kexTimeout)); |
865 } | 879 } |
866 } | 880 } |
881 | |
867 throw e; | 882 throw e; |
868 } | 883 } |
869 } | 884 } |
870 | 885 |
871 /** | 886 /** |
881 * @param host_to_connect target address (IP or hostname) | 896 * @param host_to_connect target address (IP or hostname) |
882 * @param port_to_connect target port | 897 * @param port_to_connect target port |
883 * @return A {@link LocalPortForwarder} object. | 898 * @return A {@link LocalPortForwarder} object. |
884 * @throws IOException | 899 * @throws IOException |
885 */ | 900 */ |
901 | |
886 public synchronized LocalPortForwarder createLocalPortForwarder(int local_port, String host_to_connect, | 902 public synchronized LocalPortForwarder createLocalPortForwarder(int local_port, String host_to_connect, |
887 int port_to_connect) throws IOException { | 903 int port_to_connect) throws IOException { |
888 this.checkConnection(); | 904 this.checkConnection(); |
889 | |
890 return new LocalPortForwarder(cm, local_port, host_to_connect, port_to_connect); | 905 return new LocalPortForwarder(cm, local_port, host_to_connect, port_to_connect); |
891 } | 906 } |
892 | 907 |
893 /** | 908 /** |
894 * Creates a new {@link LocalPortForwarder}. | 909 * Creates a new {@link LocalPortForwarder}. |
903 * @param host_to_connect target address (IP or hostname) | 918 * @param host_to_connect target address (IP or hostname) |
904 * @param port_to_connect target port | 919 * @param port_to_connect target port |
905 * @return A {@link LocalPortForwarder} object. | 920 * @return A {@link LocalPortForwarder} object. |
906 * @throws IOException | 921 * @throws IOException |
907 */ | 922 */ |
923 | |
908 public synchronized LocalPortForwarder createLocalPortForwarder(InetSocketAddress addr, String host_to_connect, | 924 public synchronized LocalPortForwarder createLocalPortForwarder(InetSocketAddress addr, String host_to_connect, |
909 int port_to_connect) throws IOException { | 925 int port_to_connect) throws IOException { |
910 this.checkConnection(); | 926 this.checkConnection(); |
911 | |
912 return new LocalPortForwarder(cm, addr, host_to_connect, port_to_connect); | 927 return new LocalPortForwarder(cm, addr, host_to_connect, port_to_connect); |
913 } | 928 } |
914 | 929 |
915 /** | 930 /** |
916 * Creates a new {@link LocalStreamForwarder}. | 931 * Creates a new {@link LocalStreamForwarder}. |
921 * @param host_to_connect | 936 * @param host_to_connect |
922 * @param port_to_connect | 937 * @param port_to_connect |
923 * @return A {@link LocalStreamForwarder} object. | 938 * @return A {@link LocalStreamForwarder} object. |
924 * @throws IOException | 939 * @throws IOException |
925 */ | 940 */ |
941 | |
926 public synchronized LocalStreamForwarder createLocalStreamForwarder(String host_to_connect, int port_to_connect) | 942 public synchronized LocalStreamForwarder createLocalStreamForwarder(String host_to_connect, int port_to_connect) |
927 throws IOException { | 943 throws IOException { |
928 this.checkConnection(); | 944 this.checkConnection(); |
929 | |
930 return new LocalStreamForwarder(cm, host_to_connect, port_to_connect); | 945 return new LocalStreamForwarder(cm, host_to_connect, port_to_connect); |
931 } | 946 } |
932 | 947 |
933 /** | 948 /** |
934 * Creates a new {@link DynamicPortForwarder}. A | 949 * Creates a new {@link DynamicPortForwarder}. A |
992 * Note: This factory method will probably disappear in the future. | 1007 * Note: This factory method will probably disappear in the future. |
993 * | 1008 * |
994 * @return A {@link SCPClient} object. | 1009 * @return A {@link SCPClient} object. |
995 * @throws IOException | 1010 * @throws IOException |
996 */ | 1011 */ |
1012 | |
997 public synchronized SCPClient createSCPClient() throws IOException { | 1013 public synchronized SCPClient createSCPClient() throws IOException { |
998 this.checkConnection(); | 1014 this.checkConnection(); |
999 | |
1000 return new SCPClient(this); | 1015 return new SCPClient(this); |
1001 } | 1016 } |
1002 | 1017 |
1003 /** | 1018 /** |
1004 * Force an asynchronous key re-exchange (the call does not block). The | 1019 * Force an asynchronous key re-exchange (the call does not block). The |
1010 * Note: This implementation will never start a key exchange (other than the initial one) | 1025 * Note: This implementation will never start a key exchange (other than the initial one) |
1011 * unless you or the SSH-2 server ask for it. | 1026 * unless you or the SSH-2 server ask for it. |
1012 * | 1027 * |
1013 * @throws IOException In case of any failure behind the scenes. | 1028 * @throws IOException In case of any failure behind the scenes. |
1014 */ | 1029 */ |
1030 | |
1015 public synchronized void forceKeyExchange() throws IOException { | 1031 public synchronized void forceKeyExchange() throws IOException { |
1016 this.checkConnection(); | 1032 this.checkConnection(); |
1017 | |
1018 tm.forceKeyExchange(cryptoWishList, dhgexpara, null, null, null); | 1033 tm.forceKeyExchange(cryptoWishList, dhgexpara, null, null, null); |
1019 } | 1034 } |
1020 | 1035 |
1021 /** | 1036 /** |
1022 * Returns the hostname that was passed to the constructor. | 1037 * Returns the hostname that was passed to the constructor. |
1023 * | 1038 * |
1024 * @return the hostname | 1039 * @return the hostname |
1025 */ | 1040 */ |
1041 | |
1026 public synchronized String getHostname() { | 1042 public synchronized String getHostname() { |
1027 return hostname; | 1043 return hostname; |
1028 } | 1044 } |
1029 | 1045 |
1030 /** | 1046 /** |
1031 * Returns the port that was passed to the constructor. | 1047 * Returns the port that was passed to the constructor. |
1032 * | 1048 * |
1033 * @return the TCP port | 1049 * @return the TCP port |
1034 */ | 1050 */ |
1051 | |
1035 public synchronized int getPort() { | 1052 public synchronized int getPort() { |
1036 return port; | 1053 return port; |
1037 } | 1054 } |
1038 | 1055 |
1039 /** | 1056 /** |
1042 * established (successfully connected). | 1059 * established (successfully connected). |
1043 * | 1060 * |
1044 * @return A {@link ConnectionInfo} object. | 1061 * @return A {@link ConnectionInfo} object. |
1045 * @throws IOException In case of any failure behind the scenes. | 1062 * @throws IOException In case of any failure behind the scenes. |
1046 */ | 1063 */ |
1064 | |
1047 public synchronized ConnectionInfo getConnectionInfo() throws IOException { | 1065 public synchronized ConnectionInfo getConnectionInfo() throws IOException { |
1048 this.checkConnection(); | 1066 this.checkConnection(); |
1049 | |
1050 return tm.getConnectionInfo(1); | 1067 return tm.getConnectionInfo(1); |
1051 } | 1068 } |
1052 | 1069 |
1053 /** | 1070 /** |
1054 * After a successful connect, one has to authenticate oneself. This method | 1071 * After a successful connect, one has to authenticate oneself. This method |
1070 * | 1087 * |
1071 * @param user A <code>String</code> holding the username. | 1088 * @param user A <code>String</code> holding the username. |
1072 * @return a (possibly emtpy) array holding authentication method names. | 1089 * @return a (possibly emtpy) array holding authentication method names. |
1073 * @throws IOException | 1090 * @throws IOException |
1074 */ | 1091 */ |
1092 | |
1075 public synchronized String[] getRemainingAuthMethods(String user) throws IOException { | 1093 public synchronized String[] getRemainingAuthMethods(String user) throws IOException { |
1076 if(user == null) { | 1094 if (user == null) { |
1077 throw new IllegalArgumentException("user argument may not be NULL!"); | 1095 throw new IllegalArgumentException("user argument may not be NULL!"); |
1078 } | 1096 } |
1079 | 1097 |
1080 if(tm == null) { | 1098 if (tm == null) { |
1081 throw new IllegalStateException("Connection is not established!"); | 1099 throw new IllegalStateException("Connection is not established!"); |
1082 } | 1100 } |
1083 | 1101 |
1084 if(authenticated) { | 1102 if (authenticated) { |
1085 throw new IllegalStateException("Connection is already authenticated!"); | 1103 throw new IllegalStateException("Connection is already authenticated!"); |
1086 } | 1104 } |
1087 | 1105 |
1088 if(am == null) { | 1106 if (am == null) { |
1089 am = new AuthenticationManager(tm); | 1107 am = new AuthenticationManager(tm); |
1090 } | 1108 } |
1091 | 1109 |
1092 if(cm == null) { | 1110 if (cm == null) { |
1093 cm = new ChannelManager(tm); | 1111 cm = new ChannelManager(tm); |
1094 } | 1112 } |
1095 | 1113 |
1096 final Set<String> remainingMethods = am.getRemainingMethods(user); | 1114 final Set<String> remainingMethods = am.getRemainingMethods(user); |
1097 return remainingMethods.toArray(new String[remainingMethods.size()]); | 1115 return remainingMethods.toArray(new String[remainingMethods.size()]); |
1102 * time. | 1120 * time. |
1103 * | 1121 * |
1104 * @return <code>true</code> if no further authentication steps are | 1122 * @return <code>true</code> if no further authentication steps are |
1105 * needed. | 1123 * needed. |
1106 */ | 1124 */ |
1125 | |
1107 public synchronized boolean isAuthenticationComplete() { | 1126 public synchronized boolean isAuthenticationComplete() { |
1108 return authenticated; | 1127 return authenticated; |
1109 } | 1128 } |
1110 | 1129 |
1111 /** | 1130 /** |
1118 * If you are interested in the details, then have a look at RFC4252. | 1137 * If you are interested in the details, then have a look at RFC4252. |
1119 * | 1138 * |
1120 * @return if the there was a failed authentication step and the last one | 1139 * @return if the there was a failed authentication step and the last one |
1121 * was marked as a "partial success". | 1140 * was marked as a "partial success". |
1122 */ | 1141 */ |
1142 | |
1123 public synchronized boolean isAuthenticationPartialSuccess() { | 1143 public synchronized boolean isAuthenticationPartialSuccess() { |
1124 if(am == null) { | 1144 if (am == null) { |
1125 return false; | 1145 return false; |
1126 } | 1146 } |
1147 | |
1127 return am.getPartialSuccess(); | 1148 return am.getPartialSuccess(); |
1128 } | 1149 } |
1129 | 1150 |
1130 /** | 1151 /** |
1131 * Checks if a specified authentication method is available. This method is | 1152 * Checks if a specified authentication method is available. This method is |
1136 * @param method An authentication method name (e.g., "publickey", "password", | 1157 * @param method An authentication method name (e.g., "publickey", "password", |
1137 * "keyboard-interactive") as specified by the SSH-2 standard. | 1158 * "keyboard-interactive") as specified by the SSH-2 standard. |
1138 * @return if the specified authentication method is currently available. | 1159 * @return if the specified authentication method is currently available. |
1139 * @throws IOException | 1160 * @throws IOException |
1140 */ | 1161 */ |
1162 | |
1141 public synchronized boolean isAuthMethodAvailable(String user, String method) throws IOException { | 1163 public synchronized boolean isAuthMethodAvailable(String user, String method) throws IOException { |
1142 String methods[] = getRemainingAuthMethods(user); | 1164 String methods[] = getRemainingAuthMethods(user); |
1143 for(final String m : methods) { | 1165 |
1144 if(m.compareTo(method) == 0) { | 1166 for (final String m : methods) { |
1167 if (m.compareTo(method) == 0) { | |
1145 return true; | 1168 return true; |
1146 } | 1169 } |
1147 } | 1170 } |
1171 | |
1148 return false; | 1172 return false; |
1149 } | 1173 } |
1150 | 1174 |
1151 private SecureRandom getOrCreateSecureRND() { | 1175 private SecureRandom getOrCreateSecureRND() { |
1152 if(generator == null) { | 1176 if (generator == null) { |
1153 generator = new SecureRandom(); | 1177 generator = new SecureRandom(); |
1154 } | 1178 } |
1179 | |
1155 return generator; | 1180 return generator; |
1156 } | 1181 } |
1157 | 1182 |
1158 /** | 1183 /** |
1159 * Open a new {@link Session} on this connection. Works only after one has passed | 1184 * Open a new {@link Session} on this connection. Works only after one has passed |
1161 * concurrent sessions. | 1186 * concurrent sessions. |
1162 * | 1187 * |
1163 * @return A {@link Session} object. | 1188 * @return A {@link Session} object. |
1164 * @throws IOException | 1189 * @throws IOException |
1165 */ | 1190 */ |
1191 | |
1166 public synchronized Session openSession() throws IOException { | 1192 public synchronized Session openSession() throws IOException { |
1167 this.checkConnection(); | 1193 this.checkConnection(); |
1168 | |
1169 return new Session(cm, getOrCreateSecureRND()); | 1194 return new Session(cm, getOrCreateSecureRND()); |
1170 } | 1195 } |
1171 | 1196 |
1172 /** | 1197 /** |
1173 * Send an SSH_MSG_IGNORE packet. This method will generate a random data attribute | 1198 * Send an SSH_MSG_IGNORE packet. This method will generate a random data attribute |
1175 * <p/> | 1200 * <p/> |
1176 * This method must only be called once the connection is established. | 1201 * This method must only be called once the connection is established. |
1177 * | 1202 * |
1178 * @throws IOException | 1203 * @throws IOException |
1179 */ | 1204 */ |
1205 | |
1180 public synchronized void sendIgnorePacket() throws IOException { | 1206 public synchronized void sendIgnorePacket() throws IOException { |
1181 SecureRandom rnd = getOrCreateSecureRND(); | 1207 SecureRandom rnd = getOrCreateSecureRND(); |
1182 | |
1183 byte[] data = new byte[rnd.nextInt(16)]; | 1208 byte[] data = new byte[rnd.nextInt(16)]; |
1184 rnd.nextBytes(data); | 1209 rnd.nextBytes(data); |
1185 | |
1186 sendIgnorePacket(data); | 1210 sendIgnorePacket(data); |
1187 } | 1211 } |
1188 | 1212 |
1189 /** | 1213 /** |
1190 * Send an SSH_MSG_IGNORE packet with the given data attribute. | 1214 * Send an SSH_MSG_IGNORE packet with the given data attribute. |
1191 * <p/> | 1215 * <p/> |
1192 * This method must only be called once the connection is established. | 1216 * This method must only be called once the connection is established. |
1193 * | 1217 * |
1194 * @throws IOException | 1218 * @throws IOException |
1195 */ | 1219 */ |
1220 | |
1196 public synchronized void sendIgnorePacket(byte[] data) throws IOException { | 1221 public synchronized void sendIgnorePacket(byte[] data) throws IOException { |
1197 this.checkConnection(); | 1222 this.checkConnection(); |
1198 | |
1199 PacketIgnore pi = new PacketIgnore(data); | 1223 PacketIgnore pi = new PacketIgnore(data); |
1200 | |
1201 tm.sendMessage(pi.getPayload()); | 1224 tm.sendMessage(pi.getPayload()); |
1202 } | 1225 } |
1203 | 1226 |
1204 /** | 1227 /** |
1205 * Controls whether compression is used on the link or not. | 1228 * Controls whether compression is used on the link or not. |
1206 */ | 1229 */ |
1230 | |
1207 public synchronized void setCompression(String[] algorithms) { | 1231 public synchronized void setCompression(String[] algorithms) { |
1208 CompressionFactory.checkCompressorList(algorithms); | 1232 CompressionFactory.checkCompressorList(algorithms); |
1209 cryptoWishList.c2s_comp_algos = algorithms; | 1233 cryptoWishList.c2s_comp_algos = algorithms; |
1210 } | 1234 } |
1211 | 1235 |
1213 cryptoWishList.c2s_comp_algos = CompressionFactory.getDefaultCompressorList(); | 1237 cryptoWishList.c2s_comp_algos = CompressionFactory.getDefaultCompressorList(); |
1214 cryptoWishList.s2c_comp_algos = CompressionFactory.getDefaultCompressorList(); | 1238 cryptoWishList.s2c_comp_algos = CompressionFactory.getDefaultCompressorList(); |
1215 } | 1239 } |
1216 | 1240 |
1217 public synchronized void disableCompression() { | 1241 public synchronized void disableCompression() { |
1218 cryptoWishList.c2s_comp_algos = new String[]{"none"}; | 1242 cryptoWishList.c2s_comp_algos = new String[] {"none"}; |
1219 cryptoWishList.s2c_comp_algos = new String[]{"none"}; | 1243 cryptoWishList.s2c_comp_algos = new String[] {"none"}; |
1220 } | 1244 } |
1221 | 1245 |
1222 /** | 1246 /** |
1223 * Unless you know what you are doing, you will never need this. | 1247 * Unless you know what you are doing, you will never need this. |
1224 */ | 1248 */ |
1249 | |
1225 public synchronized void setClient2ServerCiphers(final String[] ciphers) { | 1250 public synchronized void setClient2ServerCiphers(final String[] ciphers) { |
1226 if((ciphers == null) || (ciphers.length == 0)) { | 1251 if ((ciphers == null) || (ciphers.length == 0)) { |
1227 throw new IllegalArgumentException(); | 1252 throw new IllegalArgumentException(); |
1228 } | 1253 } |
1254 | |
1229 BlockCipherFactory.checkCipherList(ciphers); | 1255 BlockCipherFactory.checkCipherList(ciphers); |
1230 cryptoWishList.c2s_enc_algos = ciphers; | 1256 cryptoWishList.c2s_enc_algos = ciphers; |
1231 } | 1257 } |
1232 | 1258 |
1233 /** | 1259 /** |
1234 * Unless you know what you are doing, you will never need this. | 1260 * Unless you know what you are doing, you will never need this. |
1235 */ | 1261 */ |
1262 | |
1236 public synchronized void setClient2ServerMACs(final String[] macs) { | 1263 public synchronized void setClient2ServerMACs(final String[] macs) { |
1237 MAC.checkMacList(macs); | 1264 MAC.checkMacList(macs); |
1238 cryptoWishList.c2s_mac_algos = macs; | 1265 cryptoWishList.c2s_mac_algos = macs; |
1239 } | 1266 } |
1240 | 1267 |
1243 * know what you are doing, you will never need this. Default values are | 1270 * know what you are doing, you will never need this. Default values are |
1244 * defined in the {@link DHGexParameters} class. | 1271 * defined in the {@link DHGexParameters} class. |
1245 * | 1272 * |
1246 * @param dgp {@link DHGexParameters}, non null. | 1273 * @param dgp {@link DHGexParameters}, non null. |
1247 */ | 1274 */ |
1275 | |
1248 public synchronized void setDHGexParameters(DHGexParameters dgp) { | 1276 public synchronized void setDHGexParameters(DHGexParameters dgp) { |
1249 if(dgp == null) { | 1277 if (dgp == null) { |
1250 throw new IllegalArgumentException(); | 1278 throw new IllegalArgumentException(); |
1251 } | 1279 } |
1252 | 1280 |
1253 dhgexpara = dgp; | 1281 dhgexpara = dgp; |
1254 } | 1282 } |
1255 | 1283 |
1256 /** | 1284 /** |
1257 * Unless you know what you are doing, you will never need this. | 1285 * Unless you know what you are doing, you will never need this. |
1258 */ | 1286 */ |
1287 | |
1259 public synchronized void setServer2ClientCiphers(final String[] ciphers) { | 1288 public synchronized void setServer2ClientCiphers(final String[] ciphers) { |
1260 BlockCipherFactory.checkCipherList(ciphers); | 1289 BlockCipherFactory.checkCipherList(ciphers); |
1261 cryptoWishList.s2c_enc_algos = ciphers; | 1290 cryptoWishList.s2c_enc_algos = ciphers; |
1262 } | 1291 } |
1263 | 1292 |
1264 /** | 1293 /** |
1265 * Unless you know what you are doing, you will never need this. | 1294 * Unless you know what you are doing, you will never need this. |
1266 */ | 1295 */ |
1296 | |
1267 public synchronized void setServer2ClientMACs(final String[] macs) { | 1297 public synchronized void setServer2ClientMACs(final String[] macs) { |
1268 MAC.checkMacList(macs); | 1298 MAC.checkMacList(macs); |
1269 cryptoWishList.s2c_mac_algos = macs; | 1299 cryptoWishList.s2c_mac_algos = macs; |
1270 } | 1300 } |
1271 | 1301 |
1279 * SSH-2 defines <code>ssh-dss</code> and <code>ssh-rsa</code>. | 1309 * SSH-2 defines <code>ssh-dss</code> and <code>ssh-rsa</code>. |
1280 * The entries of the array must be ordered after preference, i.e., | 1310 * The entries of the array must be ordered after preference, i.e., |
1281 * the entry at index 0 is the most preferred one. You must specify | 1311 * the entry at index 0 is the most preferred one. You must specify |
1282 * at least one entry. | 1312 * at least one entry. |
1283 */ | 1313 */ |
1314 | |
1284 public synchronized void setServerHostKeyAlgorithms(final String[] algos) { | 1315 public synchronized void setServerHostKeyAlgorithms(final String[] algos) { |
1285 KexManager.checkServerHostkeyAlgorithmsList(algos); | 1316 KexManager.checkServerHostkeyAlgorithmsList(algos); |
1286 cryptoWishList.serverHostKeyAlgorithms = algos; | 1317 cryptoWishList.serverHostKeyAlgorithms = algos; |
1287 } | 1318 } |
1288 | 1319 |
1294 * The default value that will be used is <code>false</code>. | 1325 * The default value that will be used is <code>false</code>. |
1295 * | 1326 * |
1296 * @param enable the argument passed to the <code>Socket.setTCPNoDelay()</code> method. | 1327 * @param enable the argument passed to the <code>Socket.setTCPNoDelay()</code> method. |
1297 * @throws IOException | 1328 * @throws IOException |
1298 */ | 1329 */ |
1330 | |
1299 public synchronized void setTCPNoDelay(boolean enable) throws IOException { | 1331 public synchronized void setTCPNoDelay(boolean enable) throws IOException { |
1300 tcpNoDelay = enable; | 1332 tcpNoDelay = enable; |
1301 if(tm != null) { | 1333 |
1334 if (tm != null) { | |
1302 tm.setTcpNoDelay(enable); | 1335 tm.setTcpNoDelay(enable); |
1303 } | 1336 } |
1304 } | 1337 } |
1305 | 1338 |
1306 /** | 1339 /** |
1361 * @param bindPort port number to bind on the server (must be > 0) | 1394 * @param bindPort port number to bind on the server (must be > 0) |
1362 * @param targetAddress the target address (IP or hostname) | 1395 * @param targetAddress the target address (IP or hostname) |
1363 * @param targetPort the target port | 1396 * @param targetPort the target port |
1364 * @throws IOException | 1397 * @throws IOException |
1365 */ | 1398 */ |
1399 | |
1366 public synchronized void requestRemotePortForwarding(String bindAddress, int bindPort, String targetAddress, | 1400 public synchronized void requestRemotePortForwarding(String bindAddress, int bindPort, String targetAddress, |
1367 int targetPort) throws IOException { | 1401 int targetPort) throws IOException { |
1368 this.checkConnection(); | 1402 this.checkConnection(); |
1369 | 1403 |
1370 if((bindAddress == null) || (targetAddress == null) || (bindPort <= 0) || (targetPort <= 0)) { | 1404 if ((bindAddress == null) || (targetAddress == null) || (bindPort <= 0) || (targetPort <= 0)) { |
1371 throw new IllegalArgumentException(); | 1405 throw new IllegalArgumentException(); |
1372 } | 1406 } |
1373 | 1407 |
1374 cm.requestGlobalForward(bindAddress, bindPort, targetAddress, targetPort); | 1408 cm.requestGlobalForward(bindAddress, bindPort, targetAddress, targetPort); |
1375 } | 1409 } |
1382 * | 1416 * |
1383 * @param bindPort the allocated port number on the server | 1417 * @param bindPort the allocated port number on the server |
1384 * @throws IOException if the remote side refuses the cancel request or another low | 1418 * @throws IOException if the remote side refuses the cancel request or another low |
1385 * level error occurs (e.g., the underlying connection is closed) | 1419 * level error occurs (e.g., the underlying connection is closed) |
1386 */ | 1420 */ |
1421 | |
1387 public synchronized void cancelRemotePortForwarding(int bindPort) throws IOException { | 1422 public synchronized void cancelRemotePortForwarding(int bindPort) throws IOException { |
1388 this.checkConnection(); | 1423 this.checkConnection(); |
1389 | |
1390 cm.requestCancelGlobalForward(bindPort); | 1424 cm.requestCancelGlobalForward(bindPort); |
1391 } | 1425 } |
1392 | 1426 |
1393 /** | 1427 /** |
1394 * Provide your own instance of SecureRandom. Can be used, e.g., if you | 1428 * Provide your own instance of SecureRandom. Can be used, e.g., if you |
1397 * The SecureRandom instance is used during key exchanges, public key authentication, | 1431 * The SecureRandom instance is used during key exchanges, public key authentication, |
1398 * x11 cookie generation and the like. | 1432 * x11 cookie generation and the like. |
1399 * | 1433 * |
1400 * @param rnd a SecureRandom instance | 1434 * @param rnd a SecureRandom instance |
1401 */ | 1435 */ |
1436 | |
1402 public synchronized void setSecureRandom(SecureRandom rnd) { | 1437 public synchronized void setSecureRandom(SecureRandom rnd) { |
1403 if(rnd == null) { | 1438 if (rnd == null) { |
1404 throw new IllegalArgumentException(); | 1439 throw new IllegalArgumentException(); |
1405 } | 1440 } |
1441 | |
1406 this.generator = rnd; | 1442 this.generator = rnd; |
1407 } | 1443 } |
1408 | 1444 |
1409 private void checkConnection() throws IllegalStateException { | 1445 private void checkConnection() throws IllegalStateException { |
1410 if(tm == null) { | 1446 if (tm == null) { |
1411 throw new IllegalStateException("You need to establish a connection first."); | 1447 throw new IllegalStateException("You need to establish a connection first."); |
1412 } | 1448 } |
1413 if(!authenticated) { | 1449 |
1450 if (!authenticated) { | |
1414 throw new IllegalStateException("The connection is not authenticated."); | 1451 throw new IllegalStateException("The connection is not authenticated."); |
1415 } | 1452 } |
1416 } | 1453 } |
1417 } | 1454 } |