Click here to Skip to main content
15,902,114 members
Articles / Programming Languages / C#
Article

sharpSsh - A Secure Shell (SSH) library for .NET

Rate me:
Please Sign up or sign in to vote.
4.91/5 (125 votes)
29 Oct 2005BSD5 min read 10.4M   87.7K   261   1.1K
A C# implementation of the SSH2 protocol.

Image 1

Introduction

Recently there was a need to connect to a SSH server from my C# code. I needed to perform a simple task: login to a remote Linux device, execute a command and read the response. I knew there were a number of free Java SSH libraries out there and I hoped to find a free .NET one that will allow me to do just that, but all I could find were commercial components. After experimenting with an open source Java SSH library called JSch I decided to try and port it to C# just for the sake of exercise. The result is the attached sharpSsh library and this article which explains how to use it.

Background

SSH (Secure Shell) is a protocol to log into another computer over a network, to execute commands in a remote machine, and to move files from one machine to another. It provides strong authentication and secure communications over unsecured channels. The JSch library is a pure Java implementation of the SSH2 protocol suite; It contains many features such as port forwarding, X11 forwarding, secure file transfer and supports numerous cipher and MAC algorithms. JSch is licensed under BSD style license.

My C# version is not a full port of JSch. I ported only the minimal required features in order to complete my simple task. The following list summarizes the supported features of the library:

  • Key exchange: diffie-hellman-group-exchange-sha1, diffie-hellman-group1-sha1.
  • Cipher: 3des-cbc
  • MAC: hmac-md5
  • Host key type: ssh-rsa and partial ssh-dss.
  • Userauth: password, publickey (RSA)
  • Generating RSA key pairs.
  • Changing the passphrase for a private key.
  • SCP and SFTP

Please check my homepage for the latest version and feature list of SharpSSH.

Using the code

Let me begin with a small disclaimer. The code isn't fully tested, and I cannot guarantee any level of performance, security or quality. The purpose of this library and article is to educate myself (and maybe you) about the SSH protocol and the differences between C# and Java.

In order to provide the simplest API for SSH communication, I created two wrapper classes under the Tamir.SharpSsh namespace that encapsulates JSch's internal structures:

  • SshStream - A stream based class for reading and writing over the SSH channel.
  • Scp - A class for handling file transfers over the SSH channel.

Reading and writing data over the SSH channel

The SshStream class makes reading and writing of data over an SSH channel as easy as any I/O read/write task. Its constructor gets three parameters: The remote hostname or IP address, a username and a password. It connects to the remote server as soon as it is constructed.

C#
//Create a new SSH stream
SshStream ssh = new SshStream("remoteHost", "username", "password");

//..The SshStream has successfully established the connection.

Now, we can set some properties:

C#
//Set the end of response matcher character
ssh.Prompt = "#";
//Remove terminal emulation characters
ssh.RemoveTerminalEmulationCharacters = true;

