Friday, January 29, 2010

 

Synapse Based SSH Client


Many times, I needed a way to let my Delphi/FPC applications to connect to an SSH server, execute some commands, and get its results. Now I'm publishing a simple class based on Synapse's TTelnetSend class to do exactly what I needed.

Required ingredients

First of all, you'll need to grab a copy of the latest version of Synapse, now, to connect to an SSH server, the connection must be established by using the SSL protocol, and Synapse allows that kind of connections with plugins that allow filtering the data through OpenSSL, CryptLib and StreamSecII. Here, I'll use CryptLib, so you'll have to get this compiled version of cl32.dll for Windows, if you need the library compiled for Linux search for it in your repository (or use Google).

Now, configure the search paths of your compiler to find both, Synapse source and cryptlib.pas, the wrapper for cl32.dll.

Introducing TSSHClient class

This is a simple class to let you connect to an SSH server in an Object Oriented way, its internal parts where found in the Synapse's newsgroups, tested and arranged in a class.


unit sshclient;

interface

uses
tlntsend, ssl_openssl, ssl_openssl_lib, ssl_cryptlib;

type
TSSHClient = class
private
FTelnetSend: TTelnetSend;
public
constructor Create(AHost, APort, AUser, APass: string);
destructor Destroy; override;
procedure SendCommand(ACommand: string);
procedure LogOut;
function ReceiveData: string;
function LogIn: Boolean;
end;

implementation

{ TSSHClient }

constructor TSSHClient.Create(AHost, APort, AUser, APass: string);
begin
FTelnetSend := TTelnetSend.Create;
FTelnetSend.TargetHost := AHost;
FTelnetSend.TargetPort := APort;
FTelnetSend.UserName := AUser;
FTelnetSend.Password := APass;
end;

destructor TSSHClient.Destroy;
begin
FTelnetSend.Free;
inherited;
end;

function TSSHClient.LogIn: Boolean;
begin
Result := FTelnetSend.SSHLogin;
end;

procedure TSSHClient.LogOut;
begin
FTelnetSend.Logout;
end;

function TSSHClient.ReceiveData: string;
var
lPos: Integer;
begin
Result := '';
lPos := 1;
while FTelnetSend.Sock.CanRead(1000) or (FTelnetSend.Sock.WaitingData>0) do
begin
FTelnetSend.Sock.RecvPacket(1000);
Result := Result + Copy(FTelnetSend.SessionLog, lPos, Length(FTelnetSend.SessionLog));
lPos := Length(FTelnetSend.SessionLog)+1;
end;
end;

procedure TSSHClient.SendCommand(ACommand: string);
begin
FTelnetSend.Send(ACommand + #13);
end;

end.


A sample application

This is an example of how to execute an "df -h" command in an external SSH server, inspirated by a question in StackOverflow.

The example just connects to a server, execute the command and capture its output, just that.


program TestSSHClient;

{$APPTYPE CONSOLE}

uses
sshclient;

var
lSSh: TSSHClient;
begin
lSSh := TSSHClient.Create('[TARGET_HOST_OR_IP_ADDRESS]', '[PORT]', '[USER]', '[PASSWORD]');
if lSSh.LogIn then
begin
Writeln('Connected!.');
(* Get welcome message *)
Writeln(lSSh.ReceiveData);
(* Send command *)
lSSh.SendCommand('df -h');
(* Receive results *)
Writeln(lSSh.ReceiveData);
lSSh.LogOut;
Writeln('Logged out.');
end
else
Writeln('Can''t connect.');
lSSh.Free;
end.


Replace the words between '[' and ']' by the real ones and test it.

See you on my next post.
Comments:
Can't get it to work. Putty connects OK but this code, with the same login parameters, comes up with "Can't connect" (after quite a long time). Using Delphi 5, if that's a clue ...

Regards,
Dag Hovden
 
I don't know. The example was created with Delphi 7 and was tested with two of my SSH servers.

I'm sure you can find more help in the Synapse mailing list, and please, send them as much details about your Putty configuration info as you can, for example, if your target server works with SSH v.1 or v2.
 
ola que tal
sou rod, moro em foz do iguaçu, pr, e gostei muito do seu artigo sobre ssh.
gostaria de saber como proceder pra utilizar a mesma classe do synapse pra utilizar scp (cópia segura).
gracias!
 
ola que tal
sou rod, moro em foz do iguaçu, pr, e gostei muito do seu artigo sobre ssh.
gostaria de saber como proceder pra utilizar a mesma classe do synapse pra utilizar scp (cópia segura).
gracias!
 
Leonardo, disculpa porque mi consulta no está relacionada con tu ejemplo, pero es que hace tiempo que busco una solución y no la encuentro.
Uso Lazarus e intento hacer un clon del Explorador de Windows para las XO. Compilo en Windows y en Linux.

El problema es que en Linux el componente ListView solo muestra iconos en el estado vsReport; si paso a vsIcon, queda en blanco , pero los items no desaparecieron, volviendo a vsReport reaparecen.

Este comportamiento sucede solo en Linux; el mismo código fuente compilado en Windows funciona bien, y el ListView muestra correctamente los iconos en cualquiera de sus estados.

Disculpa nuevamente , pero es que no encuentro solución y te agradezco cualquier pista. Hace meses pedí ayuda en el sitio de Lazarus pero no tuve suerte.
Uso Lazarus 0.9.28. Mi correo es alejandro.lavarello (arroba) gmail.com
Saludos desde Uruguay.
 
Leonardo, disculpa porque mi consulta no está relacionada con tu ejemplo, pero es que hace tiempo que busco una solución y no la encuentro.
Uso Lazarus e intento hacer un clon del Explorador de Windows para las XO. Compilo en Windows y en Linux.

El problema es que en Linux el componente ListView solo muestra iconos en el estado vsReport; si paso a vsIcon, queda en blanco , pero los items no desaparecieron, volviendo a vsReport reaparecen.

Este comportamiento sucede solo en Linux; el mismo código fuente compilado en Windows funciona bien, y el ListView muestra correctamente los iconos en cualquiera de sus estados.

Disculpa nuevamente , pero es que no encuentro solución y te agradezco cualquier pista. Hace meses pedí ayuda en el sitio de Lazarus pero no tuve suerte.
Uso Lazarus 0.9.28. Mi correo es alejandro.lavarello (arroba) gmail.com
Saludos desde Uruguay.
 
Hola Alejandro, te respondo por mail.
 
ROD, I found a way to make SCP operations with Synapse!, I'm trying to find time to publish some code examples in the Blog.
 
Thank you really much !
It helped me a lot.
+++
 
I found this really helpful - followed your instructions and it works as described on Delphi 2007.

Many thanks!
 
Thanks, it helped me in my homework!
 
Hi!

Only use ssl_cryptlib in the uses, and it will work with LT_SSHv2.
 
My testing program didn't work. Still error "Can't connect."
Here are my tools:
BDS 2006
Synapse39
CryptLib-3.2.2
CL32spy340

What's the trick to fix this?
 
Post a Comment

Links to this post:

Create a Link



<< Home

This page is powered by Blogger. Isn't yours?