NetSieben SSH Library (ne7ssh) v1.1.0 README
LEGALESE
NetSieben Technologies Pty Limited
http://www.netsieben.com
Copyright (C) 2005-2006 NetSieben Technologies Pty Limited ALL RIGHTS RESERVED
This program may be distributed under the terms of the Q Public License as defined by Trolltech AS of Norway and appearing in the file LICENSE.QPL included in the packaging of this file.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
INTRODUCTION
The SSH protocol is used by many vendors, with firewalls and other network appliances now having SSH server software built into them.
If you are a developer wishing to integrate SSH client functionality into your applications you can now use the NetSieben SSH library, instead of spending countless hours developing your own solution.
The library was developed by NetSieben after researching the limited number of options available. A lot of available solutions were either wrappers to openssh application or libraries with very limited functionality, and at best, still in alpha or beta stages of development.
At the time the library was written, version 1 of the SSH protocol was rather outdated with well known security flaws inherently in its design. It was therefore decided to work only with version 2 of SSH protocol.
Currently NetSieben's library supports only the SSH client.
FEATURES
Key exchange: Diffie Hellman Group 1, SHA1
Host key algorithms: ssh-dss (1024)
User authentication: public key, password
Authentication key algorithms: DSA, RSA
Encryption algorithms: aes256-cbc, twofish-cbc, twofish256-cbc, blowfish-cbc, 3des-cbc, aes128-cbc, cast128-cbc
MAC algorithms: hmac-md5, hmac-sha1, none
Compression: none
Interoperability: SSH Library works well with most SSH2 server implementations.
Portability: The NetSieben SSH Library is based on the Botan crypto library, making it highly portable. It has been tested on Linux x86, Linux PPC, Linux SPARC, Windows 2000 and XP, and has even been ported to Linux running on AMD64 bit architecture.
DEPENDENCIES
NetSiben SSH Library requires Botan crypto library 1.4.9 or higher. It can be found here:
INSTALLATION
NetSieben SSH Library is distributed in source code form. The current version uses autoconf to handle generating an appropriate Makefile for your system. Generally you should be able to install NetSieben SSH Library like this:
./configure
make
make install
For more information pleas refer to INSTALL file included in this software package.
HOW TO USE
I) Initializing the class.
Firstly, you need to initialize the class before using the library. This will allocate the required memory resources and initialize the cryptographic algorithms. It is recommended do this first, when starting your application.
You can use only one instance of ne7ssh class at a time and make connections to multiple servers using a single ne7ssh class. It is best to initialize the class when starting, and use the same class for all of your SSH connections, destroying the class when the application quits.
You can initialize the class by using a command:
ne7ssh *ssh = new ne7ssh ();
The constructor of the class requires no arguments. The application will be aborted if trying to initialize the class more than once in the same application.
II)Setting the options.
Before opening connections to SSH servers, you may want to apply some custom options to the class. At this point, NetSieben allows you to set your preferred cipher and integrity checking algorithms. This can be accomplished by using this method:
setOptions ( const char prefCipher, const char prefHmac )
The method takes two parameters
prefCipher - your preferred cipher algorithm string representation.
NetSieben supports the following cipher algorithms: aes256-cbc,
twofish-cbc, twofish256-cbc, blowfish-cbc, 3des-cbc,
aes128-cbc, cast128-cbc.
prefHmac - the preferred integrity checking algorithm string.
The supported algorithms are: hmac-md5, hmac-sha1 and none.
An example of using this method:
ssh->setOptions ("blowfish-cbc", "none");
If desired you can skip this step, in which case the default set of algorithms will be used. If your preferred algorithm is not supported by the server, the next algorithm in the list of supported algorithms will be chosen by the client.
III) Connecting to a remote server.
After your options are set, you can start connections to remote servers. NetSieben library supports Password and Public Key types of authentication.
To establish a connection to remote server using your private key use the following method:
int ssh->connectWithKey (const char* host, uint32 port, const char* username, const char* privKeyFile);
The method takes 4 parameters.
host - Hostname or IP of the host you are connecting to.
port - Port SSH server on remote end is listening on. This will
usually be 22 (standard SSH port).
username - Username used to authenticate to the server.
privKeyFile - Full path to PEM encoded private key file. Key format is compatible with OpenSSH. OpenSSH encrypted keys are not supported at this time.
If the connection was successful, the method will return channel ID. This ID should be used in all further communications over the channel.
If the connection failed for any reason, "-1" will be returned by the method.
An example of using this method:
int channel1;
channel1 = ssh->connectWithKey ("192.168.1.1", 22, "admin", "/home/admin/.ssh/id_dsa")
This method will establish SSH connection to 192.168.1.1 and authenticate using account "admin" with private key stored in "id_dsa" file. If public key for user "admin" was not added to authorized_keys file on the server side, this method will return "-1".
To establish a connection to remote server using a password use the following method:
int connectWithPassword (const char host, uint32 port, const char username, const char *password )
The method takes 4 parameters.
host - Hostname or IP of the host you are connecting to.
port - Port SSH server on remote end is listening on. This will
usually be 22 (standard SSH port).
username - Username used to authenticate to the server. password - Password to use in authentication.
If the connection was successful, the method will return the channel ID that the connection was established on. This ID should be used in all further communications over the channel.
If the connection failed for any reason, "-1" will be returned by the metho.
An example of using this method:
int channel1;
channel1 = ssh->connectWithPassword ("192.168.1.1", 22, "admin", "password")
This method will establish SSH connection to 192.168.1.1 and authenticate using account "admin" with password "password".
IV) Waiting for results.
After the connection is established or after sending a command to the remote end you can pause until a specific requested string is received.
The SSH protocol is designed to send data in packets. If you read the result buffer right after you send a command to remote end, there is no guarantee that all data requested has been received. Thus it is useful to wait for a particular string to arrive, ensuring that all the data has been received. The string to wait for could be a shell prompt on the remote end.
If you do not receive an expected string, to avoid blocking condition, you can also specify a timeout. If the desired result is not received in the specified time, the function will return false.
The method used is:
bool waitFor (int channel, const char *str, uint32 timeout = 0)
The method takes 3 parameters.
channel - Channel ID received from the connection method, specifying
the channel to wait on.
str - String to wait for.
timeout - Timeout in seconds which really depends on the speed of your
connection to the remote side. 2 seconds should be enough for
most connections. If 0 is passed here, the method will block
until the requested string is found in the receive buffer.
If an expected string has been received the method will return "true". If a timeout has been reached, the method will return "false".
An example of using this method:
ssh->waitFor (channel1, " $", 5)
This method will pause on channel1 until " $" , the string, which can indicate a default bash shell prompt. The method will timeout and return after 5 seconds if " $" isn't received.
V) Sending a command to remote server.
Sending a command to the remote end can be accomplished using this method:
bool send (const char *data, int channel )
The method takes 2 parameters.
data - Command to send to remote side. This is just a string, which you
should terminate with an end-line. Most terminals will not
process your command if you do not append an end-line
character(s) (\n on Unix) to it.
channel - Channel ID.
The method will return "true" if the write to send buffer was successful. Otherwise false will be returned.
Note: Keep in mind that each usage of send will zero out the receive buffer.
An example of using this method:
ssh->send ("ls\n", channel1)
This command will send "ls" (unix command to get directory listing) to remote end. Command will be sent on the previously opened channel1.
VI) Reading the result.
Data received resulting from execution of a command can be retrieved with the following method:
const char *read (int channel )
The method takes 1 parameter, which is the number of the channel we got from connection method.
The method will return a pointer to the entire receive buffer. The memory for the buffer doesn't need to be allocated nor freed by a programmer, its storage is handled by the ne7ssh class.
The best place to execute this method would be just after waitFor() method returns, checking first to ensure that your data is there rather than not received due to a timeout.
An example of using this method:
const char* result;
result = ssh->read (channel1);
This will return pointer to the receive buffer on channel1.
If data received is not a string but binary stream such as a result of "cat /usr/bash", the size of received data can be obtained by using this method:
int getReceivedSize (int channel);
The method takes 1 parameter, which is the number of the channel we got from connection method.
The method will return the size of receive buffer. This value can be used in conjunction with pointer obtained from read() method to read data from the buffer passed the zero character.
VII) Closing the connection.
When you are done with the connection you can close it using this method:
bool close (int channel)
The method takes the channel number as a parameter and returns "true" if the close command was successfully placed into the send buffer. You will receive "false" if the channel has already been closed.
It is highly recommended that you use a shell command to close the connection and not this method. For example if you wish to close a remote terminal session running a bash shell, send:
ssh->send ("exit\n", channel1)
On most SSH servers, this will usually close the channel gracefully. If a close command is sent before remote shell is terminated, the remote end will send a hangup signal to the application running on the remote end. That might not always be a desired action.
An example of this method:
ssh->close (channel1);
This will close the channel previously opened with connection method.
VIII) Retrieving errors.
If something doesn't work out as planned, and any of the above mentioned methods return with either "false" in boolean methods or "-1" in other cases, there is a good chance that some errors occurred in communication or in other parts of library. These errors are placed into a static buffer within ne7ssh class. These errors can be retrieved with this method:
const char *getErrors ()
This method takes no parameters as it is a global method and not channel specific. It will return a pointer to buffer containing all error strings, separated by line feeds (\n).
IX) Generating key.
Starting with version 1.1 NetSieben SSH Library can be used to generate PKI keys used for public key authentication.
To generate a key pair use the following method:
bool generateKeyPair (const char* type, const char* fqdn, const char* privKeyFileName, const char* pubKeyFileName, uint16 keySize);
The method takes 5 parameters of which the last one is optional.
type - String specifying key type. Currently "dsa" and "rsa" are supported. fqdn - User id. Such as an Email address. privKeyFileName - Full path to a file where generated private key should be written. pubKeyFileName - Full path to a file where generated public key should be written. keySize - Desired key size in bits. If not specified will default to 2048.
The method will return "true" if keys were generated and written to the specified files. Otherwise false is returned.
Enjoy!
Andrew Useckas