The Prompt property is a string that matches the end of a response. Setting this property is useful when using the ReadResponse() method which keeps reading and buffering data from the SSH channel until the Prompt string is matched in the response, only then will it return the result string. For example, a Linux shell prompt usually ends with '#' or '$', so after executing a command it will be useful to match these characters to detect the end of the command response (this property actually gets any regular expression pattern and matches it with the response, so it's possible to match more complex patterns such as "\[[^@]*@[^]]*]#\s" which matches the bash shell prompt [user@host dir]# of a Linux host). The default value of the Prompt property is "\n", which simply tells the ReadResponse() method to return one line of response.

The response string will typically contain escape sequence characters which are terminal emulation signals that instruct the connected SSH client how to display the response. However, if we are only interested in the 'clean' response content we can omit these characters by setting the RemoveTerminalEmulationCharacters property to true.

Now, reading and writing to/from the SSH stream will be done as follows:

C#
//Writing to the SSH channel
ssh.Write( command );

//Reading from the SSH channel
string response = ssh.ReadResponse();

Of course, it's still possible to use the SshStream's standard Read/Write I/O methods available in the System.IO.Stream API.

Transferring files using SCP

Transferring files to and from an SSH server is pretty straightforward with the Scp class. The following snippet demonstrates how it's done:

C#
//Create a new SCP instance
Scp scp = new Scp();

//Copy a file from local machine to remote SSH server
scp.To("C:\fileName", "remoteHost", 
             "/pub/fileName", "username", "password");

//Copy a file from remote SSH server to local machine
scp.From("remoteHost", "/pub/fileName", 
               "username", "password", "C:\fileName");

The Scp class also has some events for tracking the progress of file transfer:

  • Scp.OnConnecting - Triggered on SSH connection initialization.
  • Scp.OnStart - Triggered on file transfer start.
  • Scp.OnEnd - Triggered on file transfer end.
  • Scp.OnProgress - Triggered on file transfer progress update (The ProgressUpdateInterval property can be set to modify the progress update interval time in milliseconds).

Running the examples

The demo project is a simple console application demonstrating the use of SshStream and Scp classes. It asks the user for the hostname, username and password for a remote SSH server and shows examples of a simple SSH session, and file transfers to/from a remote SSH machine.

Here is a screen shot of an SSH connection to a Linux shell:

Image 2

And here is a file transfer from a Linux machine to my PC using SCP:

Image 3

In the demo project zip file you will also find an examples directory containing some classes showing the use of the original JSch API. These examples were translated directly from the Java examples posted with the original JSch library and show the use of advanced options such as public key authentication, known hosts files, key generation, SFTP and others.

References

  • SharpSSH Homepage - New versions and bug fixes will be posted here, so please check this page for the latest updates.
  • JSch - JSch is a pure Java implementation of the SSH2 protocol suite. My C# library is based on this project.
  • Mentalis.org - Mentalis.org contains some great .NET projects for security and networking. I used their HMAC and Diffie Hellman classes as part of my SSH implementation.
  • Granados - A full featured open source SSH1 and SSH2 implementation in C#. I found this project after finishing my own library.

History

  • 2005-Oct-16
    • Initial version.
  • 2005-Oct-22
    • Fixed two bugs in Scp class.
  • 2005-Oct-29
    • Added the option to use DSA signatures ('ssh-dss') for authenticating the server during the key-exchange phase.
  • 2005-Oct-29
    • All future updates will be posted in my homepage.

License

This article, along with any associated source code and files, is licensed under The BSD License


Written By
Software Developer
Israel Israel
Works as a Network Engineer for a leading networking company.

Comments and Discussions

 
GeneralRe: Transfering multiple files using wild cards Pin
Tamir Gal19-Dec-06 2:19
Tamir Gal19-Dec-06 2:19 
AnswerRe: GETing multiple files using wild cards Pin
leisenstein8-Jan-07 9:42
leisenstein8-Jan-07 9:42 
GeneralMy compliments!! Pin
Erion Pici14-Dec-06 6:20
Erion Pici14-Dec-06 6:20 
GeneralRe: My compliments!! Pin
leisenstein8-Jan-07 9:44
leisenstein8-Jan-07 9:44 
GeneralRe: My compliments!! (& .Net 2.0) Pin
syzygyfire8-Feb-07 4:43
syzygyfire8-Feb-07 4:43 
QuestionProblems Executing Command Using SshExec.RunCommand & SshShell Pin
SiTeW13-Dec-06 23:22
SiTeW13-Dec-06 23:22 
AnswerRe: Problems Executing Command Using SshExec.RunCommand & SshShell Pin
Tamir Gal15-Dec-06 5:47
Tamir Gal15-Dec-06 5:47 
GeneralRe: Problems Executing Command Using SshExec.RunCommand & SshShell Pin
SiTeW17-Dec-06 9:35
SiTeW17-Dec-06 9:35 
Hi Tamir

Thanks for replying. I'll try your suggestion and let you know how it goes in a further post. Before I try it, though, here's the info on the scripts we run.

We have two scripts we run, one to process the file we have sent to the host system and another to generate a file that we will download from the host. I suspect these scripts may not be much help to you as each is basically just a d3 (Pick system) command.

However, I'll include the script we run to process the file we send to the host. The script contents are:

d3 -d \'\\r\\rUSERNAME\\rPWD\\rT\\rPROC_FILE\\r$1$2\\rexit\\r\' > /usr/site/procfiletxfr 2>&1
cd /usr/pick/input/site.$1
# <two lines="" commented="" out="">
cd /usr/pick/output/site.$1
mv new.004 new.005
mv new.003 new.004
mv new.002 new.003
mv new.001 new.002
mv new new.001
mv siteqty.004 siteqty.005
mv siteqty.003 siteqty.004
mv siteqty.002 siteqty.003
mv siteqty.001 siteqty.002
mv siteqty siteqty.001
exit 0

(sensitive info such as username, password, folder, file & script names changed).

Not knowing much about Linux or Pick, I understand the script to dupicate key strokes, mimicking the input a user would make. The "T" input after the username and password is selecting an item from a menu. PROC_FILE is the script that processes the contents of our file into the Pick system. It relies on us first having uploaded our file into a certain directory (which is happening ok).

The script generates a log file called procfiletxfr. This log file includes the standard output that a user would see on screen if they were to enter the contents of the script directly into a terminal. The script also rolls over two sets of backup files - new and siteqty - which are copies of files we have downloaded from the host.

The script is /usr/bin/site2pick. The command we send to call this script would be something like:

/usr/bin/site2pick 99 sales.005

Where the "99" is our local site ID and "sales.005" is the file we have uploaded for processing.

As far as I can see, the script will run using that SshShell code in my previous post if all the new and siteqty files exist. However, if one or more of the "new" or "siteqty" files doesn't exist then no "procfiletxfr" file is created, suggesting that the script has not run.

When I do get a "procfiletxfr" file, it seems to indicate the process is not running to completion. It will show something like:

09:57:26 15 Dec 2006
Enter your user id: '
User password:
Invalid user or password

09:57:26 15 Dec 2006
Enter your user id: USERNAME
User password:
Warning: Cannot reset term.

If I enter the same d3 command manually into a terminal I get the following output:

09:58:47 15 Dec 2006
Enter your user id: '
User password:
Invalid user or password

09:58:47 15 Dec 2006
Enter your user id: USERNAME
User password:

There is no warning and a menu is displayed.

I'm not sure if the above is much help in explaining why I can't get the system to work. I will try your suggestion and see if that improves things.

Cheers
Simon
GeneralRe: Problems Executing Command Using SshExec.RunCommand & SshShell Pin
SiTeW17-Dec-06 13:16
SiTeW17-Dec-06 13:16 
Generalvb.net app doesn't close when using SharpSSH Pin
DuncanC_edm13-Dec-06 7:21
DuncanC_edm13-Dec-06 7:21 
GeneralRe: vb.net app doesn't close when using SharpSSH Pin
Tamir Gal13-Dec-06 7:56
Tamir Gal13-Dec-06 7:56 
GeneralRe: vb.net app doesn't close when using SharpSSH Pin
DuncanC_edm13-Dec-06 9:57
DuncanC_edm13-Dec-06 9:57 
GeneralRe: vb.net app doesn't close when using SharpSSH Pin
Tamir Gal15-Dec-06 5:32
Tamir Gal15-Dec-06 5:32 
GeneralRe: vb.net app doesn't close when using SharpSSH Pin
Jordon4Kraftd16-Nov-07 11:09
Jordon4Kraftd16-Nov-07 11:09 
GeneralRe: vb.net app doesn't close when using SharpSSH Pin
hardmuf25-Oct-11 0:28
hardmuf25-Oct-11 0:28 
GeneralRe: vb.net app doesn't close when using SharpSSH Pin
jmwAtUnisys11-Jan-07 7:02
jmwAtUnisys11-Jan-07 7:02 
GeneralRe: vb.net app doesn't close when using SharpSSH [modified] Pin
leisenstein8-Jan-07 9:50
leisenstein8-Jan-07 9:50 
GeneralUserAuthPubKey Pin
BoFabio11-Dec-06 8:07
BoFabio11-Dec-06 8:07 
GeneralRe: UserAuthPubKey Pin
Tamir Gal12-Dec-06 10:13
Tamir Gal12-Dec-06 10:13 
GeneralRe: UserAuthPubKey Pin
BoFabio12-Dec-06 20:30
BoFabio12-Dec-06 20:30 
GeneralRe: UserAuthPubKey Pin
BoFabio12-Dec-06 20:37
BoFabio12-Dec-06 20:37 
GeneralRe: UserAuthPubKey Pin
Tamir Gal13-Dec-06 8:03
Tamir Gal13-Dec-06 8:03 
GeneralRe: UserAuthPubKey Pin
BoFabio14-Dec-06 8:29
BoFabio14-Dec-06 8:29 
GeneralRe: UserAuthPubKey Pin
Tamir Gal19-Dec-06 2:01
Tamir Gal19-Dec-06 2:01 
QuestionRe: UserAuthPubKey Pin
dfkthbq8-Feb-07 0:28
dfkthbq8-Feb-07 0:28 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.