📄 connection.java
字号:
package ch.ethz.ssh2;
import java.io.CharArrayWriter;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.SocketTimeoutException;
import java.security.SecureRandom;
import ch.ethz.ssh2.auth.AuthenticationManager;
import ch.ethz.ssh2.channel.ChannelManager;
import ch.ethz.ssh2.crypto.CryptoWishList;
import ch.ethz.ssh2.crypto.cipher.BlockCipherFactory;
import ch.ethz.ssh2.crypto.digest.MAC;
import ch.ethz.ssh2.transport.KexManager;
import ch.ethz.ssh2.transport.TransportManager;
import ch.ethz.ssh2.util.TimeoutService;
import ch.ethz.ssh2.util.TimeoutService.TimeoutToken;
/**
* A <code>Connection</code> is used to establish an encrypted TCP/IP
* connection to a SSH-2 server.
* <p>
* Typically, one
* <ol>
* <li>creates a {@link #Connection(String) Connection} object.</li>
* <li>calls the {@link #connect() connect()} method.</li>
* <li>calls some of the authentication methods (e.g., {@link #authenticateWithPublicKey(String, File, String) authenticateWithPublicKey()}).</li>
* <li>calls one or several times the {@link #openSession() openSession()} method.</li>
* <li>finally, one must close the connection and release resources with the {@link #close() close()} method.</li>
* </ol>
*
* @author Christian Plattner, plattner@inf.ethz.ch
* @version $Id: Connection.java,v 1.20 2006/02/14 19:43:16 cplattne Exp $
*/
public class Connection
{
/* The identifier presented to the SSH-2 server. */
public final static String identification = "Ganymed Build_209";
/* Will be used to generate all random data needed for the current connection.
* Note: SecureRandom.nextBytes() is thread safe.
*/
private final SecureRandom rnd = new SecureRandom();
/**
* Unless you know what you are doing, you will never need this.
*
* @return The list of supported cipher algorithms by this implementation.
*/
public static synchronized String[] getAvailableCiphers()
{
return BlockCipherFactory.getDefaultCipherList();
}
/**
* Unless you know what you are doing, you will never need this.
*
* @return The list of supported MAC algorthims by this implementation.
*/
public static synchronized String[] getAvailableMACs()
{
return MAC.getMacList();
}
/**
* Unless you know what you are doing, you will never need this.
*
* @return The list of supported server host key algorthims by this implementation.
*/
public static synchronized String[] getAvailableServerHostKeyAlgorithms()
{
return KexManager.getDefaultServerHostkeyAlgorithmList();
}
private AuthenticationManager am;
private boolean authenticated = false;
private ChannelManager cm;
private CryptoWishList cryptoWishList = new CryptoWishList();
private DHGexParameters dhgexpara = new DHGexParameters();
private final String hostname;
private final int port;
private TransportManager tm;
private boolean tcpNoDelay = false;
/**
* Prepares a fresh <code>Connection</code> object which can then be used
* to establish a connection to the specified SSH-2 server.
* <p>
* Same as {@link #Connection(String, int) Connection(hostname, 22)}.
*
* @param hostname the hostname of the SSH-2 server.
*/
public Connection(String hostname)
{
this(hostname, 22);
}
/**
* Prepares a fresh <code>Connection</code> object which can then be used
* to establish a connection to the specified SSH-2 server.
*
* @param hostname
* the host where we later want to connect to.
* @param port
* port on the server, normally 22.
*/
public Connection(String hostname, int port)
{
this.hostname = hostname;
this.port = port;
}
/**
* After a successful connect, one has to authenticate oneself. This method
* is based on DSA (it uses DSA to sign a challenge sent by the server).
* <p>
* If the authentication phase is complete, <code>true</code> will be
* returned. If the server does not accept the request (or if further
* authentication steps are needed), <code>false</code> is returned and
* one can retry either by using this or any other authentication method
* (use the <code>getRemainingAuthMethods</code> method to get a list of
* the remaining possible methods).
*
* @param user
* A <code>String</code> holding the username.
* @param pem
* A <code>String</code> containing the DSA private key of the
* user in OpenSSH key format (PEM, you can't miss the
* "-----BEGIN DSA PRIVATE KEY-----" tag). The string may contain
* linefeeds.
* @param password
* If the PEM string is 3DES encrypted ("DES-EDE3-CBC"), then you
* must specify the password. Otherwise, this argument will be
* ignored and can be set to <code>null</code>.
*
* @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.
*
*/
public synchronized boolean authenticateWithDSA(String user, String pem, String password) throws IOException
{
if (tm == null)
throw new IllegalStateException("Connection is not established!");
if (authenticated)
throw new IllegalStateException("Connection is already authenticated!");
if (am == null)
am = new AuthenticationManager(tm);
if (cm == null)
cm = new ChannelManager(tm);
if (user == null)
throw new IllegalArgumentException("user argument is null");
if (pem == null)
throw new IllegalArgumentException("pem argument is null");
authenticated = am.authenticatePublicKey(user, pem.toCharArray(), password, rnd);
return authenticated;
}
/**
* A wrapper that calls {@link #authenticateWithKeyboardInteractive(String, String[], InteractiveCallback)
* authenticateWithKeyboardInteractivewith} a <code>null</code> submethod list.
*
* @param user
* A <code>String</code> holding the username.
* @param cb
* An <code>InteractiveCallback</code> which will be used to
* determine the responses to the questions asked by the server.
* @return whether the connection is now authenticated.
* @throws IOException
*/
public synchronized boolean authenticateWithKeyboardInteractive(String user, InteractiveCallback cb)
throws IOException
{
return authenticateWithKeyboardInteractive(user, null, cb);
}
/**
* After a successful connect, one has to authenticate oneself. This method
* is based on "keyboard-interactive", specified in
* draft-ietf-secsh-auth-kbdinteract-XX. Basically, you have to define a
* callback object which will be feeded with challenges generated by the
* server. Answers are then sent back to the server. It is possible that the
* callback will be called several times during the invocation of this
* method (e.g., if the server replies to the callback's answer(s) with
* another challenge...)
* <p>
* If the authentication phase is complete, <code>true</code> will be
* returned. If the server does not accept the request (or if further
* authentication steps are needed), <code>false</code> is returned and
* one can retry either by using this or any other authentication method
* (use the <code>getRemainingAuthMethods</code> method to get a list of
* the remaining possible methods).
* <p>
* Note: some SSH servers advertise "keyboard-interactive", however, any
* interactive request will be denied (without having sent any challenge to
* the client).
*
* @param user
* A <code>String</code> holding the username.
* @param submethods
* An array of submethod names, see
* draft-ietf-secsh-auth-kbdinteract-XX. May be <code>null</code>
* to indicate an empty list.
* @param cb
* An <code>InteractiveCallback</code> which will be used to
* determine the responses to the questions asked by the server.
*
* @return whether the connection is now authenticated.
* @throws IOException
*/
public synchronized boolean authenticateWithKeyboardInteractive(String user, String[] submethods,
InteractiveCallback cb) throws IOException
{
if (cb == null)
throw new IllegalArgumentException("Callback may not ne NULL!");
if (tm == null)
throw new IllegalStateException("Connection is not established!");
if (authenticated)
throw new IllegalStateException("Connection is already authenticated!");
if (am == null)
am = new AuthenticationManager(tm);
if (cm == null)
cm = new ChannelManager(tm);
if (user == null)
throw new IllegalArgumentException("user argument is null");
authenticated = am.authenticateInteractive(user, submethods, cb);
return authenticated;
}
/**
* After a successfull connect, one has to authenticate oneself. This method
* sends username and password to the server.
* <p>
* If the authentication phase is complete, <code>true</code> will be
* returned. If the server does not accept the request (or if further
* authentication steps are needed), <code>false</code> is returned and
* one can retry either by using this or any other authentication method
* (use the <code>getRemainingAuthMethods</code> method to get a list of
* the remaining possible methods).
* <p>
* Note: if this method fails, then please double-check that it is actually
* offered by the server (use {@link #getRemainingAuthMethods(String) getRemainingAuthMethods()}.
* <p>
* 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
* @return if the connection is now authenticated.
* @throws IOException
*/
public synchronized boolean authenticateWithPassword(String user, String password) throws IOException
{
if (tm == null)
throw new IllegalStateException("Connection is not established!");
if (authenticated)
throw new IllegalStateException("Connection is already authenticated!");
if (am == null)
am = new AuthenticationManager(tm);
if (cm == null)
cm = new ChannelManager(tm);
if (user == null)
throw new IllegalArgumentException("user argument is null");
if (password == null)
throw new IllegalArgumentException("password argument is null");
authenticated = am.authenticatePassword(user, password);
return authenticated;
}
/**
* 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 =).
* <p>
* 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.
* <p>
* If the authentication phase is complete, <code>true</code> will be
* returned. If the server does not accept the request (or if further
* authentication steps are needed), <code>false</code> is returned and
* one can retry either by using this or any other authentication method
* (use the <code>getRemainingAuthMethods</code> method to get a list of
* the remaining possible methods).
* <p>
* 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 <code>String</code> holding the username.
* @param pemPrivateKey
* A <code>char[]</code> 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 <code>null</code>.
*
* @return whether the connection is now authenticated.
* @throws IOException
*/
public synchronized boolean authenticateWithPublicKey(String user, char[] pemPrivateKey, String password)
throws IOException
{
if (tm == null)
throw new IllegalStateException("Connection is not established!");
if (authenticated)
throw new IllegalStateException("Connection is already authenticated!");
if (am == null)
am = new AuthenticationManager(tm);
if (cm == null)
cm = new ChannelManager(tm);
if (user == null)
throw new IllegalArgumentException("user argument is null");
if (pemPrivateKey == null)
throw new IllegalArgumentException("pemPrivateKey argument is null");
authenticated = am.authenticatePublicKey(user, pemPrivateKey, password, rnd);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -