From c1e41c03ad352b00e88a926db600937f2ab06e50 Mon Sep 17 00:00:00 2001 From: Kenny Root Date: Tue, 26 Aug 2008 05:10:04 +0000 Subject: Update Trilead SSH-2 for Java from build 211 to build 213 --- src/com/trilead/ssh2/Connection.java | 624 +++++++++++++++++++++-------------- 1 file changed, 383 insertions(+), 241 deletions(-) (limited to 'src/com/trilead/ssh2/Connection.java') diff --git a/src/com/trilead/ssh2/Connection.java b/src/com/trilead/ssh2/Connection.java index acc8395..38b96c5 100644 --- a/src/com/trilead/ssh2/Connection.java +++ b/src/com/trilead/ssh2/Connection.java @@ -15,6 +15,7 @@ import com.trilead.ssh2.channel.ChannelManager; import com.trilead.ssh2.crypto.CryptoWishList; import com.trilead.ssh2.crypto.cipher.BlockCipherFactory; import com.trilead.ssh2.crypto.digest.MAC; +import com.trilead.ssh2.log.Logger; import com.trilead.ssh2.packets.PacketIgnore; import com.trilead.ssh2.transport.KexManager; import com.trilead.ssh2.transport.TransportManager; @@ -29,13 +30,16 @@ import com.trilead.ssh2.util.TimeoutService.TimeoutToken; *
    *
  1. creates a {@link #Connection(String) Connection} object.
  2. *
  3. calls the {@link #connect() connect()} method.
  4. - *
  5. calls some of the authentication methods (e.g., {@link #authenticateWithPublicKey(String, File, String) authenticateWithPublicKey()}).
  6. - *
  7. calls one or several times the {@link #openSession() openSession()} method.
  8. - *
  9. finally, one must close the connection and release resources with the {@link #close() close()} method.
  10. + *
  11. calls some of the authentication methods (e.g., + * {@link #authenticateWithPublicKey(String, File, String) authenticateWithPublicKey()}).
  12. + *
  13. calls one or several times the {@link #openSession() openSession()} + * method.
  14. + *
  15. finally, one must close the connection and release resources with the + * {@link #close() close()} method.
  16. *
* * @author Christian Plattner, plattner@trilead.com - * @version $Id: Connection.java,v 1.1 2007/10/15 12:49:56 cplattne Exp $ + * @version $Id: Connection.java,v 1.3 2008/04/01 12:38:09 cplattne Exp $ */ public class Connection @@ -43,12 +47,12 @@ public class Connection /** * The identifier presented to the SSH-2 server. */ - public final static String identification = "TrileadSSH2Java_211"; + public final static String identification = "TrileadSSH2Java_213"; - /* Will be used to generate all random data needed for the current connection. - * Note: SecureRandom.nextBytes() is thread safe. + /** + * Will be used to generate all random data needed for the current + * connection. Note: SecureRandom.nextBytes() is thread safe. */ - private SecureRandom generator; /** @@ -74,7 +78,8 @@ public class Connection /** * Unless you know what you are doing, you will never need this. * - * @return The list of supported server host key algorthims by this implementation. + * @return The list of supported server host key algorthims by this + * implementation. */ public static synchronized String[] getAvailableServerHostKeyAlgorithms() { @@ -106,9 +111,10 @@ public class Connection * Prepares a fresh Connection object which can then be used * to establish a connection to the specified SSH-2 server. *

- * Same as {@link #Connection(String, int) Connection(hostname, 22)}. + * Same as {@link #Connection(String, int) Connection(hostname, 22)}. * - * @param hostname the hostname of the SSH-2 server. + * @param hostname + * the hostname of the SSH-2 server. */ public Connection(String hostname) { @@ -156,9 +162,10 @@ public class Connection * @return whether the connection is now authenticated. * @throws IOException * - * @deprecated You should use one of the {@link #authenticateWithPublicKey(String, File, String) authenticateWithPublicKey()} - * methods, this method is just a wrapper for it and will - * disappear in future builds. + * @deprecated You should use one of the + * {@link #authenticateWithPublicKey(String, File, String) authenticateWithPublicKey()} + * methods, this method is just a wrapper for it and will + * disappear in future builds. * */ public synchronized boolean authenticateWithDSA(String user, String pem, String password) throws IOException @@ -187,8 +194,10 @@ public class Connection } /** - * A wrapper that calls {@link #authenticateWithKeyboardInteractive(String, String[], InteractiveCallback) - * authenticateWithKeyboardInteractivewith} a null submethod list. + * A wrapper that calls + * {@link #authenticateWithKeyboardInteractive(String, String[], InteractiveCallback) + * authenticateWithKeyboardInteractivewith} a null submethod + * list. * * @param user * A String holding the username. @@ -276,12 +285,14 @@ public class Connection * the remaining possible methods). *

* Note: if this method fails, then please double-check that it is actually - * offered by the server (use {@link #getRemainingAuthMethods(String) getRemainingAuthMethods()}. + * offered by the server (use + * {@link #getRemainingAuthMethods(String) getRemainingAuthMethods()}. *

- * Often, password authentication is disabled, but users are not aware of it. - * Many servers only offer "publickey" and "keyboard-interactive". However, - * even though "keyboard-interactive" *feels* like password authentication - * (e.g., when using the putty or openssh clients) it is *not* the same mechanism. + * Often, password authentication is disabled, but users are not aware of + * it. Many servers only offer "publickey" and "keyboard-interactive". + * However, even though "keyboard-interactive" *feels* like password + * authentication (e.g., when using the putty or openssh clients) it is + * *not* the same mechanism. * * @param user * @param password @@ -314,26 +325,26 @@ public class Connection } /** - * After a successful connect, one has to authenticate oneself. - * This method can be used to explicitly use the special "none" - * authentication method (where only a username has to be specified). + * After a successful connect, one has to authenticate oneself. This method + * can be used to explicitly use the special "none" authentication method + * (where only a username has to be specified). *

* Note 1: The "none" method may always be tried by clients, however as by * the specs, the server will not explicitly announce it. In other words, * the "none" token will never show up in the list returned by * {@link #getRemainingAuthMethods(String)}. *

- * Note 2: no matter which one of the authenticateWithXXX() methods - * you call, the library will always issue exactly one initial "none" + * Note 2: no matter which one of the authenticateWithXXX() methods you + * call, the library will always issue exactly one initial "none" * authentication request to retrieve the initially allowed list of * authentication methods by the server. Please read RFC 4252 for the * details. *

* If the authentication phase is complete, true will be * returned. If further authentication steps are needed, false - * is returned and one can retry by any other authentication method - * (use the getRemainingAuthMethods method to get a list of - * the remaining possible methods). + * is returned and one can retry by any other authentication method (use the + * getRemainingAuthMethods method to get a list of the + * remaining possible methods). * * @param user * @return if the connection is now authenticated. @@ -357,7 +368,7 @@ public class Connection throw new IllegalArgumentException("user argument is null"); /* Trigger the sending of the PacketUserauthRequestNone packet */ - /* (if not already done) */ + /* (if not already done) */ authenticated = am.authenticateNone(user); @@ -365,18 +376,19 @@ public class Connection } /** - * After a successful connect, one has to authenticate oneself. - * The authentication method "publickey" works by signing a challenge - * sent by the server. The signature is either DSA or RSA based - it - * just depends on the type of private key you specify, either a DSA - * or RSA private key in PEM format. And yes, this is may seem to be a - * little confusing, the method is called "publickey" in the SSH-2 protocol - * specification, however since we need to generate a signature, you - * actually have to supply a private key =). + * After a successful connect, one has to authenticate oneself. The + * authentication method "publickey" works by signing a challenge sent by + * the server. The signature is either DSA or RSA based - it just depends on + * the type of private key you specify, either a DSA or RSA private key in + * PEM format. And yes, this is may seem to be a little confusing, the + * method is called "publickey" in the SSH-2 protocol specification, however + * since we need to generate a signature, you actually have to supply a + * private key =). *

- * The private key contained in the PEM file may also be encrypted ("Proc-Type: 4,ENCRYPTED"). - * The library supports DES-CBC and DES-EDE3-CBC encryption, as well - * as the more exotic PEM encrpytions AES-128-CBC, AES-192-CBC and AES-256-CBC. + * The private key contained in the PEM file may also be encrypted + * ("Proc-Type: 4,ENCRYPTED"). The library supports DES-CBC and DES-EDE3-CBC + * encryption, as well as the more exotic PEM encrpytions AES-128-CBC, + * AES-192-CBC and AES-256-CBC. *

* If the authentication phase is complete, true will be * returned. If the server does not accept the request (or if further @@ -385,23 +397,24 @@ public class Connection * (use the getRemainingAuthMethods method to get a list of * the remaining possible methods). *

- * NOTE PUTTY USERS: Event though your key file may start with "-----BEGIN..." - * it is not in the expected format. You have to convert it to the OpenSSH - * key format by using the "puttygen" tool (can be downloaded from the Putty - * website). Simply load your key and then use the "Conversions/Export OpenSSH key" - * functionality to get a proper PEM file. + * NOTE PUTTY USERS: Event though your key file may start with + * "-----BEGIN..." it is not in the expected format. You have to convert it + * to the OpenSSH key format by using the "puttygen" tool (can be downloaded + * from the Putty website). Simply load your key and then use the + * "Conversions/Export OpenSSH key" functionality to get a proper PEM file. * * @param user * A String holding the username. * @param pemPrivateKey - * A char[] containing a DSA or RSA private key of the - * user in OpenSSH key format (PEM, you can't miss the - * "-----BEGIN DSA PRIVATE KEY-----" or "-----BEGIN RSA PRIVATE KEY-----" - * tag). The char array may contain linebreaks/linefeeds. + * A char[] containing a DSA or RSA private key of + * the user in OpenSSH key format (PEM, you can't miss the + * "-----BEGIN DSA PRIVATE KEY-----" or "-----BEGIN RSA PRIVATE + * KEY-----" tag). The char array may contain + * linebreaks/linefeeds. * @param password - * If the PEM structure is encrypted ("Proc-Type: 4,ENCRYPTED") then - * you must specify a password. Otherwise, this argument will be ignored - * and can be set to null. + * If the PEM structure is encrypted ("Proc-Type: 4,ENCRYPTED") + * then you must specify a password. Otherwise, this argument + * will be ignored and can be set to null. * * @return whether the connection is now authenticated. * @throws IOException @@ -433,25 +446,27 @@ public class Connection } /** - * A convenience wrapper function which reads in a private key (PEM format, either DSA or RSA) - * and then calls authenticateWithPublicKey(String, char[], String). + * A convenience wrapper function which reads in a private key (PEM format, + * either DSA or RSA) and then calls + * authenticateWithPublicKey(String, char[], String). *

- * NOTE PUTTY USERS: Event though your key file may start with "-----BEGIN..." - * it is not in the expected format. You have to convert it to the OpenSSH - * key format by using the "puttygen" tool (can be downloaded from the Putty - * website). Simply load your key and then use the "Conversions/Export OpenSSH key" - * functionality to get a proper PEM file. + * NOTE PUTTY USERS: Event though your key file may start with + * "-----BEGIN..." it is not in the expected format. You have to convert it + * to the OpenSSH key format by using the "puttygen" tool (can be downloaded + * from the Putty website). Simply load your key and then use the + * "Conversions/Export OpenSSH key" functionality to get a proper PEM file. * * @param user * A String holding the username. * @param pemFile - * A File object pointing to a file containing a DSA or RSA - * private key of the user in OpenSSH key format (PEM, you can't miss the - * "-----BEGIN DSA PRIVATE KEY-----" or "-----BEGIN RSA PRIVATE KEY-----" - * tag). + * A File object pointing to a file containing a + * DSA or RSA private key of the user in OpenSSH key format (PEM, + * you can't miss the "-----BEGIN DSA PRIVATE KEY-----" or + * "-----BEGIN RSA PRIVATE KEY-----" tag). * @param password - * If the PEM file is encrypted then you must specify the password. - * Otherwise, this argument will be ignored and can be set to null. + * If the PEM file is encrypted then you must specify the + * password. Otherwise, this argument will be ignored and can be + * set to null. * * @return whether the connection is now authenticated. * @throws IOException @@ -482,17 +497,19 @@ public class Connection } /** - * Add a {@link ConnectionMonitor} to this connection. Can be invoked at any time, - * but it is best to add connection monitors before invoking - * connect() to avoid glitches (e.g., you add a connection monitor after - * a successful connect(), but the connection has died in the mean time. Then, - * your connection monitor won't be notified.) + * Add a {@link ConnectionMonitor} to this connection. Can be invoked at any + * time, but it is best to add connection monitors before invoking + * connect() to avoid glitches (e.g., you add a connection + * monitor after a successful connect(), but the connection has died in the + * mean time. Then, your connection monitor won't be notified.) *

* You can add as many monitors as you like. * * @see ConnectionMonitor * - * @param cmon An object implementing the ConnectionMonitor interface. + * @param cmon + * An object implementing the ConnectionMonitor + * interface. */ public synchronized void addConnectionMonitor(ConnectionMonitor cmon) { @@ -533,9 +550,12 @@ public class Connection } /** - * Same as {@link #connect(ServerHostKeyVerifier, int, int) connect(null, 0, 0)}. + * Same as + * {@link #connect(ServerHostKeyVerifier, int, int) connect(null, 0, 0)}. * - * @return see comments for the {@link #connect(ServerHostKeyVerifier, int, int) connect(ServerHostKeyVerifier, int, int)} method. + * @return see comments for the + * {@link #connect(ServerHostKeyVerifier, int, int) connect(ServerHostKeyVerifier, int, int)} + * method. * @throws IOException */ public synchronized ConnectionInfo connect() throws IOException @@ -544,9 +564,12 @@ public class Connection } /** - * Same as {@link #connect(ServerHostKeyVerifier, int, int) connect(verifier, 0, 0)}. + * Same as + * {@link #connect(ServerHostKeyVerifier, int, int) connect(verifier, 0, 0)}. * - * @return see comments for the {@link #connect(ServerHostKeyVerifier, int, int) connect(ServerHostKeyVerifier, int, int)} method. + * @return see comments for the + * {@link #connect(ServerHostKeyVerifier, int, int) connect(ServerHostKeyVerifier, int, int)} + * method. * @throws IOException */ public synchronized ConnectionInfo connect(ServerHostKeyVerifier verifier) throws IOException @@ -556,74 +579,85 @@ public class Connection /** * Connect to the SSH-2 server and, as soon as the server has presented its - * host key, use the {@link ServerHostKeyVerifier#verifyServerHostKey(String, - * int, String, byte[]) ServerHostKeyVerifier.verifyServerHostKey()} - * method of the verifier to ask for permission to proceed. - * If verifier is null, then any host key will be - * accepted - this is NOT recommended, since it makes man-in-the-middle attackes - * VERY easy (somebody could put a proxy SSH server between you and the real server). + * host key, use the + * {@link ServerHostKeyVerifier#verifyServerHostKey(String, int, String, + * byte[]) ServerHostKeyVerifier.verifyServerHostKey()} method of the + * verifier to ask for permission to proceed. If + * verifier is null, then any host key will + * be accepted - this is NOT recommended, since it makes man-in-the-middle + * attackes VERY easy (somebody could put a proxy SSH server between you and + * the real server). *

* Note: The verifier will be called before doing any crypto calculations - * (i.e., diffie-hellman). Therefore, if you don't like the presented host key then - * no CPU cycles are wasted (and the evil server has less information about us). + * (i.e., diffie-hellman). Therefore, if you don't like the presented host + * key then no CPU cycles are wasted (and the evil server has less + * information about us). *

- * However, it is still possible that the server presented a fake host key: the server - * cheated (typically a sign for a man-in-the-middle attack) and is not able to generate - * a signature that matches its host key. Don't worry, the library will detect such - * a scenario later when checking the signature (the signature cannot be checked before - * having completed the diffie-hellman exchange). + * However, it is still possible that the server presented a fake host key: + * the server cheated (typically a sign for a man-in-the-middle attack) and + * is not able to generate a signature that matches its host key. Don't + * worry, the library will detect such a scenario later when checking the + * signature (the signature cannot be checked before having completed the + * diffie-hellman exchange). *

- * Note 2: The {@link ServerHostKeyVerifier#verifyServerHostKey(String, - * int, String, byte[]) ServerHostKeyVerifier.verifyServerHostKey()} method - * will *NOT* be called from the current thread, the call is being made from a + * Note 2: The {@link ServerHostKeyVerifier#verifyServerHostKey(String, int, + * String, byte[]) ServerHostKeyVerifier.verifyServerHostKey()} method will + * *NOT* be called from the current thread, the call is being made from a * background thread (there is a background dispatcher thread for every - * established connection). + * established connection). *

- * Note 3: This method will block as long as the key exchange of the underlying connection - * has not been completed (and you have not specified any timeouts). + * Note 3: This method will block as long as the key exchange of the + * underlying connection has not been completed (and you have not specified + * any timeouts). *

- * Note 4: If you want to re-use a connection object that was successfully connected, - * then you must call the {@link #close()} method before invoking connect() again. + * Note 4: If you want to re-use a connection object that was successfully + * connected, then you must call the {@link #close()} method before invoking + * connect() again. * * @param verifier - * An object that implements the - * {@link ServerHostKeyVerifier} interface. Pass null - * to accept any server host key - NOT recommended. - * + * An object that implements the {@link ServerHostKeyVerifier} + * interface. Pass null to accept any server host + * key - NOT recommended. + * * @param connectTimeout - * Connect the underlying TCP socket to the server with the given timeout - * value (non-negative, in milliseconds). Zero means no timeout. If a proxy is being - * used (see {@link #setProxyData(ProxyData)}), then this timeout is used for the - * connection establishment to the proxy. + * Connect the underlying TCP socket to the server with the given + * timeout value (non-negative, in milliseconds). Zero means no + * timeout. If a proxy is being used (see + * {@link #setProxyData(ProxyData)}), then this timeout is used + * for the connection establishment to the proxy. * * @param kexTimeout * Timeout for complete connection establishment (non-negative, - * in milliseconds). Zero means no timeout. The timeout counts from the - * moment you invoke the connect() method and is cancelled as soon as the - * first key-exchange round has finished. It is possible that - * the timeout event will be fired during the invocation of the - * verifier callback, but it will only have an effect after - * the verifier returns. - * - * @return A {@link ConnectionInfo} object containing the details of - * the established connection. - * + * in milliseconds). Zero means no timeout. The timeout counts + * from the moment you invoke the connect() method and is + * cancelled as soon as the first key-exchange round has + * finished. It is possible that the timeout event will be fired + * during the invocation of the verifier callback, + * but it will only have an effect after the + * verifier returns. + * + * @return A {@link ConnectionInfo} object containing the details of the + * established connection. + * * @throws IOException - * If any problem occurs, e.g., the server's host key is not - * accepted by the verifier or there is problem during - * the initial crypto setup (e.g., the signature sent by the server is wrong). - *

- * In case of a timeout (either connectTimeout or kexTimeout) - * a SocketTimeoutException is thrown. - *

- * An exception may also be thrown if the connection was already successfully - * connected (no matter if the connection broke in the mean time) and you invoke - * connect() again without having called {@link #close()} first. - *

- * If a HTTP proxy is being used and the proxy refuses the connection, - * then a {@link HTTPProxyException} may be thrown, which - * contains the details returned by the proxy. If the proxy is buggy and does - * not return a proper HTTP response, then a normal IOException is thrown instead. + * If any problem occurs, e.g., the server's host key is not + * accepted by the verifier or there is problem + * during the initial crypto setup (e.g., the signature sent by + * the server is wrong). + *

+ * In case of a timeout (either connectTimeout or kexTimeout) a + * SocketTimeoutException is thrown. + *

+ * An exception may also be thrown if the connection was already + * successfully connected (no matter if the connection broke in + * the mean time) and you invoke connect() again + * without having called {@link #close()} first. + *

+ * If a HTTP proxy is being used and the proxy refuses the + * connection, then a {@link HTTPProxyException} may be thrown, + * which contains the details returned by the proxy. If the + * proxy is buggy and does not return a proper HTTP response, + * then a normal IOException is thrown instead. */ public synchronized ConnectionInfo connect(ServerHostKeyVerifier verifier, int connectTimeout, int kexTimeout) throws IOException @@ -649,16 +683,17 @@ public class Connection tm.setConnectionMonitors(connectionMonitors); - /* Make sure that the runnable below will observe the new value of "tm" - * and "state" (the runnable will be executed in a different thread, which - * may be already running, that is why we need a memory barrier here). - * See also the comment in Channel.java if you - * are interested in the details. + /* + * Make sure that the runnable below will observe the new value of "tm" + * and "state" (the runnable will be executed in a different thread, + * which may be already running, that is why we need a memory barrier + * here). See also the comment in Channel.java if you are interested in + * the details. * - * OKOK, this is paranoid since adding the runnable to the todo list - * of the TimeoutService will ensure that all writes have been flushed - * before the Runnable reads anything - * (there is a synchronized block in TimeoutService.addTimeoutHandler). + * OKOK, this is paranoid since adding the runnable to the todo list of + * the TimeoutService will ensure that all writes have been flushed + * before the Runnable reads anything (there is a synchronized block in + * TimeoutService.addTimeoutHandler). */ synchronized (tm) @@ -719,9 +754,10 @@ public class Connection { if (state.timeoutSocketClosed) throw new IOException("This exception will be replaced by the one below =)"); - /* Just in case the "cancelTimeoutHandler" invocation came just a little bit - * too late but the handler did not enter the semaphore yet - we can - * still stop it. + /* + * Just in case the "cancelTimeoutHandler" invocation came + * just a little bit too late but the handler did not enter + * the semaphore yet - we can still stop it. */ state.isCancelled = true; } @@ -740,7 +776,10 @@ public class Connection synchronized (state) { - /* Show a clean exception, not something like "the socket is closed!?!" */ + /* + * Show a clean exception, not something like "the socket is + * closed!?!" + */ if (state.timeoutSocketClosed) throw new SocketTimeoutException("The kexTimeout (" + kexTimeout + " ms) expired."); } @@ -755,17 +794,21 @@ public class Connection } /** - * Creates a new {@link LocalPortForwarder}. - * A LocalPortForwarder forwards TCP/IP connections that arrive at a local - * port via the secure tunnel to another host (which may or may not be - * identical to the remote SSH-2 server). + * Creates a new {@link LocalPortForwarder}. A + * LocalPortForwarder forwards TCP/IP connections that arrive + * at a local port via the secure tunnel to another host (which may or may + * not be identical to the remote SSH-2 server). *

- * This method must only be called after one has passed successfully the authentication step. - * There is no limit on the number of concurrent forwardings. + * This method must only be called after one has passed successfully the + * authentication step. There is no limit on the number of concurrent + * forwardings. * - * @param local_port the local port the LocalPortForwarder shall bind to. - * @param host_to_connect target address (IP or hostname) - * @param port_to_connect target port + * @param local_port + * the local port the LocalPortForwarder shall bind to. + * @param host_to_connect + * target address (IP or hostname) + * @param port_to_connect + * target port * @return A {@link LocalPortForwarder} object. * @throws IOException */ @@ -782,17 +825,22 @@ public class Connection } /** - * Creates a new {@link LocalPortForwarder}. - * A LocalPortForwarder forwards TCP/IP connections that arrive at a local - * port via the secure tunnel to another host (which may or may not be - * identical to the remote SSH-2 server). + * Creates a new {@link LocalPortForwarder}. A + * LocalPortForwarder forwards TCP/IP connections that arrive + * at a local port via the secure tunnel to another host (which may or may + * not be identical to the remote SSH-2 server). *

- * This method must only be called after one has passed successfully the authentication step. - * There is no limit on the number of concurrent forwardings. + * This method must only be called after one has passed successfully the + * authentication step. There is no limit on the number of concurrent + * forwardings. * - * @param addr specifies the InetSocketAddress where the local socket shall be bound to. - * @param host_to_connect target address (IP or hostname) - * @param port_to_connect target port + * @param addr + * specifies the InetSocketAddress where the local socket shall + * be bound to. + * @param host_to_connect + * target address (IP or hostname) + * @param port_to_connect + * target port * @return A {@link LocalPortForwarder} object. * @throws IOException */ @@ -809,10 +857,11 @@ public class Connection } /** - * Creates a new {@link LocalStreamForwarder}. - * A LocalStreamForwarder manages an Input/Outputstream pair - * that is being forwarded via the secure tunnel into a TCP/IP connection to another host - * (which may or may not be identical to the remote SSH-2 server). + * Creates a new {@link LocalStreamForwarder}. A + * LocalStreamForwarder manages an Input/Outputstream pair + * that is being forwarded via the secure tunnel into a TCP/IP connection to + * another host (which may or may not be identical to the remote SSH-2 + * server). * * @param host_to_connect * @param port_to_connect @@ -832,8 +881,8 @@ public class Connection } /** - * Create a very basic {@link SCPClient} that can be used to copy - * files from/to the SSH-2 server. + * Create a very basic {@link SCPClient} that can be used to copy files + * from/to the SSH-2 server. *

* Works only after one has passed successfully the authentication step. * There is no limit on the number of concurrent SCP clients. @@ -861,8 +910,8 @@ public class Connection * the only effect that the so far specified parameters will be used for the * next (server driven) key exchange. *

- * Note: This implementation will never start a key exchange (other than the initial one) - * unless you or the SSH-2 server ask for it. + * Note: This implementation will never start a key exchange (other than the + * initial one) unless you or the SSH-2 server ask for it. * * @throws IOException * In case of any failure behind the scenes. @@ -896,9 +945,9 @@ public class Connection } /** - * Returns a {@link ConnectionInfo} object containing the details of - * the connection. Can be called as soon as the connection has been - * established (successfully connected). + * Returns a {@link ConnectionInfo} object containing the details of the + * connection. Can be called as soon as the connection has been established + * (successfully connected). * * @return A {@link ConnectionInfo} object. * @throws IOException @@ -921,8 +970,9 @@ public class Connection * Note 1: the username will only be used if no authentication step was done * so far (it will be used to ask the server for a list of possible * authentication methods by sending the initial "none" request). Otherwise, - * this method ignores the user name and returns a cached method list - * (which is based on the information contained in the last negative server response). + * this method ignores the user name and returns a cached method list (which + * is based on the information contained in the last negative server + * response). *

* Note 2: the server may return method names that are not supported by this * implementation. @@ -971,9 +1021,9 @@ public class Connection /** * Returns true if there was at least one failed authentication request and * the last failed authentication request was marked with "partial success" - * by the server. This is only needed in the rare case of SSH-2 server setups - * that cannot be satisfied with a single successful authentication request - * (i.e., multiple authentication steps are needed.) + * by the server. This is only needed in the rare case of SSH-2 server + * setups that cannot be satisfied with a single successful authentication + * request (i.e., multiple authentication steps are needed.) *

* If you are interested in the details, then have a look at RFC4252. * @@ -1026,9 +1076,9 @@ public class Connection } /** - * Open a new {@link Session} on this connection. Works only after one has passed - * successfully the authentication step. There is no limit on the number of - * concurrent sessions. + * Open a new {@link Session} on this connection. Works only after one has + * passed successfully the authentication step. There is no limit on the + * number of concurrent sessions. * * @return A {@link Session} object. * @throws IOException @@ -1045,8 +1095,9 @@ public class Connection } /** - * Send an SSH_MSG_IGNORE packet. This method will generate a random data attribute - * (length between 0 (invlusive) and 16 (exclusive) bytes, contents are random bytes). + * Send an SSH_MSG_IGNORE packet. This method will generate a random data + * attribute (length between 0 (invlusive) and 16 (exclusive) bytes, + * contents are random bytes). *

* This method must only be called once the connection is established. * @@ -1085,11 +1136,12 @@ public class Connection } /** - * Removes duplicates from a String array, keeps only first occurence - * of each element. Does not destroy order of elements; can handle nulls. - * Uses a very efficient O(N^2) algorithm =) + * Removes duplicates from a String array, keeps only first occurence of + * each element. Does not destroy order of elements; can handle nulls. Uses + * a very efficient O(N^2) algorithm =) * - * @param list a String array. + * @param list + * a String array. * @return a cleaned String array. */ private String[] removeDuplicates(String[] list) @@ -1164,7 +1216,8 @@ public class Connection * know what you are doing, you will never need this. Default values are * defined in the {@link DHGexParameters} class. * - * @param dgp {@link DHGexParameters}, non null. + * @param dgp + * {@link DHGexParameters}, non null. * */ public synchronized void setDHGexParameters(DHGexParameters dgp) @@ -1205,16 +1258,17 @@ public class Connection } /** - * Define the set of allowed server host key algorithms to be used for - * the following key exchange operations. + * Define the set of allowed server host key algorithms to be used for the + * following key exchange operations. *

* Unless you know what you are doing, you will never need this. * - * @param algos An array of allowed server host key algorithms. - * SSH-2 defines ssh-dss and ssh-rsa. - * The entries of the array must be ordered after preference, i.e., - * the entry at index 0 is the most preferred one. You must specify - * at least one entry. + * @param algos + * An array of allowed server host key algorithms. SSH-2 defines + * ssh-dss and ssh-rsa. The + * entries of the array must be ordered after preference, i.e., + * the entry at index 0 is the most preferred one. You must + * specify at least one entry. */ public synchronized void setServerHostKeyAlgorithms(String[] algos) { @@ -1227,13 +1281,16 @@ public class Connection } /** - * Enable/disable TCP_NODELAY (disable/enable Nagle's algorithm) on the underlying socket. + * Enable/disable TCP_NODELAY (disable/enable Nagle's algorithm) on the + * underlying socket. *

* Can be called at any time. If the connection has not yet been established - * then the passed value will be stored and set after the socket has been set up. - * The default value that will be used is false. + * then the passed value will be stored and set after the socket has been + * set up. The default value that will be used is false. * - * @param enable the argument passed to the Socket.setTCPNoDelay() method. + * @param enable + * the argument passed to the Socket.setTCPNoDelay() + * method. * @throws IOException */ public synchronized void setTCPNoDelay(boolean enable) throws IOException @@ -1245,19 +1302,22 @@ public class Connection } /** - * Used to tell the library that the connection shall be established through a proxy server. - * It only makes sense to call this method before calling the {@link #connect() connect()} - * method. + * Used to tell the library that the connection shall be established through + * a proxy server. It only makes sense to call this method before calling + * the {@link #connect() connect()} method. *

* At the moment, only HTTP proxies are supported. *

- * Note: This method can be called any number of times. The {@link #connect() connect()} - * method will use the value set in the last preceding invocation of this method. + * Note: This method can be called any number of times. The + * {@link #connect() connect()} method will use the value set in the last + * preceding invocation of this method. * * @see HTTPProxyData * - * @param proxyData Connection information about the proxy. If null, then - * no proxy will be used (non surprisingly, this is also the default). + * @param proxyData + * Connection information about the proxy. If null, + * then no proxy will be used (non surprisingly, this is also the + * default). */ public synchronized void setProxyData(ProxyData proxyData) { @@ -1265,40 +1325,47 @@ public class Connection } /** - * Request a remote port forwarding. - * If successful, then forwarded connections will be redirected to the given target address. - * You can cancle a requested remote port forwarding by calling + * Request a remote port forwarding. If successful, then forwarded + * connections will be redirected to the given target address. You can + * cancle a requested remote port forwarding by calling * {@link #cancelRemotePortForwarding(int) cancelRemotePortForwarding()}. *

- * A call of this method will block until the peer either agreed or disagreed to your request- + * A call of this method will block until the peer either agreed or + * disagreed to your request- *

* Note 1: this method typically fails if you *

*

- * Note 2: (from the openssh man page): By default, the listening socket on the server will be - * bound to the loopback interface only. This may be overriden by specifying a bind address. - * Specifying a remote bind address will only succeed if the server's GatewayPorts option - * is enabled (see sshd_config(5)). + * Note 2: (from the openssh man page): By default, the listening socket on + * the server will be bound to the loopback interface only. This may be + * overriden by specifying a bind address. Specifying a remote bind address + * will only succeed if the server's GatewayPorts option is enabled + * (see sshd_config(5)). * - * @param bindAddress address to bind to on the server: - *

- * @param bindPort port number to bind on the server (must be > 0) - * @param targetAddress the target address (IP or hostname) - * @param targetPort the target port + * @param bindAddress + * address to bind to on the server: + * + * @param bindPort + * port number to bind on the server (must be > 0) + * @param targetAddress + * the target address (IP or hostname) + * @param targetPort + * the target port * @throws IOException */ public synchronized void requestRemotePortForwarding(String bindAddress, int bindPort, String targetAddress, @@ -1317,14 +1384,17 @@ public class Connection } /** - * Cancel an earlier requested remote port forwarding. - * Currently active forwardings will not be affected (e.g., disrupted). - * Note that further connection forwarding requests may be received until - * this method has returned. + * Cancel an earlier requested remote port forwarding. Currently active + * forwardings will not be affected (e.g., disrupted). Note that further + * connection forwarding requests may be received until this method has + * returned. * - * @param bindPort the allocated port number on the server - * @throws IOException if the remote side refuses the cancel request or another low - * level error occurs (e.g., the underlying connection is closed) + * @param bindPort + * the allocated port number on the server + * @throws IOException + * if the remote side refuses the cancel request or another low + * level error occurs (e.g., the underlying connection is + * closed) */ public synchronized void cancelRemotePortForwarding(int bindPort) throws IOException { @@ -1338,13 +1408,14 @@ public class Connection } /** - * Provide your own instance of SecureRandom. Can be used, e.g., if you - * want to seed the used SecureRandom generator manually. + * Provide your own instance of SecureRandom. Can be used, e.g., if you want + * to seed the used SecureRandom generator manually. *

- * The SecureRandom instance is used during key exchanges, public key authentication, - * x11 cookie generation and the like. + * The SecureRandom instance is used during key exchanges, public key + * authentication, x11 cookie generation and the like. * - * @param rnd a SecureRandom instance + * @param rnd + * a SecureRandom instance */ public synchronized void setSecureRandom(SecureRandom rnd) { @@ -1353,4 +1424,75 @@ public class Connection this.generator = rnd; } + + /** + * Enable/disable debug logging. Only do this when requested by Trilead + * support. + *

+ * For speed reasons, some static variables used to check whether debugging + * is enabled are not protected with locks. In other words, if you + * dynamicaly enable/disable debug logging, then some threads may still use + * the old setting. To be on the safe side, enable debugging before doing + * the connect() call. + * + * @param enable + * on/off + * @param logger + * a {@link DebugLogger DebugLogger} instance, null + * means logging using the simple logger which logs all messages + * to to stderr. Ignored if enabled is false + */ + public synchronized void enableDebugging(boolean enable, DebugLogger logger) + { + Logger.enabled = enable; + + if (enable == false) + { + Logger.logger = null; + } + else + { + if (logger == null) + { + logger = new DebugLogger() + { + + public void log(int level, String className, String message) + { + long now = System.currentTimeMillis(); + System.err.println(now + " : " + className + ": " + message); + } + }; + } + } + } + + /** + * This method can be used to perform end-to-end connection testing. It + * sends a 'ping' message to the server and waits for the 'pong' from the + * server. + *

+ * When this method throws an exception, then you can assume that the + * connection should be abandoned. + *

+ * Note: Works only after one has passed successfully the authentication + * step. + *

+ * Implementation details: this method sends a SSH_MSG_GLOBAL_REQUEST + * request ('trilead-ping') to the server and waits for the + * SSH_MSG_REQUEST_FAILURE reply packet from the server. + * + * @throws IOException + * in case of any problem + */ + public synchronized void ping() throws IOException + { + if (tm == null) + throw new IllegalStateException("You need to establish a connection first."); + + if (!authenticated) + throw new IllegalStateException("The connection is not authenticated."); + + cm.requestGlobalTrileadPing(); + } } -- cgit v1.2.3