Home | History | Annotate | Download | only in ssh2
      1 /*
      2  * Copyright (c) 2006-2011 Christian Plattner. All rights reserved.
      3  * Please refer to the LICENSE.txt for licensing details.
      4  */
      5 package ch.ethz.ssh2;
      6 
      7 import java.io.CharArrayWriter;
      8 import java.io.File;
      9 import java.io.FileReader;
     10 import java.io.IOException;
     11 import java.net.InetSocketAddress;
     12 import java.net.SocketTimeoutException;
     13 import java.security.SecureRandom;
     14 import java.util.List;
     15 import java.util.Vector;
     16 
     17 import ch.ethz.ssh2.auth.AuthenticationManager;
     18 import ch.ethz.ssh2.channel.ChannelManager;
     19 import ch.ethz.ssh2.crypto.CryptoWishList;
     20 import ch.ethz.ssh2.crypto.cipher.BlockCipherFactory;
     21 import ch.ethz.ssh2.crypto.digest.MAC;
     22 import ch.ethz.ssh2.packets.PacketIgnore;
     23 import ch.ethz.ssh2.transport.KexManager;
     24 import ch.ethz.ssh2.transport.TransportManager;
     25 import ch.ethz.ssh2.util.TimeoutService;
     26 import ch.ethz.ssh2.util.TimeoutService.TimeoutToken;
     27 
     28 /**
     29  * A <code>Connection</code> is used to establish an encrypted TCP/IP
     30  * connection to a SSH-2 server.
     31  * <p>
     32  * Typically, one
     33  * <ol>
     34  * <li>creates a {@link #Connection(String) Connection} object.</li>
     35  * <li>calls the {@link #connect() connect()} method.</li>
     36  * <li>calls some of the authentication methods (e.g., {@link #authenticateWithPublicKey(String, File, String) authenticateWithPublicKey()}).</li>
     37  * <li>calls one or several times the {@link #openSession() openSession()} method.</li>
     38  * <li>finally, one must close the connection and release resources with the {@link #close() close()} method.</li>
     39  * </ol>
     40  *
     41  * @author Christian Plattner
     42  * @version $Id: Connection.java 37 2011-05-28 22:31:46Z dkocher (at) sudo.ch $
     43  */
     44 
     45 public class Connection
     46 {
     47 	/**
     48 	 * The identifier presented to the SSH-2 server.
     49 	 */
     50 	private String identification = "Ganymed-" + Version.getSpecification();
     51 
     52 	/* Will be used to generate all random data needed for the current connection.
     53 	 * Note: SecureRandom.nextBytes() is thread safe.
     54 	 */
     55 
     56 	private SecureRandom generator;
     57 
     58 	/**
     59 	 * Unless you know what you are doing, you will never need this.
     60 	 *
     61 	 * @return The list of supported cipher algorithms by this implementation.
     62 	 */
     63 	public static synchronized String[] getAvailableCiphers()
     64 	{
     65 		return BlockCipherFactory.getDefaultCipherList();
     66 	}
     67 
     68 	/**
     69 	 * Unless you know what you are doing, you will never need this.
     70 	 *
     71 	 * @return The list of supported MAC algorthims by this implementation.
     72 	 */
     73 	public static synchronized String[] getAvailableMACs()
     74 	{
     75 		return MAC.getMacList();
     76 	}
     77 
     78 	/**
     79 	 * Unless you know what you are doing, you will never need this.
     80 	 *
     81 	 * @return The list of supported server host key algorthims by this implementation.
     82 	 */
     83 	public static synchronized String[] getAvailableServerHostKeyAlgorithms()
     84 	{
     85 		return KexManager.getDefaultServerHostkeyAlgorithmList();
     86 	}
     87 
     88 	private AuthenticationManager am;
     89 
     90 	private boolean authenticated = false;
     91 	private ChannelManager cm;
     92 
     93 	private CryptoWishList cryptoWishList = new CryptoWishList();
     94 
     95 	private DHGexParameters dhgexpara = new DHGexParameters();
     96 
     97 	private final String hostname;
     98 
     99 	private final int port;
    100 
    101 	private TransportManager tm;
    102 
    103 	private boolean tcpNoDelay = false;
    104 
    105 	private ProxyData proxyData = null;
    106 
    107 	private List<ConnectionMonitor> connectionMonitors = new Vector<ConnectionMonitor>();
    108 
    109 	/**
    110 	 * Prepares a fresh <code>Connection</code> object which can then be used
    111 	 * to establish a connection to the specified SSH-2 server.
    112 	 * <p>
    113 	 * Same as {@link #Connection(String, int) Connection(hostname, 22)}.
    114 	 *
    115 	 * @param hostname the hostname of the SSH-2 server.
    116 	 */
    117 	public Connection(String hostname)
    118 	{
    119 		this(hostname, 22);
    120 	}
    121 
    122 	/**
    123 	 * Prepares a fresh <code>Connection</code> object which can then be used
    124 	 * to establish a connection to the specified SSH-2 server.
    125 	 *
    126 	 * @param hostname
    127 	 *            the host where we later want to connect to.
    128 	 * @param port
    129 	 *            port on the server, normally 22.
    130 	 */
    131 	public Connection(String hostname, int port)
    132 	{
    133 		this.hostname = hostname;
    134 		this.port = port;
    135 	}
    136 
    137 	public Connection(String hostname, int port, String identification)
    138 	{
    139 		this.hostname = hostname;
    140 		this.port = port;
    141         this.identification = identification;
    142 	}
    143 
    144 	/**
    145 	 * After a successful connect, one has to authenticate oneself. This method
    146 	 * is based on DSA (it uses DSA to sign a challenge sent by the server).
    147 	 * <p>
    148 	 * If the authentication phase is complete, <code>true</code> will be
    149 	 * returned. If the server does not accept the request (or if further
    150 	 * authentication steps are needed), <code>false</code> is returned and
    151 	 * one can retry either by using this or any other authentication method
    152 	 * (use the <code>getRemainingAuthMethods</code> method to get a list of
    153 	 * the remaining possible methods).
    154 	 *
    155 	 * @param user
    156 	 *            A <code>String</code> holding the username.
    157 	 * @param pem
    158 	 *            A <code>String</code> containing the DSA private key of the
    159 	 *            user in OpenSSH key format (PEM, you can't miss the
    160 	 *            "-----BEGIN DSA PRIVATE KEY-----" tag). The string may contain
    161 	 *            linefeeds.
    162 	 * @param password
    163 	 *            If the PEM string is 3DES encrypted ("DES-EDE3-CBC"), then you
    164 	 *            must specify the password. Otherwise, this argument will be
    165 	 *            ignored and can be set to <code>null</code>.
    166 	 *
    167 	 * @return whether the connection is now authenticated.
    168 	 * @throws IOException
    169 	 *
    170 	 * @deprecated You should use one of the {@link #authenticateWithPublicKey(String, File, String) authenticateWithPublicKey()}
    171 	 * 		      methods, this method is just a wrapper for it and will
    172 	 *            disappear in future builds.
    173 	 *
    174 	 */
    175 	public synchronized boolean authenticateWithDSA(String user, String pem, String password) throws IOException
    176 	{
    177 		if (tm == null)
    178 			throw new IllegalStateException("Connection is not established!");
    179 
    180 		if (authenticated)
    181 			throw new IllegalStateException("Connection is already authenticated!");
    182 
    183 		if (am == null)
    184 			am = new AuthenticationManager(tm);
    185 
    186 		if (cm == null)
    187 			cm = new ChannelManager(tm);
    188 
    189 		if (user == null)
    190 			throw new IllegalArgumentException("user argument is null");
    191 
    192 		if (pem == null)
    193 			throw new IllegalArgumentException("pem argument is null");
    194 
    195 		authenticated = am.authenticatePublicKey(user, pem.toCharArray(), password, getOrCreateSecureRND());
    196 
    197 		return authenticated;
    198 	}
    199 
    200 	/**
    201 	 * A wrapper that calls {@link #authenticateWithKeyboardInteractive(String, String[], InteractiveCallback)
    202 	 * authenticateWithKeyboardInteractivewith} a <code>null</code> submethod list.
    203 	 *
    204 	 * @param user
    205 	 *            A <code>String</code> holding the username.
    206 	 * @param cb
    207 	 *            An <code>InteractiveCallback</code> which will be used to
    208 	 *            determine the responses to the questions asked by the server.
    209 	 * @return whether the connection is now authenticated.
    210 	 * @throws IOException
    211 	 */
    212 	public synchronized boolean authenticateWithKeyboardInteractive(String user, InteractiveCallback cb)
    213 			throws IOException
    214 	{
    215 		return authenticateWithKeyboardInteractive(user, null, cb);
    216 	}
    217 
    218 	/**
    219 	 * After a successful connect, one has to authenticate oneself. This method
    220 	 * is based on "keyboard-interactive", specified in
    221 	 * draft-ietf-secsh-auth-kbdinteract-XX. Basically, you have to define a
    222 	 * callback object which will be feeded with challenges generated by the
    223 	 * server. Answers are then sent back to the server. It is possible that the
    224 	 * callback will be called several times during the invocation of this
    225 	 * method (e.g., if the server replies to the callback's answer(s) with
    226 	 * another challenge...)
    227 	 * <p>
    228 	 * If the authentication phase is complete, <code>true</code> will be
    229 	 * returned. If the server does not accept the request (or if further
    230 	 * authentication steps are needed), <code>false</code> is returned and
    231 	 * one can retry either by using this or any other authentication method
    232 	 * (use the <code>getRemainingAuthMethods</code> method to get a list of
    233 	 * the remaining possible methods).
    234 	 * <p>
    235 	 * Note: some SSH servers advertise "keyboard-interactive", however, any
    236 	 * interactive request will be denied (without having sent any challenge to
    237 	 * the client).
    238 	 *
    239 	 * @param user
    240 	 *            A <code>String</code> holding the username.
    241 	 * @param submethods
    242 	 *            An array of submethod names, see
    243 	 *            draft-ietf-secsh-auth-kbdinteract-XX. May be <code>null</code>
    244 	 *            to indicate an empty list.
    245 	 * @param cb
    246 	 *            An <code>InteractiveCallback</code> which will be used to
    247 	 *            determine the responses to the questions asked by the server.
    248 	 *
    249 	 * @return whether the connection is now authenticated.
    250 	 * @throws IOException
    251 	 */
    252 	public synchronized boolean authenticateWithKeyboardInteractive(String user, String[] submethods,
    253 			InteractiveCallback cb) throws IOException
    254 	{
    255 		if (cb == null)
    256 			throw new IllegalArgumentException("Callback may not ne NULL!");
    257 
    258 		if (tm == null)
    259 			throw new IllegalStateException("Connection is not established!");
    260 
    261 		if (authenticated)
    262 			throw new IllegalStateException("Connection is already authenticated!");
    263 
    264 		if (am == null)
    265 			am = new AuthenticationManager(tm);
    266 
    267 		if (cm == null)
    268 			cm = new ChannelManager(tm);
    269 
    270 		if (user == null)
    271 			throw new IllegalArgumentException("user argument is null");
    272 
    273 		authenticated = am.authenticateInteractive(user, submethods, cb);
    274 
    275 		return authenticated;
    276 	}
    277 
    278 	/**
    279 	 * After a successful connect, one has to authenticate oneself. This method
    280 	 * sends username and password to the server.
    281 	 * <p>
    282 	 * If the authentication phase is complete, <code>true</code> will be
    283 	 * returned. If the server does not accept the request (or if further
    284 	 * authentication steps are needed), <code>false</code> is returned and
    285 	 * one can retry either by using this or any other authentication method
    286 	 * (use the <code>getRemainingAuthMethods</code> method to get a list of
    287 	 * the remaining possible methods).
    288 	 * <p>
    289 	 * Note: if this method fails, then please double-check that it is actually
    290 	 * offered by the server (use {@link #getRemainingAuthMethods(String) getRemainingAuthMethods()}.
    291 	 * <p>
    292 	 * Often, password authentication is disabled, but users are not aware of it.
    293 	 * Many servers only offer "publickey" and "keyboard-interactive". However,
    294 	 * even though "keyboard-interactive" *feels* like password authentication
    295 	 * (e.g., when using the putty or openssh clients) it is *not* the same mechanism.
    296 	 *
    297 	 * @param user
    298 	 * @param password
    299 	 * @return if the connection is now authenticated.
    300 	 * @throws IOException
    301 	 */
    302 	public synchronized boolean authenticateWithPassword(String user, String password) throws IOException
    303 	{
    304 		if (tm == null)
    305 			throw new IllegalStateException("Connection is not established!");
    306 
    307 		if (authenticated)
    308 			throw new IllegalStateException("Connection is already authenticated!");
    309 
    310 		if (am == null)
    311 			am = new AuthenticationManager(tm);
    312 
    313 		if (cm == null)
    314 			cm = new ChannelManager(tm);
    315 
    316 		if (user == null)
    317 			throw new IllegalArgumentException("user argument is null");
    318 
    319 		if (password == null)
    320 			throw new IllegalArgumentException("password argument is null");
    321 
    322 		authenticated = am.authenticatePassword(user, password);
    323 
    324 		return authenticated;
    325 	}
    326 
    327 	/**
    328 	 * After a successful connect, one has to authenticate oneself.
    329 	 * This method can be used to explicitly use the special "none"
    330 	 * authentication method (where only a username has to be specified).
    331 	 * <p>
    332 	 * Note 1: The "none" method may always be tried by clients, however as by
    333 	 * the specs, the server will not explicitly announce it. In other words,
    334 	 * the "none" token will never show up in the list returned by
    335 	 * {@link #getRemainingAuthMethods(String)}.
    336 	 * <p>
    337 	 * Note 2: no matter which one of the authenticateWithXXX() methods
    338 	 * you call, the library will always issue exactly one initial "none"
    339 	 * authentication request to retrieve the initially allowed list of
    340 	 * authentication methods by the server. Please read RFC 4252 for the
    341 	 * details.
    342 	 * <p>
    343 	 * If the authentication phase is complete, <code>true</code> will be
    344 	 * returned. If further authentication steps are needed, <code>false</code>
    345 	 * is returned and one can retry by any other authentication method
    346 	 * (use the <code>getRemainingAuthMethods</code> method to get a list of
    347 	 * the remaining possible methods).
    348 	 *
    349 	 * @param user
    350 	 * @return if the connection is now authenticated.
    351 	 * @throws IOException
    352 	 */
    353 	public synchronized boolean authenticateWithNone(String user) throws IOException
    354 	{
    355 		if (tm == null)
    356 			throw new IllegalStateException("Connection is not established!");
    357 
    358 		if (authenticated)
    359 			throw new IllegalStateException("Connection is already authenticated!");
    360 
    361 		if (am == null)
    362 			am = new AuthenticationManager(tm);
    363 
    364 		if (cm == null)
    365 			cm = new ChannelManager(tm);
    366 
    367 		if (user == null)
    368 			throw new IllegalArgumentException("user argument is null");
    369 
    370 		/* Trigger the sending of the PacketUserauthRequestNone packet */
    371 		/* (if not already done)                                       */
    372 
    373 		authenticated = am.authenticateNone(user);
    374 
    375 		return authenticated;
    376 	}
    377 
    378 	/**
    379 	 * After a successful connect, one has to authenticate oneself.
    380 	 * The authentication method "publickey" works by signing a challenge
    381 	 * sent by the server. The signature is either DSA or RSA based - it
    382 	 * just depends on the type of private key you specify, either a DSA
    383 	 * or RSA private key in PEM format. And yes, this is may seem to be a
    384 	 * little confusing, the method is called "publickey" in the SSH-2 protocol
    385 	 * specification, however since we need to generate a signature, you
    386 	 * actually have to supply a private key =).
    387 	 * <p>
    388 	 * The private key contained in the PEM file may also be encrypted ("Proc-Type: 4,ENCRYPTED").
    389 	 * The library supports DES-CBC and DES-EDE3-CBC encryption, as well
    390 	 * as the more exotic PEM encrpytions AES-128-CBC, AES-192-CBC and AES-256-CBC.
    391 	 * <p>
    392 	 * If the authentication phase is complete, <code>true</code> will be
    393 	 * returned. If the server does not accept the request (or if further
    394 	 * authentication steps are needed), <code>false</code> is returned and
    395 	 * one can retry either by using this or any other authentication method
    396 	 * (use the <code>getRemainingAuthMethods</code> method to get a list of
    397 	 * the remaining possible methods).
    398 	 * <p>
    399 	 * NOTE PUTTY USERS: Event though your key file may start with "-----BEGIN..."
    400 	 * it is not in the expected format. You have to convert it to the OpenSSH
    401 	 * key format by using the "puttygen" tool (can be downloaded from the Putty
    402 	 * website). Simply load your key and then use the "Conversions/Export OpenSSH key"
    403 	 * functionality to get a proper PEM file.
    404 	 *
    405 	 * @param user
    406 	 *            A <code>String</code> holding the username.
    407 	 * @param pemPrivateKey
    408 	 *            A <code>char[]</code> containing a DSA or RSA private key of the
    409 	 *            user in OpenSSH key format (PEM, you can't miss the
    410 	 *            "-----BEGIN DSA PRIVATE KEY-----" or "-----BEGIN RSA PRIVATE KEY-----"
    411 	 *            tag). The char array may contain linebreaks/linefeeds.
    412 	 * @param password
    413 	 *            If the PEM structure is encrypted ("Proc-Type: 4,ENCRYPTED") then
    414 	 *            you must specify a password. Otherwise, this argument will be ignored
    415 	 *            and can be set to <code>null</code>.
    416 	 *
    417 	 * @return whether the connection is now authenticated.
    418 	 * @throws IOException
    419 	 */
    420 	public synchronized boolean authenticateWithPublicKey(String user, char[] pemPrivateKey, String password)
    421 			throws IOException
    422 	{
    423 		if (tm == null)
    424 			throw new IllegalStateException("Connection is not established!");
    425 
    426 		if (authenticated)
    427 			throw new IllegalStateException("Connection is already authenticated!");
    428 
    429 		if (am == null)
    430 			am = new AuthenticationManager(tm);
    431 
    432 		if (cm == null)
    433 			cm = new ChannelManager(tm);
    434 
    435 		if (user == null)
    436 			throw new IllegalArgumentException("user argument is null");
    437 
    438 		if (pemPrivateKey == null)
    439 			throw new IllegalArgumentException("pemPrivateKey argument is null");
    440 
    441 		authenticated = am.authenticatePublicKey(user, pemPrivateKey, password, getOrCreateSecureRND());
    442 
    443 		return authenticated;
    444 	}
    445 
    446 	/**
    447 	 * A convenience wrapper function which reads in a private key (PEM format, either DSA or RSA)
    448 	 * and then calls <code>authenticateWithPublicKey(String, char[], String)</code>.
    449 	 * <p>
    450 	 * NOTE PUTTY USERS: Event though your key file may start with "-----BEGIN..."
    451 	 * it is not in the expected format. You have to convert it to the OpenSSH
    452 	 * key format by using the "puttygen" tool (can be downloaded from the Putty
    453 	 * website). Simply load your key and then use the "Conversions/Export OpenSSH key"
    454 	 * functionality to get a proper PEM file.
    455 	 *
    456 	 * @param user
    457 	 *            A <code>String</code> holding the username.
    458 	 * @param pemFile
    459 	 *            A <code>File</code> object pointing to a file containing a DSA or RSA
    460 	 *            private key of the user in OpenSSH key format (PEM, you can't miss the
    461 	 *            "-----BEGIN DSA PRIVATE KEY-----" or "-----BEGIN RSA PRIVATE KEY-----"
    462 	 *            tag).
    463 	 * @param password
    464 	 *            If the PEM file is encrypted then you must specify the password.
    465 	 *            Otherwise, this argument will be ignored and can be set to <code>null</code>.
    466 	 *
    467 	 * @return whether the connection is now authenticated.
    468 	 * @throws IOException
    469 	 */
    470 	public synchronized boolean authenticateWithPublicKey(String user, File pemFile, String password)
    471 			throws IOException
    472 	{
    473 		if (pemFile == null)
    474 			throw new IllegalArgumentException("pemFile argument is null");
    475 
    476 		char[] buff = new char[256];
    477 
    478 		CharArrayWriter cw = new CharArrayWriter();
    479 
    480 		FileReader fr = new FileReader(pemFile);
    481 
    482 		while (true)
    483 		{
    484 			int len = fr.read(buff);
    485 			if (len < 0)
    486 				break;
    487 			cw.write(buff, 0, len);
    488 		}
    489 
    490 		fr.close();
    491 
    492 		return authenticateWithPublicKey(user, cw.toCharArray(), password);
    493 	}
    494 
    495 	/**
    496 	 * Add a {@link ConnectionMonitor} to this connection. Can be invoked at any time,
    497 	 * but it is best to add connection monitors before invoking
    498 	 * <code>connect()</code> to avoid glitches (e.g., you add a connection monitor after
    499 	 * a successful connect(), but the connection has died in the mean time. Then,
    500 	 * your connection monitor won't be notified.)
    501 	 * <p>
    502 	 * You can add as many monitors as you like.
    503 	 *
    504 	 * @see ConnectionMonitor
    505 	 *
    506 	 * @param cmon An object implementing the <code>ConnectionMonitor</code> interface.
    507 	 */
    508 	public synchronized void addConnectionMonitor(ConnectionMonitor cmon)
    509 	{
    510 		if (cmon == null)
    511 			throw new IllegalArgumentException("cmon argument is null");
    512 
    513 		connectionMonitors.add(cmon);
    514 
    515 		if (tm != null)
    516 			tm.setConnectionMonitors(connectionMonitors);
    517 	}
    518 
    519 	/**
    520 	 * Close the connection to the SSH-2 server. All assigned sessions will be
    521 	 * closed, too. Can be called at any time. Don't forget to call this once
    522 	 * you don't need a connection anymore - otherwise the receiver thread may
    523 	 * run forever.
    524 	 */
    525 	public synchronized void close()
    526 	{
    527 		Throwable t = new Throwable("Closed due to user request.");
    528 		close(t, false);
    529 	}
    530 
    531     public void close(Throwable t, boolean hard)
    532 	{
    533 		if (cm != null)
    534 			cm.closeAllChannels();
    535 
    536 		if (tm != null)
    537 		{
    538 			tm.close(t, hard == false);
    539 			tm = null;
    540 		}
    541 		am = null;
    542 		cm = null;
    543 		authenticated = false;
    544 	}
    545 
    546 	/**
    547 	 * Same as {@link #connect(ServerHostKeyVerifier, int, int) connect(null, 0, 0)}.
    548 	 *
    549 	 * @return see comments for the {@link #connect(ServerHostKeyVerifier, int, int) connect(ServerHostKeyVerifier, int, int)} method.
    550 	 * @throws IOException
    551 	 */
    552 	public synchronized ConnectionInfo connect() throws IOException
    553 	{
    554 		return connect(null, 0, 0);
    555 	}
    556 
    557 	/**
    558 	 * Same as {@link #connect(ServerHostKeyVerifier, int, int) connect(verifier, 0, 0)}.
    559 	 *
    560 	 * @return see comments for the {@link #connect(ServerHostKeyVerifier, int, int) connect(ServerHostKeyVerifier, int, int)} method.
    561 	 * @throws IOException
    562 	 */
    563 	public synchronized ConnectionInfo connect(ServerHostKeyVerifier verifier) throws IOException
    564 	{
    565 		return connect(verifier, 0, 0);
    566 	}
    567 
    568 	/**
    569 	 * Connect to the SSH-2 server and, as soon as the server has presented its
    570 	 * host key, use the {@link ServerHostKeyVerifier#verifyServerHostKey(String,
    571 	 * int, String, byte[]) ServerHostKeyVerifier.verifyServerHostKey()}
    572 	 * method of the <code>verifier</code> to ask for permission to proceed.
    573 	 * If <code>verifier</code> is <code>null</code>, then any host key will be
    574 	 * accepted - this is NOT recommended, since it makes man-in-the-middle attackes
    575 	 * VERY easy (somebody could put a proxy SSH server between you and the real server).
    576 	 * <p>
    577 	 * Note: The verifier will be called before doing any crypto calculations
    578 	 * (i.e., diffie-hellman). Therefore, if you don't like the presented host key then
    579 	 * no CPU cycles are wasted (and the evil server has less information about us).
    580 	 * <p>
    581 	 * However, it is still possible that the server presented a fake host key: the server
    582 	 * cheated (typically a sign for a man-in-the-middle attack) and is not able to generate
    583 	 * a signature that matches its host key. Don't worry, the library will detect such
    584 	 * a scenario later when checking the signature (the signature cannot be checked before
    585 	 * having completed the diffie-hellman exchange).
    586 	 * <p>
    587 	 * Note 2: The  {@link ServerHostKeyVerifier#verifyServerHostKey(String,
    588 	 * int, String, byte[]) ServerHostKeyVerifier.verifyServerHostKey()} method
    589 	 * will *NOT* be called from the current thread, the call is being made from a
    590 	 * background thread (there is a background dispatcher thread for every
    591 	 * established connection).
    592 	 * <p>
    593 	 * Note 3: This method will block as long as the key exchange of the underlying connection
    594 	 * has not been completed (and you have not specified any timeouts).
    595 	 * <p>
    596 	 * Note 4: If you want to re-use a connection object that was successfully connected,
    597 	 * then you must call the {@link #close()} method before invoking <code>connect()</code> again.
    598 	 *
    599 	 * @param verifier
    600 	 *            An object that implements the
    601 	 *            {@link ServerHostKeyVerifier} interface. Pass <code>null</code>
    602 	 *            to accept any server host key - NOT recommended.
    603 	 *
    604 	 * @param connectTimeout
    605 	 *            Connect the underlying TCP socket to the server with the given timeout
    606 	 *            value (non-negative, in milliseconds). Zero means no timeout. If a proxy is being
    607 	 *            used (see {@link #setProxyData(ProxyData)}), then this timeout is used for the
    608 	 *            connection establishment to the proxy.
    609 	 *
    610 	 * @param kexTimeout
    611 	 *            Timeout for complete connection establishment (non-negative,
    612 	 *            in milliseconds). Zero means no timeout. The timeout counts from the
    613 	 *            moment you invoke the connect() method and is cancelled as soon as the
    614 	 *            first key-exchange round has finished. It is possible that
    615 	 *            the timeout event will be fired during the invocation of the
    616 	 *            <code>verifier</code> callback, but it will only have an effect after
    617 	 *            the <code>verifier</code> returns.
    618 	 *
    619 	 * @return A {@link ConnectionInfo} object containing the details of
    620 	 *            the established connection.
    621 	 *
    622 	 * @throws IOException
    623 	 *            If any problem occurs, e.g., the server's host key is not
    624 	 *            accepted by the <code>verifier</code> or there is problem during
    625 	 *            the initial crypto setup (e.g., the signature sent by the server is wrong).
    626 	 *            <p>
    627 	 *            In case of a timeout (either connectTimeout or kexTimeout)
    628 	 *            a SocketTimeoutException is thrown.
    629 	 *            <p>
    630 	 *            An exception may also be thrown if the connection was already successfully
    631 	 *            connected (no matter if the connection broke in the mean time) and you invoke
    632 	 *            <code>connect()</code> again without having called {@link #close()} first.
    633 	 *            <p>
    634 	 *            If a HTTP proxy is being used and the proxy refuses the connection,
    635 	 *            then a {@link HTTPProxyException} may be thrown, which
    636 	 *            contains the details returned by the proxy. If the proxy is buggy and does
    637 	 *            not return a proper HTTP response, then a normal IOException is thrown instead.
    638 	 */
    639 	public synchronized ConnectionInfo connect(ServerHostKeyVerifier verifier, int connectTimeout, int kexTimeout)
    640 			throws IOException
    641 	{
    642 		final class TimeoutState
    643 		{
    644 			boolean isCancelled = false;
    645 			boolean timeoutSocketClosed = false;
    646 		}
    647 
    648 		if (tm != null)
    649 			throw new IOException("Connection to " + hostname + " is already in connected state!");
    650 
    651 		if (connectTimeout < 0)
    652 			throw new IllegalArgumentException("connectTimeout must be non-negative!");
    653 
    654 		if (kexTimeout < 0)
    655 			throw new IllegalArgumentException("kexTimeout must be non-negative!");
    656 
    657 		final TimeoutState state = new TimeoutState();
    658 
    659 		tm = new TransportManager(hostname, port);
    660         tm.setSoTimeout(connectTimeout);
    661 		tm.setConnectionMonitors(connectionMonitors);
    662 
    663 		/* Make sure that the runnable below will observe the new value of "tm"
    664 		 * and "state" (the runnable will be executed in a different thread, which
    665 		 * may be already running, that is why we need a memory barrier here).
    666 		 * See also the comment in Channel.java if you
    667 		 * are interested in the details.
    668 		 *
    669 		 * OKOK, this is paranoid since adding the runnable to the todo list
    670 		 * of the TimeoutService will ensure that all writes have been flushed
    671 		 * before the Runnable reads anything
    672 		 * (there is a synchronized block in TimeoutService.addTimeoutHandler).
    673 		 */
    674 
    675 		synchronized (tm)
    676 		{
    677 			/* We could actually synchronize on anything. */
    678 		}
    679 
    680 		try
    681 		{
    682 			TimeoutToken token = null;
    683 
    684 			if (kexTimeout > 0)
    685 			{
    686 				final Runnable timeoutHandler = new Runnable()
    687 				{
    688 					public void run()
    689 					{
    690 						synchronized (state)
    691 						{
    692 							if (state.isCancelled)
    693 								return;
    694 							state.timeoutSocketClosed = true;
    695 							tm.close(new SocketTimeoutException("The connect timeout expired"), false);
    696 						}
    697 					}
    698 				};
    699 
    700 				long timeoutHorizont = System.currentTimeMillis() + kexTimeout;
    701 
    702 				token = TimeoutService.addTimeoutHandler(timeoutHorizont, timeoutHandler);
    703 			}
    704 
    705 			try
    706 			{
    707 				tm.initialize(identification, cryptoWishList, verifier, dhgexpara, connectTimeout,
    708                         getOrCreateSecureRND(), proxyData);
    709 			}
    710 			catch (SocketTimeoutException se)
    711 			{
    712 				throw (SocketTimeoutException) new SocketTimeoutException(
    713 						"The connect() operation on the socket timed out.").initCause(se);
    714 			}
    715 
    716 			tm.setTcpNoDelay(tcpNoDelay);
    717 
    718 			/* Wait until first KEX has finished */
    719 
    720 			ConnectionInfo ci = tm.getConnectionInfo(1);
    721 
    722 			/* Now try to cancel the timeout, if needed */
    723 
    724 			if (token != null)
    725 			{
    726 				TimeoutService.cancelTimeoutHandler(token);
    727 
    728 				/* Were we too late? */
    729 
    730 				synchronized (state)
    731 				{
    732 					if (state.timeoutSocketClosed)
    733 						throw new IOException("This exception will be replaced by the one below =)");
    734 					/* Just in case the "cancelTimeoutHandler" invocation came just a little bit
    735 					 * too late but the handler did not enter the semaphore yet - we can
    736 					 * still stop it.
    737 					 */
    738 					state.isCancelled = true;
    739 				}
    740 			}
    741 
    742 			return ci;
    743 		}
    744 		catch (SocketTimeoutException ste)
    745 		{
    746 			throw ste;
    747 		}
    748 		catch (IOException e1)
    749 		{
    750 			/* This will also invoke any registered connection monitors */
    751 			close(new Throwable("There was a problem during connect."), false);
    752 
    753 			synchronized (state)
    754 			{
    755 				/* Show a clean exception, not something like "the socket is closed!?!" */
    756 				if (state.timeoutSocketClosed)
    757 					throw new SocketTimeoutException("The kexTimeout (" + kexTimeout + " ms) expired.");
    758 			}
    759 
    760 			/* Do not wrap a HTTPProxyException */
    761 			if (e1 instanceof HTTPProxyException)
    762 				throw e1;
    763 
    764 			throw (IOException) new IOException("There was a problem while connecting to " + hostname + ":" + port)
    765 					.initCause(e1);
    766 		}
    767 	}
    768 
    769 	/**
    770 	 * Creates a new {@link LocalPortForwarder}.
    771 	 * A <code>LocalPortForwarder</code> forwards TCP/IP connections that arrive at a local
    772 	 * port via the secure tunnel to another host (which may or may not be
    773 	 * identical to the remote SSH-2 server).
    774 	 * <p>
    775 	 * This method must only be called after one has passed successfully the authentication step.
    776 	 * There is no limit on the number of concurrent forwardings.
    777 	 *
    778 	 * @param local_port the local port the LocalPortForwarder shall bind to.
    779 	 * @param host_to_connect target address (IP or hostname)
    780 	 * @param port_to_connect target port
    781 	 * @return A {@link LocalPortForwarder} object.
    782 	 * @throws IOException
    783 	 */
    784 	public synchronized LocalPortForwarder createLocalPortForwarder(int local_port, String host_to_connect,
    785 			int port_to_connect) throws IOException
    786 	{
    787 		if (tm == null)
    788 			throw new IllegalStateException("Cannot forward ports, you need to establish a connection first.");
    789 
    790 		if (!authenticated)
    791 			throw new IllegalStateException("Cannot forward ports, connection is not authenticated.");
    792 
    793 		return new LocalPortForwarder(cm, local_port, host_to_connect, port_to_connect);
    794 	}
    795 
    796 	/**
    797 	 * Creates a new {@link LocalPortForwarder}.
    798 	 * A <code>LocalPortForwarder</code> forwards TCP/IP connections that arrive at a local
    799 	 * port via the secure tunnel to another host (which may or may not be
    800 	 * identical to the remote SSH-2 server).
    801 	 * <p>
    802 	 * This method must only be called after one has passed successfully the authentication step.
    803 	 * There is no limit on the number of concurrent forwardings.
    804 	 *
    805 	 * @param addr specifies the InetSocketAddress where the local socket shall be bound to.
    806 	 * @param host_to_connect target address (IP or hostname)
    807 	 * @param port_to_connect target port
    808 	 * @return A {@link LocalPortForwarder} object.
    809 	 * @throws IOException
    810 	 */
    811 	public synchronized LocalPortForwarder createLocalPortForwarder(InetSocketAddress addr, String host_to_connect,
    812 			int port_to_connect) throws IOException
    813 	{
    814 		if (tm == null)
    815 			throw new IllegalStateException("Cannot forward ports, you need to establish a connection first.");
    816 
    817 		if (!authenticated)
    818 			throw new IllegalStateException("Cannot forward ports, connection is not authenticated.");
    819 
    820 		return new LocalPortForwarder(cm, addr, host_to_connect, port_to_connect);
    821 	}
    822 
    823 	/**
    824 	 * Creates a new {@link LocalStreamForwarder}.
    825 	 * A <code>LocalStreamForwarder</code> manages an Input/Outputstream pair
    826 	 * that is being forwarded via the secure tunnel into a TCP/IP connection to another host
    827 	 * (which may or may not be identical to the remote SSH-2 server).
    828 	 *
    829 	 * @param host_to_connect
    830 	 * @param port_to_connect
    831 	 * @return A {@link LocalStreamForwarder} object.
    832 	 * @throws IOException
    833 	 */
    834 	public synchronized LocalStreamForwarder createLocalStreamForwarder(String host_to_connect, int port_to_connect)
    835 			throws IOException
    836 	{
    837 		if (tm == null)
    838 			throw new IllegalStateException("Cannot forward, you need to establish a connection first.");
    839 
    840 		if (!authenticated)
    841 			throw new IllegalStateException("Cannot forward, connection is not authenticated.");
    842 
    843 		return new LocalStreamForwarder(cm, host_to_connect, port_to_connect);
    844 	}
    845 
    846 	/**
    847 	 * Create a very basic {@link SCPClient} that can be used to copy
    848 	 * files from/to the SSH-2 server.
    849 	 * <p>
    850 	 * Works only after one has passed successfully the authentication step.
    851 	 * There is no limit on the number of concurrent SCP clients.
    852 	 * <p>
    853 	 * Note: This factory method will probably disappear in the future.
    854 	 *
    855 	 * @return A {@link SCPClient} object.
    856 	 * @throws IOException
    857 	 */
    858 	public synchronized SCPClient createSCPClient() throws IOException
    859 	{
    860 		if (tm == null)
    861 			throw new IllegalStateException("Cannot create SCP client, you need to establish a connection first.");
    862 
    863 		if (!authenticated)
    864 			throw new IllegalStateException("Cannot create SCP client, connection is not authenticated.");
    865 
    866 		return new SCPClient(this);
    867 	}
    868 
    869 	/**
    870 	 * Force an asynchronous key re-exchange (the call does not block). The
    871 	 * latest values set for MAC, Cipher and DH group exchange parameters will
    872 	 * be used. If a key exchange is currently in progress, then this method has
    873 	 * the only effect that the so far specified parameters will be used for the
    874 	 * next (server driven) key exchange.
    875 	 * <p>
    876 	 * Note: This implementation will never start a key exchange (other than the initial one)
    877 	 * unless you or the SSH-2 server ask for it.
    878 	 *
    879 	 * @throws IOException
    880 	 *             In case of any failure behind the scenes.
    881 	 */
    882 	public synchronized void forceKeyExchange() throws IOException
    883 	{
    884 		if (tm == null)
    885 			throw new IllegalStateException("You need to establish a connection first.");
    886 
    887 		tm.forceKeyExchange(cryptoWishList, dhgexpara);
    888 	}
    889 
    890 	/**
    891 	 * Returns the hostname that was passed to the constructor.
    892 	 *
    893 	 * @return the hostname
    894 	 */
    895 	public synchronized String getHostname()
    896 	{
    897 		return hostname;
    898 	}
    899 
    900 	/**
    901 	 * Returns the port that was passed to the constructor.
    902 	 *
    903 	 * @return the TCP port
    904 	 */
    905 	public synchronized int getPort()
    906 	{
    907 		return port;
    908 	}
    909 
    910 	/**
    911 	 * Returns a {@link ConnectionInfo} object containing the details of
    912 	 * the connection. Can be called as soon as the connection has been
    913 	 * established (successfully connected).
    914 	 *
    915 	 * @return A {@link ConnectionInfo} object.
    916 	 * @throws IOException
    917 	 *             In case of any failure behind the scenes.
    918 	 */
    919 	public synchronized ConnectionInfo getConnectionInfo() throws IOException
    920 	{
    921 		if (tm == null)
    922 			throw new IllegalStateException(
    923 					"Cannot get details of connection, you need to establish a connection first.");
    924 		return tm.getConnectionInfo(1);
    925 	}
    926 
    927 	/**
    928 	 * After a successful connect, one has to authenticate oneself. This method
    929 	 * can be used to tell which authentication methods are supported by the
    930 	 * server at a certain stage of the authentication process (for the given
    931 	 * username).
    932 	 * <p>
    933 	 * Note 1: the username will only be used if no authentication step was done
    934 	 * so far (it will be used to ask the server for a list of possible
    935 	 * authentication methods by sending the initial "none" request). Otherwise,
    936 	 * this method ignores the user name and returns a cached method list
    937 	 * (which is based on the information contained in the last negative server response).
    938 	 * <p>
    939 	 * Note 2: the server may return method names that are not supported by this
    940 	 * implementation.
    941 	 * <p>
    942 	 * After a successful authentication, this method must not be called
    943 	 * anymore.
    944 	 *
    945 	 * @param user
    946 	 *            A <code>String</code> holding the username.
    947 	 *
    948 	 * @return a (possibly emtpy) array holding authentication method names.
    949 	 * @throws IOException
    950 	 */
    951 	public synchronized String[] getRemainingAuthMethods(String user) throws IOException
    952 	{
    953 		if (user == null)
    954 			throw new IllegalArgumentException("user argument may not be NULL!");
    955 
    956 		if (tm == null)
    957 			throw new IllegalStateException("Connection is not established!");
    958 
    959 		if (authenticated)
    960 			throw new IllegalStateException("Connection is already authenticated!");
    961 
    962 		if (am == null)
    963 			am = new AuthenticationManager(tm);
    964 
    965 		if (cm == null)
    966 			cm = new ChannelManager(tm);
    967 
    968 		return am.getRemainingMethods(user);
    969 	}
    970 
    971 	/**
    972 	 * Determines if the authentication phase is complete. Can be called at any
    973 	 * time.
    974 	 *
    975 	 * @return <code>true</code> if no further authentication steps are
    976 	 *         needed.
    977 	 */
    978 	public synchronized boolean isAuthenticationComplete()
    979 	{
    980 		return authenticated;
    981 	}
    982 
    983 	/**
    984 	 * Returns true if there was at least one failed authentication request and
    985 	 * the last failed authentication request was marked with "partial success"
    986 	 * by the server. This is only needed in the rare case of SSH-2 server setups
    987 	 * that cannot be satisfied with a single successful authentication request
    988 	 * (i.e., multiple authentication steps are needed.)
    989 	 * <p>
    990 	 * If you are interested in the details, then have a look at RFC4252.
    991 	 *
    992 	 * @return if the there was a failed authentication step and the last one
    993 	 *         was marked as a "partial success".
    994 	 */
    995 	public synchronized boolean isAuthenticationPartialSuccess()
    996 	{
    997 		if (am == null)
    998 			return false;
    999 
   1000 		return am.getPartialSuccess();
   1001 	}
   1002 
   1003 	/**
   1004 	 * Checks if a specified authentication method is available. This method is
   1005 	 * actually just a wrapper for {@link #getRemainingAuthMethods(String)
   1006 	 * getRemainingAuthMethods()}.
   1007 	 *
   1008 	 * @param user
   1009 	 *            A <code>String</code> holding the username.
   1010 	 * @param method
   1011 	 *            An authentication method name (e.g., "publickey", "password",
   1012 	 *            "keyboard-interactive") as specified by the SSH-2 standard.
   1013 	 * @return if the specified authentication method is currently available.
   1014 	 * @throws IOException
   1015 	 */
   1016 	public synchronized boolean isAuthMethodAvailable(String user, String method) throws IOException
   1017 	{
   1018 		if (method == null)
   1019 			throw new IllegalArgumentException("method argument may not be NULL!");
   1020 
   1021 		String methods[] = getRemainingAuthMethods(user);
   1022 
   1023 		for (int i = 0; i < methods.length; i++)
   1024 		{
   1025 			if (methods[i].compareTo(method) == 0)
   1026 				return true;
   1027 		}
   1028 
   1029 		return false;
   1030 	}
   1031 
   1032 	private SecureRandom getOrCreateSecureRND()
   1033 	{
   1034 		if (generator == null)
   1035 			generator = new SecureRandom();
   1036 
   1037 		return generator;
   1038 	}
   1039 
   1040 	/**
   1041 	 * Open a new {@link Session} on this connection. Works only after one has passed
   1042 	 * successfully the authentication step. There is no limit on the number of
   1043 	 * concurrent sessions.
   1044 	 *
   1045 	 * @return A {@link Session} object.
   1046 	 * @throws IOException
   1047 	 */
   1048 	public synchronized Session openSession() throws IOException
   1049 	{
   1050 		if (tm == null)
   1051 			throw new IllegalStateException("Cannot open session, you need to establish a connection first.");
   1052 
   1053 		if (!authenticated)
   1054 			throw new IllegalStateException("Cannot open session, connection is not authenticated.");
   1055 
   1056 		return new Session(cm, getOrCreateSecureRND());
   1057 	}
   1058 
   1059 	/**
   1060 	 * Send an SSH_MSG_IGNORE packet. This method will generate a random data attribute
   1061 	 * (length between 0 (invlusive) and 16 (exclusive) bytes, contents are random bytes).
   1062 	 * <p>
   1063 	 * This method must only be called once the connection is established.
   1064 	 *
   1065 	 * @throws IOException
   1066 	 */
   1067 	public synchronized void sendIgnorePacket() throws IOException
   1068 	{
   1069 		SecureRandom rnd = getOrCreateSecureRND();
   1070 
   1071 		byte[] data = new byte[rnd.nextInt(16)];
   1072 		rnd.nextBytes(data);
   1073 
   1074 		sendIgnorePacket(data);
   1075 	}
   1076 
   1077 	/**
   1078 	 * Send an SSH_MSG_IGNORE packet with the given data attribute.
   1079 	 * <p>
   1080 	 * This method must only be called once the connection is established.
   1081 	 *
   1082 	 * @throws IOException
   1083 	 */
   1084 	public synchronized void sendIgnorePacket(byte[] data) throws IOException
   1085 	{
   1086 		if (data == null)
   1087 			throw new IllegalArgumentException("data argument must not be null.");
   1088 
   1089 		if (tm == null)
   1090 			throw new IllegalStateException(
   1091 					"Cannot send SSH_MSG_IGNORE packet, you need to establish a connection first.");
   1092 
   1093 		PacketIgnore pi = new PacketIgnore();
   1094 		pi.setData(data);
   1095 
   1096 		tm.sendMessage(pi.getPayload());
   1097 	}
   1098 
   1099 	/**
   1100 	 * Removes duplicates from a String array, keeps only first occurence
   1101 	 * of each element. Does not destroy order of elements; can handle nulls.
   1102 	 * Uses a very efficient O(N^2) algorithm =)
   1103 	 *
   1104 	 * @param list a String array.
   1105 	 * @return a cleaned String array.
   1106 	 */
   1107 	private String[] removeDuplicates(String[] list)
   1108 	{
   1109 		if ((list == null) || (list.length < 2))
   1110 			return list;
   1111 
   1112 		String[] list2 = new String[list.length];
   1113 
   1114 		int count = 0;
   1115 
   1116 		for (int i = 0; i < list.length; i++)
   1117 		{
   1118 			boolean duplicate = false;
   1119 
   1120 			String element = list[i];
   1121 
   1122 			for (int j = 0; j < count; j++)
   1123 			{
   1124 				if (((element == null) && (list2[j] == null)) || ((element != null) && (element.equals(list2[j]))))
   1125 				{
   1126 					duplicate = true;
   1127 					break;
   1128 				}
   1129 			}
   1130 
   1131 			if (duplicate)
   1132 				continue;
   1133 
   1134 			list2[count++] = list[i];
   1135 		}
   1136 
   1137 		if (count == list2.length)
   1138 			return list2;
   1139 
   1140 		String[] tmp = new String[count];
   1141 		System.arraycopy(list2, 0, tmp, 0, count);
   1142 
   1143 		return tmp;
   1144 	}
   1145 
   1146 	/**
   1147 	 * Unless you know what you are doing, you will never need this.
   1148 	 *
   1149 	 * @param ciphers
   1150 	 */
   1151 	public synchronized void setClient2ServerCiphers(String[] ciphers)
   1152 	{
   1153 		if ((ciphers == null) || (ciphers.length == 0))
   1154 			throw new IllegalArgumentException();
   1155 		ciphers = removeDuplicates(ciphers);
   1156 		BlockCipherFactory.checkCipherList(ciphers);
   1157 		cryptoWishList.c2s_enc_algos = ciphers;
   1158 	}
   1159 
   1160 	/**
   1161 	 * Unless you know what you are doing, you will never need this.
   1162 	 *
   1163 	 * @param macs
   1164 	 */
   1165 	public synchronized void setClient2ServerMACs(String[] macs)
   1166 	{
   1167 		if ((macs == null) || (macs.length == 0))
   1168 			throw new IllegalArgumentException();
   1169 		macs = removeDuplicates(macs);
   1170 		MAC.checkMacList(macs);
   1171 		cryptoWishList.c2s_mac_algos = macs;
   1172 	}
   1173 
   1174 	/**
   1175 	 * Sets the parameters for the diffie-hellman group exchange. Unless you
   1176 	 * know what you are doing, you will never need this. Default values are
   1177 	 * defined in the {@link DHGexParameters} class.
   1178 	 *
   1179 	 * @param dgp {@link DHGexParameters}, non null.
   1180 	 *
   1181 	 */
   1182 	public synchronized void setDHGexParameters(DHGexParameters dgp)
   1183 	{
   1184 		if (dgp == null)
   1185 			throw new IllegalArgumentException();
   1186 
   1187 		dhgexpara = dgp;
   1188 	}
   1189 
   1190 	/**
   1191 	 * Unless you know what you are doing, you will never need this.
   1192 	 *
   1193 	 * @param ciphers
   1194 	 */
   1195 	public synchronized void setServer2ClientCiphers(String[] ciphers)
   1196 	{
   1197 		if ((ciphers == null) || (ciphers.length == 0))
   1198 			throw new IllegalArgumentException();
   1199 		ciphers = removeDuplicates(ciphers);
   1200 		BlockCipherFactory.checkCipherList(ciphers);
   1201 		cryptoWishList.s2c_enc_algos = ciphers;
   1202 	}
   1203 
   1204 	/**
   1205 	 * Unless you know what you are doing, you will never need this.
   1206 	 *
   1207 	 * @param macs
   1208 	 */
   1209 	public synchronized void setServer2ClientMACs(String[] macs)
   1210 	{
   1211 		if ((macs == null) || (macs.length == 0))
   1212 			throw new IllegalArgumentException();
   1213 
   1214 		macs = removeDuplicates(macs);
   1215 		MAC.checkMacList(macs);
   1216 		cryptoWishList.s2c_mac_algos = macs;
   1217 	}
   1218 
   1219 	/**
   1220 	 * Define the set of allowed server host key algorithms to be used for
   1221 	 * the following key exchange operations.
   1222 	 * <p>
   1223 	 * Unless you know what you are doing, you will never need this.
   1224 	 *
   1225 	 * @param algos An array of allowed server host key algorithms.
   1226 	 * 	SSH-2 defines <code>ssh-dss</code> and <code>ssh-rsa</code>.
   1227 	 * 	The entries of the array must be ordered after preference, i.e.,
   1228 	 *  the entry at index 0 is the most preferred one. You must specify
   1229 	 *  at least one entry.
   1230 	 */
   1231 	public synchronized void setServerHostKeyAlgorithms(String[] algos)
   1232 	{
   1233 		if ((algos == null) || (algos.length == 0))
   1234 			throw new IllegalArgumentException();
   1235 
   1236 		algos = removeDuplicates(algos);
   1237 		KexManager.checkServerHostkeyAlgorithmsList(algos);
   1238 		cryptoWishList.serverHostKeyAlgorithms = algos;
   1239 	}
   1240 
   1241 	/**
   1242 	 * Enable/disable TCP_NODELAY (disable/enable Nagle's algorithm) on the underlying socket.
   1243 	 * <p>
   1244 	 * Can be called at any time. If the connection has not yet been established
   1245 	 * then the passed value will be stored and set after the socket has been set up.
   1246 	 * The default value that will be used is <code>false</code>.
   1247 	 *
   1248 	 * @param enable the argument passed to the <code>Socket.setTCPNoDelay()</code> method.
   1249 	 * @throws IOException
   1250 	 */
   1251 	public synchronized void setTCPNoDelay(boolean enable) throws IOException
   1252 	{
   1253 		tcpNoDelay = enable;
   1254 
   1255 		if (tm != null)
   1256 			tm.setTcpNoDelay(enable);
   1257 	}
   1258 
   1259 	/**
   1260 	 * Used to tell the library that the connection shall be established through a proxy server.
   1261 	 * It only makes sense to call this method before calling the {@link #connect() connect()}
   1262 	 * method.
   1263 	 * <p>
   1264 	 * At the moment, only HTTP proxies are supported.
   1265 	 * <p>
   1266 	 * Note: This method can be called any number of times. The {@link #connect() connect()}
   1267 	 * method will use the value set in the last preceding invocation of this method.
   1268 	 *
   1269 	 * @see HTTPProxyData
   1270 	 *
   1271 	 * @param proxyData Connection information about the proxy. If <code>null</code>, then
   1272 	 *                  no proxy will be used (non surprisingly, this is also the default).
   1273 	 */
   1274 	public synchronized void setProxyData(ProxyData proxyData)
   1275 	{
   1276 		this.proxyData = proxyData;
   1277 	}
   1278 
   1279 	/**
   1280 	 * Request a remote port forwarding.
   1281 	 * If successful, then forwarded connections will be redirected to the given target address.
   1282 	 * You can cancle a requested remote port forwarding by calling
   1283 	 * {@link #cancelRemotePortForwarding(int) cancelRemotePortForwarding()}.
   1284 	 * <p>
   1285 	 * A call of this method will block until the peer either agreed or disagreed to your request-
   1286 	 * <p>
   1287 	 * Note 1: this method typically fails if you
   1288 	 * <ul>
   1289 	 * <li>pass a port number for which the used remote user has not enough permissions (i.e., port
   1290 	 * &lt; 1024)</li>
   1291 	 * <li>or pass a port number that is already in use on the remote server</li>
   1292 	 * <li>or if remote port forwarding is disabled on the server.</li>
   1293 	 * </ul>
   1294 	 * <p>
   1295 	 * Note 2: (from the openssh man page): By default, the listening socket on the server will be
   1296 	 * bound to the loopback interface only. This may be overriden by specifying a bind address.
   1297 	 * Specifying a remote bind address will only succeed if the server's <b>GatewayPorts</b> option
   1298 	 * is enabled (see sshd_config(5)).
   1299 	 *
   1300 	 * @param bindAddress address to bind to on the server:
   1301 	 *                    <ul>
   1302 	 *                    <li>"" means that connections are to be accepted on all protocol families
   1303 	 *                    supported by the SSH implementation</li>
   1304 	 *                    <li>"0.0.0.0" means to listen on all IPv4 addresses</li>
   1305 	 *                    <li>"::" means to listen on all IPv6 addresses</li>
   1306 	 *                    <li>"localhost" means to listen on all protocol families supported by the SSH
   1307 	 *                    implementation on loopback addresses only, [RFC3330] and RFC3513]</li>
   1308 	 *                    <li>"127.0.0.1" and "::1" indicate listening on the loopback interfaces for
   1309 	 *                    IPv4 and IPv6 respectively</li>
   1310 	 *                    </ul>
   1311 	 * @param bindPort port number to bind on the server (must be &gt; 0)
   1312 	 * @param targetAddress the target address (IP or hostname)
   1313 	 * @param targetPort the target port
   1314 	 * @throws IOException
   1315 	 */
   1316 	public synchronized void requestRemotePortForwarding(String bindAddress, int bindPort, String targetAddress,
   1317 			int targetPort) throws IOException
   1318 	{
   1319 		if (tm == null)
   1320 			throw new IllegalStateException("You need to establish a connection first.");
   1321 
   1322 		if (!authenticated)
   1323 			throw new IllegalStateException("The connection is not authenticated.");
   1324 
   1325 		if ((bindAddress == null) || (targetAddress == null) || (bindPort <= 0) || (targetPort <= 0))
   1326 			throw new IllegalArgumentException();
   1327 
   1328 		cm.requestGlobalForward(bindAddress, bindPort, targetAddress, targetPort);
   1329 	}
   1330 
   1331 	/**
   1332 	 * Cancel an earlier requested remote port forwarding.
   1333 	 * Currently active forwardings will not be affected (e.g., disrupted).
   1334 	 * Note that further connection forwarding requests may be received until
   1335 	 * this method has returned.
   1336 	 *
   1337 	 * @param bindPort the allocated port number on the server
   1338 	 * @throws IOException if the remote side refuses the cancel request or another low
   1339 	 *         level error occurs (e.g., the underlying connection is closed)
   1340 	 */
   1341 	public synchronized void cancelRemotePortForwarding(int bindPort) throws IOException
   1342 	{
   1343 		if (tm == null)
   1344 			throw new IllegalStateException("You need to establish a connection first.");
   1345 
   1346 		if (!authenticated)
   1347 			throw new IllegalStateException("The connection is not authenticated.");
   1348 
   1349 		cm.requestCancelGlobalForward(bindPort);
   1350 	}
   1351 
   1352 	/**
   1353 	 * Provide your own instance of SecureRandom. Can be used, e.g., if you
   1354 	 * want to seed the used SecureRandom generator manually.
   1355 	 * <p>
   1356 	 * The SecureRandom instance is used during key exchanges, public key authentication,
   1357 	 * x11 cookie generation and the like.
   1358 	 *
   1359 	 * @param rnd a SecureRandom instance
   1360 	 */
   1361 	public synchronized void setSecureRandom(SecureRandom rnd)
   1362 	{
   1363 		if (rnd == null)
   1364 			throw new IllegalArgumentException();
   1365 
   1366 		this.generator = rnd;
   1367 	}
   1368 }
   1369