Home > Articles > Programming > Java

Java Reference Guide

Hosted by

Toggle Open Guide Table of ContentsGuide Contents

Close Table of ContentsGuide Contents

Close Table of Contents

Ganymed SSH-2 for Java

Last updated Mar 14, 2003.

If you’ve worked with Linux or Unix you have undoubtedly encountered SSH. SSH, or secure shell, is defined on wikipedia as “a network protocol that allows data to be exchanged securely between two network devices.” SSH is used for many purposes, including:

  • A replacement for telnet and rlogin for executing shell commands
  • To execute a single command on a remote server using rsh
  • To copy files between servers using SCP
  • Used with SFTP to support secure FTP
  • Port forwarding or tunneling
  • Encrypted VPN, such as with OpenSSH
  • As a secure proxy with the SOCKS protocol
  • To create a secure file system using SSHFS

As a bit of background, SSH was created in 1995, but had security vulnerabilities that allowed for a “man in the middle” attack, so SSH-2 was released in 1996. In 2006, SSH-2 became a proposed Internet standard.

Encrypting the transmission of data between servers is very important, especially in current times in which almost every computer is connected to a network. And if you’re writing a Java application that needs to connect to a remote server and transfer sensitive data, it would be nice to take advantage of the work that went into integrating SSH with unix/linux operating systems. The Jakarta Commons Net classes provide support for Telnet, FTP, and a host of other protocols, but not for SSH.

Fortunately, there is a library called Ganymed SSH-2 for Java that implements SSH 2 using AES, Blowfish, and 3DES encryption ciphers in a BSD style license, and using it is very straightforward. Download Ganymed and add ganymed-ssh2-build210.jar (or the latest version) to your CLASSPATH and then implement the following steps:

  1. Create a Connection object, passing it the host name or IP address (as a String) of the server you want to connect to
  2. Call the Connection’s connect() method to connect to the server
  3. Call authenticateWithPassword(), passing it your username and password
  4. Open a Session by calling the Connection’s openSession()
  5. Execute a command by calling the Session’s execCommand() method, passing it the command to execute
  6. Consume the response of the command by invoking the sessions’ getStdOut() (or getStdErr() if you want the error stream), optionally using Ganymed’s StreamGobbler to help you
  7. Close the session by calling the Session’s close() method
  8. Close the connection by calling its close() method

Listing 1 shows the source code for a class called SSHAgent that provides the ability to execute commands on a remote computer using SSH.

Listing 1. SSHAgent.java

package com.javasrc.jolt.agent.ssh;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;

import com.javasrc.jolt.component.linux.model.FileSystem;

/**
 * The SSHAgent allows a Java application to execute commands on a remote server via SSH
 * 
 * @author shaines
 *
 */
public class SSHAgent {
    
    /**
     * The hostname (or IP address) of the server to connect to
     */
    private String hostname;
    
    /**
     * The username of the user on that server
     */
    private String username;
    
    /**
     * The password of the user on that server
     */
    private String password;
    
    /**
     * A connection to the server
     */
    private Connection connection;
    
    /**
     * Creates a new SSHAgent
     * 
     * @param hostname
     * @param username
     * @param password
     */
    public SSHAgent( String hostname, String username, String password )
    {
        this.hostname = hostname;
        this.username = username;
        this.password = password;
    }
    
    /**
     * Connects to the server
     * 
     * @return        True if the connection succeeded, false otherwise
     */
    public boolean connect() throws SSHException
    {
        try
        {
            // Connect to the server
            connection = new Connection( hostname );
            connection.connect();
            
            // Authenticate
            boolean result = connection.authenticateWithPassword( username, password );
            System.out.println( "Connection result: " + result );
            return result;
        }
        catch( Exception e )
        {
            throw new SSHException( "An exception occurred while trying to connect to the host: " + hostname + ", Exception=" + e.getMessage(), e ); 
        }
    }
    
