⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 connection.java

📁 thinking in java4 src
💻 JAVA
📖 第 1 页 / 共 3 页
字号:

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 + -