Indice

Scrivere un client ssh con libssh2

Autore: Fabio Di Matteo
Ultima revisione: 25/07/2008

Libssh2 è una libreria che implementa il protocollo SSH2 come definito nelle specifiche: SECSH-TRANS, SECSH-USERAUTH, SECSH-CONNECTION, SECSH-ARCH, SECSH-FILEXFER, SECSH-DHGEX, SECSH-NUMBERS, e SECSH-PUBLICKEY .

Dipendenze

Prepariamo quello che serve

Siccome non installeremo libssh2 ma la utilizzeremo piuttosto come libreria statica dobbiamo prepararci tutto l'occorrente.

  1. Scarichiamo Libssh2 (sorgenti);
  2. compiliamo i sorgenti con ./configure && make ;
  3. creiamo una directory vuota;
  4. copiamo nella directory vuota libssh2.a contenuta in src/.libs;
  5. copiamo anche tutta include/ ;
  6. copiamo anche example/simple/config.h che è un file di configurazione della libreria (non sempre indispensabile).

Bene adesso il contenuto della nostra directory sarà questo:

config.h  include  libssh2.a 

al quale andremo ad aggiungere :

* makefile (il nostro makefile)
* ssh2.c (il sorgente completo del nostro client);

Il makefile

Semplice e conciso:

all:
	gcc -lssl -lcrypto -L/usr/lib -lz  ssh2.c  libssh2.a -o ssh2 

come potete vedere compila staticamente libssh2 ma ha comunque bisogno delle librerie dinamiche libssl, libcrypto e libz le quali sono comunemente disponibili su tutte le distribuzioni GNU/Linux ma non solo.

Il sorgente del nostro client

Esegue il comando specificato nella variabile cmd (riga 35) .

#include "config.h"
#include "include/libssh2.h"
 
#ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
# ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
# ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
 
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <ctype.h>
 
 
 
int main(void)
{
	/*Parametri per la connessione SSH*/
	char* host="127.0.0.1"; //solo ip, non risolve i nomi di host
	int   port=22;
	char* user="utente";
	char* pass="password-segreta";    
	char* cmd="touch PROVAAA\n";
	/*----------------------------------*/
 
 
 
    int sock;
    LIBSSH2_SESSION *session; //puntatore sessione ssh
    LIBSSH2_CHANNEL *channel; //puntatore shell ssh
    struct sockaddr_in sin;   // socket generico aperto per la connessione	
 
 
 
	/* Connessione ad un socket generico sulla porta 22 */
	sock = socket(AF_INET, SOCK_STREAM, 0);
	#ifndef WIN32
    		fcntl(sock, F_SETFL, 0);
	#endif
    	sin.sin_family = AF_INET;
    	sin.sin_port = htons(port);
    	sin.sin_addr.s_addr = inet_addr(host);
	if (connect(sock, (struct sockaddr*)(&sin), sizeof(struct sockaddr_in)) != 0) {
        	fprintf(stderr, "Connessione fallita!\n");
        	return -1;
    	}
 
 
 
 
    session = libssh2_session_init();
 
    if (libssh2_session_startup(session, sock)) {
        /* istruzioni se la connessione fallisce */
    } else {
        /* istruzioni se la connessione va a buon fine */
    }
 
 
 
    /* Autenticazione */
    if (libssh2_userauth_password(session, user, pass)) {
        /* istruzioni se la autenticazione fallisce */
    } else {
        /* istruzioni se la autenticazione va a buon fine */
    }
 
    /*Apriamo un canale per scrivere i comandi*/
    if (!(channel = libssh2_channel_open_session(session))) {
        /* l'apertura del canale fallisce */
    } else {
        /* Successo, si può lanciare una shell in questo canale */
        libssh2_channel_shell(channel);
    }
 
 
    /* Lanciamo il comando "touch PROVAAA" e premiamo invio */
    libssh2_channel_write(channel, cmd, strlen(cmd));
 
    /* Chiudiamo il canale con la shell associata adesso che abbiamo finito */
    libssh2_channel_close(channel);
 
    /* Distruggiamo il puntatore al canale*/
    libssh2_channel_free(channel);
 
 
	/*Ci disconnettiamo e distruggiamo il socket alla connessione */
	libssh2_session_disconnect(session, "Goodbye");
    	libssh2_session_free(session);
 
    return 0;
}

Risolvere i nomi degli host

Il codice di sopra non risolve i nomi host, ma se si ha l'esigenza di risolverli basta includere Una funzione per risolvere i nomi di dominio modificare la sezione dei parametri in questo modo:

...
        /*Parametri per la connessione SSH*/
	char* host=resolv("localhost"); 
	int   port=22;
	char* user="utente";
	char* pass="password-segreta";    
	char* cmd="touch PROVAAA\n";
	/*----------------------------------*/
 
...