Creating a connection

Lee Painter

The first thing you will probably want to do is to connect to an SSH server using J2SSH Maverick. This is a fairly straightforward procedure using the SshConnector class. This class creates the initial connection, determines which protocol versions are supported by the server and depending upon which settings have been specified informs the server which protocol version to use for the newly created connection.

The next few sections will guide you through making the initial connection, authenticating the user and executing a command or starting the user's shell for a simple console-based SSH application. First, let's look at the SshConnector and the basic connection options available.

To create an instance of the SshConnector uses the following code:

SshConnector con = SshConnector.createInstance();


The SshConnector class is designed to be configured and reused for all subsequent connections that require the same settings. The SshConnector provides you with access to a SshContext object for each version of the protocol that the API supports and this can be used to configure the various components of the protocol, such as ciphers, macs, public keys, and compression preferences and also socket timeout and connection behavior. 

Host Key Verification


When the client connects to the server, the server supplies its public key for the client to verify. It is good practice to check the supplied key to verify the identity of the server and with Maverick this is possible using the HostKeyVerification interface. You can provide your own implementation of this interface if you require custom handling of the server’s public key however most SSH implementations verify the key against a list of known hosts stored in a special file $HOME/.ssh/known_hosts. 

Maverick provides an abstract implementation called AbstractKnownHostsKeyVerification to handle the reading of keys from the known_hosts file should you want to prompt the user within your own user interface but for the purposes of this command line example we will use the ConsoleKnownHostsKeyVerification class to prompt the user through System.out.

con.setKnownHosts(new ConsoleKnownHostsKeyVerification());


When we eventually make our connection we will be prompted in the console to confirm the identity of the server:

The host shell.sourceforge.net is currently unknown to the system
The host key (ssh-dss) fingerprint is: f2:fd:57:3f:b1:f4:90:2d:2d:e8:50:de:99:9c:dd:fe:13:1f:8c:8c
Do you want to allow this host key? [Yes|No|Always]:

 

Setting SSH Version (Commercial API Only)

The default behavior for the SshConnector is to select an SSH2 connection where ever possible, this is because SSH1 has known vulnerabilities and should only be used when no SSH2 connection is available. If you are using the commercial version of the API then an SSH1 implementation is available to you. If you wish to force the use of a specific version you can configure the SshConnector using the following code before calling the connect method:

// Force the use of the SSH1 protocol
con.setSupportedVersions(SshConnector.SSH1);

// Force the use of SSH2 i.e. do not fallback to SSH1
con.setSupportedVersions(SshConnector.SSH2);

 

Establishing the Connection


When we are ready to make a connection we call the following method

SshClient ssh = con.connect(new SocketTransport("cvs", 22), "lee", true);

The first parameter provides the transport mechanism for the connection which in this case is a Socket. Maverick has been designed to operate over a transport interface called SshTransport which at its simplest requires just a pair of IO streams. This enables Maverick to operate over any type of current or future communication medium supported by the Java runtime. Notice that we have passed the hostname of the computer we wish to connect to and the port number to the SocketTransport constructor, which in our case is the default SSH port number 22.

The SocketTransport class extends Socket directly and as such uses the default socket connection settings. If you want to set a custom connect timeout you should create a Socket directly and pass it into the API using the SocketWrapper transport. More information can be found here.

The second parameter identifies the username for the connection. This needs to be declared now as it's used by the client to get a list of available authentication methods prior to performing authentication.

The third boolean parameter of 'true' tells the API to use a threaded mode client. The API can operate in a single-threaded or threaded mode. If you choose a single-threaded mode no further threads will be spawned by the API. A further discussion of this can be found here.

Once a connection has been established the method returns an instance of the SshClient interface. This interface provides a protocol-independent contract for an SSH client allowing applications to support both versions of the SSH protocol without the need for separate client libraries. It should be noted that there are many differences between the protocols and some restrictions may apply when using the interface, these will be identified as and when required but for general usage, this interface provides a suitable means for SSH protocol independence.

 

Authenticating

We now have a connection to the SSH server and the next task is to authenticate the user we declared earlier in our connect method. We will not be able to perform any other operation until the user has been authenticated. Password authentication is ideal for first time users as it requires no additional configuration within the SSH client or server. The user simply supplies his username and password to the client which is then transmitted over the encrypted connection to the server. The server then checks that the given password is acceptable to the native password-authentication mechanism of the host operating system and returns the result to the client.

// Create a password authentication object
PasswordAuthentication pwd = new PasswordAuthentication();
pwd.setPassword("xxxxxxxx"); 


This creates a PasswordAuthentication object and configures it with the user's password. We are now ready to authenticate the user.

if(ssh.authenticate(pwd)==SshAuthentication.COMPLETE) {
     // We have authenticated 
}


The authenticate method returns either SshAuthentication.COMPLETE to indicate successful authentication, SshAuthentication.FAILED to indicate the credentials were not accepted or SshAuthentication.FURTHER_AUTHENTICATION_REQUIRED to indicate that the authentication was successful but a further method of authentication is required.

This concludes this article as we now have an authenticated SshClient which can be used to start a shell, execute a command, create port forwards or transfer files over SFTP or SCP. Please see the articles listed below to continue your implementation.

Authenticating with public/private keys

[TODO] Starting a shell and executing commands

[TODO] Transferring files over SFTP

[TODO] Using SCP

[TODO] Creating a port forwarding client

Setting SSH2 algorithm preferences