    /**
     * Executes the specified command and returns the response from the server
     *  
     * @param command        The command to execute
     * @return               The response that is returned from the server (or null)
     */
    public String executeCommand( String command ) throws SSHException 
    {
        try
        {
            // Open a session
            Session session = connection.openSession();
            
            // Execute the command
            session.execCommand( command );
            
            // Read the results
            StringBuilder sb = new StringBuilder();
            InputStream stdout = new StreamGobbler( session.getStdout() );
            BufferedReader br = new BufferedReader(new InputStreamReader(stdout));
            String line = br.readLine();
            while( line != null )
            {
                sb.append( line + "\n" );
                line = br.readLine();
            }

            // DEBUG: dump the exit code
            System.out.println( "ExitCode: " + session.getExitStatus() );

            // Close the session
            session.close();
            
            // Return the results to the caller
            return sb.toString();
        }
        catch( Exception e )
        {
            throw new SSHException( "An exception occurred while executing the following command: " + command + ". Exception = " + e.getMessage(), e );
        }
    }

    /**
     * Logs out from the server
     * @throws SSHException
     */
    public void logout() throws SSHException
    {
        try
        {
            connection.close();
        }
        catch( Exception e )
        {
            throw new SSHException( "An exception occurred while closing the SSH connection: " + e.getMessage(), e );
        }
    }
    
    /**
     * Returns true if the underlying authentication is complete, otherwise returns false
     * @return
     */
    public boolean isAuthenticationComplete()
    {
        return connection.isAuthenticationComplete();
    }
    
    public static void main( String[] args ) 
    {
        try
        {
            SSHAgent sshAgent = new SSHAgent( "192.168.2.3", "username", "mypassword" );
            if( sshAgent.connect() ) 
            {
                String diskInfo = sshAgent.executeCommand( "df -k" );
                System.out.println( "Disk info: " + diskInfo );
                
                String processInfo = sshAgent.executeCommand( "top -b -n 1" );
                System.out.println( "Process Info: " + processInfo );
                
                // Logout
                sshAgent.logout();
            }
        }
        catch( SSHException e )
        {
            e.printStackTrace();
        }
    }
}

Listing 1 implements all of the aforementioned steps, wrapping them into the SSHAgent class. To use this class, the main() method creates an instance, passing it the host name, username, and password, calls connect(), and then executes a couple commands:

  • df -k shows hard disk information such as the total size of each hard drive and how much space is available
  • top -b -n 1 shows a combination of memory, CPU, and process information. The “top” command presents all of this information in an interactive text UI, so “-b” tells it to run in “batch mode” and “-n” tells it how many iterations to run, which is once in this case

The following is the output of running this application in my environment:

Connection result: true
ExitCode: null
Disk info: Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/sdb1             56649688  37197348  16574700  70% /
tmpfs                  1422124         0   1422124   0% /lib/init/rw
varrun                 1422124      1848   1420276   1% /var/run
varlock                1422124         0   1422124   0% /var/lock
udev                   1422124      2860   1419264   1% /dev
tmpfs                  1422124       104   1422020   1% /dev/shm
lrm                    1422124      2004   1420120   1% /lib/modules/2.6.27-11-generic/volatile
/dev/sdg1            732572000 513842468 218729532  71% /media/New Volume
/dev/scd0               266850    266850         0 100% /media/cdrom0
/dev/sda1             78147688  43732360  34415328  56% /media/disk
/dev/sdh1            976521568 749319872 227201696  77% /media/My Book

ExitCode: null
Process Info: top - 22:30:00 up 17 days, 11:50,  2 users,  load average: 0.00, 0.05, 0.18
Tasks: 158 total,   1 running, 157 sleeping,   0 stopped,   0 zombie
Cpu(s):  1.5%us,  1.0%sy,  0.2%ni, 96.2%id,  0.9%wa,  0.0%hi,  0.2%si,  0.0%st
Mem:   2844252k total,  2764004k used,    80248k free,     8500k buffers
Swap:  2498068k total,     5444k used,  2492624k free,  2062624k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND            
 8064 shaines   20   0  2412 1064  784 R    4  0.0   0:00.02 top                
 5917 shaines   20   0 21548 8992 7424 S    2  0.3  13:48.53 multiload-apple    
    1 root      20   0  3056 1896  576 S    0  0.1   0:01.38 init               
    2 root      15  -5     0    0    0 S    0  0.0   0:00.02 kthreadd           
    3 root      RT  -5     0    0    0 S    0  0.0   0:00.26 migration/0        
    4 root      15  -5     0    0    0 S    0  0.0  20:16.71 ksoftirqd/0        
    5 root      RT  -5     0    0    0 S    0  0.0   0:00.00 watchdog/0         
    6 root      RT  -5     0    0    0 S    0  0.0   0:00.28 migration/1        
    7 root      15  -5     0    0    0 S    0  0.0   4:18.69 ksoftirqd/1        
    8 root      RT  -5     0    0    0 S    0  0.0   0:00.00 watchdog/1         
    9 root      15  -5     0    0    0 S    0  0.0   0:10.56 events/0           
   10 root      15  -5     0    0    0 S    0  0.0   0:10.02 events/1           
   11 root      15  -5     0    0    0 S    0  0.0   0:00.02 khelper            
   51 root      15  -5     0    0    0 S    0  0.0   0:00.00 kintegrityd/0      
   52 root      15  -5     0    0    0 S    0  0.0   0:00.00 kintegrityd/1      
   54 root      15  -5     0    0    0 S    0  0.0   0:19.02 kblockd/0          
   55 root      15  -5     0    0    0 S    0  0.0   0:21.08 kblockd/1          
   57 root      15  -5     0    0    0 S    0  0.0   0:00.00 kacpid             
   58 root      15  -5     0    0    0 S    0  0.0   0:00.00 kacpi_notify       
  125 root      15  -5     0    0    0 S    0  0.0   0:00.00 cqueue             
  129 root      15  -5     0    0    0 S    0  0.0   0:00.00 kseriod            
  168 root      15  -5     0    0    0 S    0  0.0  19:43.78 kswapd0            
  208 root      15  -5     0    0    0 S    0  0.0   0:00.00 aio/0              
  209 root      15  -5     0    0    0 S    0  0.0   0:00.00 aio/1              
 1224 root      15  -5     0    0    0 S    0  0.0   0:00.00 ksuspend_usbd      
 1232 root      15  -5     0    0    0 S    0  0.0   0:01.96 khubd              
 1254 root      15  -5     0    0    0 S    0  0.0   1:08.80 ata/0              
 1256 root      15  -5     0    0    0 S    0  0.0   0:06.38 ata/1              
 1258 root      15  -5     0    0    0 S    0  0.0   0:00.00 ata_aux            
 1983 root      15  -5     0    0    0 S    0  0.0   0:00.00 scsi_eh_0          
 1984 root      15  -5     0    0    0 S    0  0.0   0:00.00 scsi_eh_1          
 2018 root      15  -5     0    0    0 S    0  0.0   0:00.00 scsi_eh_2          
 2019 root      15  -5     0    0    0 S    0  0.0   0:00.00 scsi_eh_3          
 2114 root      15  -5     0    0    0 S    0  0.0   0:00.00 scsi_eh_4          
 2115 root      15  -5     0    0    0 S    0  0.0   2:59.67 usb-storage        
 2127 root      15  -5     0    0    0 S    0  0.0   0:00.00 scsi_eh_6          
 2128 root      15  -5     0    0    0 S    0  0.0  10:45.66 usb-storage        
 2244 root      15  -5     0    0    0 S    0  0.0   0:26.48 kjournald          
 2422 root      16  -4  2528 1024  404 S    0  0.0   0:00.90 udevd              
 2860 root      15  -5     0    0    0 S    0  0.0   0:00.00 kpsmoused          
 4273 daemon    20   0  1912  528  424 S    0  0.0   0:00.00 portmap            
 4295 statd     20   0  1976  744  636 S    0  0.0   0:00.00 rpc.statd          
 4301 root      15  -5     0    0    0 S    0  0.0   0:00.00 rpciod/0           
 4304 root      15  -5     0    0    0 S    0  0.0   0:00.00 rpciod/1           
 4314 root      15  -5     0    0    0 S    0  0.0   0:00.00 nfsiod             
 4323 root      20   0  4040  604  320 S    0  0.0   0:00.00 rpc.idmapd         
 4447 root      20   0  1780  524  456 S    0  0.0   0:00.00 getty              
 4448 root      20   0  1780  524  456 S    0  0.0   0:00.00 getty              
 4451 root      20   0  1780  524  456 S    0  0.0   0:00.00 getty              
 4452 root      20   0  1780  524  456 S    0  0.0   0:00.00 getty              
 4455 root      20   0  1780  528  456 S    0  0.0   0:00.00 getty              
 4645 root      20   0  2308 1220  540 S    0  0.0   0:00.00 acpid              
 4694 root      15  -5     0    0    0 S    0  0.0   0:00.00 kondemand/0        
 4696 root      15  -5     0    0    0 S    0  0.0   0:00.00 kondemand/1        
 4777 syslog    20   0  2012  708  556 S    0  0.0   0:03.14 syslogd            
 4830 root      20   0  1940  540  444 S    0  0.0   0:00.16 dd                 
 4832 klog      20   0  3508 2348  440 S    0  0.1   0:00.22 klogd              
 4855 messageb  20   0  3024 1456  856 S    0  0.1   0:24.78 dbus-daemon        
 4877 avahi     20   0  2992 1564 1300 S    0  0.1   0:01.44 avahi-daemon       
 4878 avahi     20   0  2888  496  296 S    0  0.0   0:00.00 avahi-daemon       
 4907 root      20   0  5396 1064  668 S    0  0.0   0:00.06 sshd               
 5037 root      15  -5     0    0    0 S    0  0.0   0:00.00 lockd              
 5038 root      15  -5     0    0    0 S    0  0.0   0:00.08 nfsd4              
 5039 root      15  -5     0    0    0 S    0  0.0   0:00.00 nfsd               
 5040 root      15  -5     0    0    0 S    0  0.0   0:00.00 nfsd               
 5041 root      15  -5     0    0    0 S    0  0.0   0:00.00 nfsd               
 5042 root      15  -5     0    0    0 S    0  0.0   0:00.00 nfsd               
 5043 root      15  -5     0    0    0 S    0  0.0   0:00.00 nfsd               
 5044 root      15  -5     0    0    0 S    0  0.0   0:00.00 nfsd               
 5045 root      15  -5     0    0    0 S    0  0.0   0:00.00 nfsd               
 5046 root      15  -5     0    0    0 S    0  0.0   0:00.00 nfsd               
 5050 root      20   0  2096  316  168 S    0  0.0   0:00.00 rpc.mountd         
 5099 root      20   0  7164 1696 1192 S    0  0.1   0:43.36 nmbd               
 5101 root      20   0 13052 3524 2368 S    0  0.1   0:01.74 smbd               
 5123 haldaemo  20   0  7232 5316 3724 S    0  0.2   0:44.56 hald               
 5126 root      20   0 17656 3108 1788 S    0  0.1   0:19.67 console-kit-dae    
 5127 root      20   0  3364 1156  936 S    0  0.0   0:03.08 hald-runner        
 5208 root      20   0 12684 1200  432 S    0  0.0   0:00.00 smbd               
 5209 root      20   0  3436 1048  904 S    0  0.0   0:00.02 hald-addon-inpu    
 5214 root      20   0  3440 1060  908 S    0  0.0   1:28.27 hald-addon-stor    
 5217 haldaemo  20   0  2296  896  760 S    0  0.0   0:00.00 hald-addon-acpi    
 5219 root      20   0  3440 1060  908 S    0  0.0   1:26.99 hald-addon-stor    
 5222 root      20   0  3440 1060  908 S    0  0.0   1:27.81 hald-addon-stor    
 5225 root      20   0  3440 1060  908 S    0  0.0   1:27.74 hald-addon-stor    
 5238 root      20   0  3440 1152  996 S    0  0.0   7:16.57 hald-addon-stor    
 5285 root      20   0  3488 1548 1324 S    0  0.1   0:00.00 bluetoothd         
 5291 root      15  -5     0    0    0 S    0  0.0   0:00.00 btaddconn          
 5293 root      15  -5     0    0    0 S    0  0.0   0:00.00 btdelconn          
 5324 root      10 -10     0    0    0 S    0  0.0   0:00.00 krfcommd           
 5347 root      20   0 14632 2524 2080 S    0  0.1   0:01.42 NetworkManager     
 5363 root      20   0  4244 1328 1096 S    0  0.0   0:00.00 wpa_supplicant     
 5367 root      20   0  6768 2964 2452 S    0  0.1   0:00.68 nm-system-setti    
 5383 root      20   0 14240 1780 1052 S    0  0.1   0:00.00 gdm                
 5386 root      20   0 19492 4788 3588 S    0  0.2   0:00.08 gdm                
 5389 root      20   0  273m  40m 8944 S    0  1.5 163:51.60 Xorg               
 5406 root      20   0  4336 1152  912 S    0  0.0   0:00.00 system-tools-ba    
 5440 daemon    20   0  2068  460  328 S    0  0.0   0:00.00 atd                
 5472 root      20   0  3412 1032  820 S    0  0.0   0:02.24 cron               
 5584 root      20   0  1780  528  456 S    0  0.0   0:00.00 getty              
 5675 shaines   20   0 14700 2168 1724 S    0  0.1   0:00.02 gnome-keyring-d    
 5686 shaines   20   0 24764 5744 4660 S    0  0.2   0:03.24 x-session-manag    
 5743 shaines   20   0  3124  672  456 S    0  0.0   0:00.00 dbus-launch        
 5744 shaines   20   0  3036 1300  644 S    0  0.0   0:29.26 dbus-daemon        
 5747 shaines   20   0 29968 4172 3124 S    0  0.1   0:42.32 pulseaudio         
 5750 shaines   20   0  7528 2544 2072 S    0  0.1   0:00.00 gconf-helper       
 5752 shaines   20   0  7780 4780 2176 S    0  0.2   0:31.08 gconfd-2           
 5758 shaines   20   0 17712 6328 4652 S    0  0.2   0:00.16 seahorse-agent     
 5761 shaines   20   0 17384  13m 1808 S    0  0.5   0:07.34 gvfsd              
 5765 shaines   20   0 13916 3628 2972 S    0  0.1   0:01.08 gnome-keyring-d    
 5766 shaines   20   0 46084  15m 8332 S    0  0.5   1:48.44 gnome-settings-    
 5770 shaines   20   0  1844  548  452 S    0  0.0   0:00.00 compiz             
 5775 shaines   20   0 29196 2068 1636 S    0  0.1   0:00.00 gvfs-fuse-daemo    
 5842 shaines   20   0 24520  16m 7084 S    0  0.6  55:39.38 compiz.real        
 5849 shaines   20   0 21336 5680 4268 S    0  0.2   1:42.44 gnome-screensav    
 5854 shaines   20   0  1844  488  424 S    0  0.0   0:00.00 sh                 
 5855 shaines   20   0  1844  524  440 S    0  0.0   0:00.00 compiz-decorato    
 5857 shaines   20   0 21076  11m 7164 S    0  0.4   1:00.23 gtk-window-deco    
 5858 shaines   20   0 38584  22m  12m S    0  0.8   2:05.80 gnome-panel        
 5860 shaines   20   0  245m 194m  15m S    0  7.0 189:37.08 nautilus           
 5862 shaines   20   0 41664 3520 2684 S    0  0.1   0:00.18 bonobo-activati    
 5872 shaines   20   0 23460 3192 2424 S    0  0.1   0:00.32 gvfs-hal-volume    
 5874 shaines   20   0  5536 2196 1600 S    0  0.1   0:00.04 gvfs-gphoto2-vo    
 5877 shaines   20   0  5556 2208 1880 S    0  0.1   0:00.00 gvfsd-burn         
 5881 shaines   20   0 39744 2976 2276 S    0  0.1   0:02.56 gvfsd-trash        
 5885 shaines   20   0 38684  16m 9952 S    0  0.6   0:03.59 trashapplet        
 5920 shaines   20   0 26704  13m 9036 S    0  0.5   0:03.68 fast-user-switc    
 5923 shaines   20   0 45140  15m 9.8m S    0  0.6   0:00.99 mixer_applet2      
 5927 root      20   0  3980 1336  700 S    0  0.0 222:26.10 mount.ntfs-3g      
 5968 shaines   20   0 65328  10m 8448 S    0  0.4   0:02.19 evolution-alarm    
 5969 shaines   20   0 14752 5840 4832 S    0  0.2   0:02.72 bluetooth-apple    
 5970 shaines   20   0 15556 5552 4580 S    0  0.2   0:01.94 tracker-applet     
 5971 shaines   20   0 25476  12m 7352 S    0  0.5   0:05.38 python             
 5974 shaines   20   0 27904  16m 9332 S    0  0.6   0:06.12 nm-applet          
 5978 shaines   20   0 29800  17m  10m S    0  0.6   0:27.64 update-notifier    
 5980 shaines   20   0 21364 7988 6444 S    0  0.3   0:03.52 vino-server        
 5983 shaines   39  19 31540  10m 2260 S    0  0.4   0:00.13 trackerd           
 5984 shaines   20   0 23956 8908 6416 S    0  0.3   0:20.66 gnome-power-man    
 5992 shaines   20   0 61948 7548 5600 S    0  0.3   0:00.11 evolution-data-    
 5994 shaines   20   0 23904  13m 7728 S    0  0.5   0:08.42 notification-da    
 5999 shaines   20   0 32424 9920 7936 S    0  0.3   0:00.08 evolution-excha    
 7820 root      20   0 12408 4296 3428 S    0  0.2   0:00.04 sshd               
 7830 shaines   20   0 12540 1884 1000 S    0  0.1   0:00.08 sshd               
 7831 shaines   20   0  5704 3052 1468 S    0  0.1   0:00.20 bash               
 7870 root      20   0     0    0    0 S    0  0.0   0:00.02 pdflush            
 7875 root      20   0     0    0    0 S    0  0.0   0:00.04 pdflush            
 7943 root      20   0 12408 4268 3404 S    0  0.2   0:00.04 sshd               
 7991 shaines   20   0 13540 2968 1036 S    0  0.1   0:05.80 sshd               
 7995 shaines   20   0  5076 1668 1084 S    0  0.1   0:12.68 sftp-server        
 8052 root      20   0 12408 4268 3404 S    0  0.2   0:00.04 sshd               
 8059 shaines   20   0 12408 1856  988 S    0  0.1   0:00.00 sshd               
 9775 shaines   20   0  250m  86m  27m S    0  3.1   5:20.31 firefox            
14537 root      20   0  3908 1196  668 S    0  0.0   0:02.60 mount.ntfs-3g      
18158 root      15  -5     0    0    0 S    0  0.0   0:00.00 scsi_eh_8          
18159 root      15  -5     0    0    0 S    0  0.0   1:38.22 usb-storage        
18248 root      20   0 14540 5220 4060 S    0  0.2   7:38.46 smbd               
21206 root      20   0  2252  952  824 S    0  0.0   0:00.00 dhclient           
22557 root      20   0 14432 5456 4328 S    0  0.2   0:10.34 smbd               
32062 root      20   0  6440 2396 1736 S    0  0.1   0:00.88 cupsd              

SSH is the best way to securely transfer information between network devices and can be used to execute commands on remote servers. In this example I used the Ganymed SSH-2 Java library to connect to a remote server and read its disk, memory, CPU, and process information all in a handful of lines of code. SSH is a complicated protocol, but Ganymed makes its implementation simple.