A great ssh 2 java library JSCH
Here you can find one of the most cleaner implementation I found, to realize ssh sftp tools in java.
Here a breaf usage example class:
public class SSHConnectionCore {
Logger LOG = Logger.getLogger(SSHConnectionCore.class);
private class JonnyUserInfo implements UserInfo {
private String password;
private String passphrase;
private String userName;
public JonnyUserInfo(String username) {
this.userName = username;
}
@Override
public String getPassphrase() {
return passphrase;
}
@Override
public String getPassword() {
return password;
}
@Override
public boolean promptPassphrase(String message) {
passphrase = null;
LOG.debug(message);
passphrase = readOneLine();
if (passphrase != null && passphrase.length() > 0) {
return true;
} else {
return false;
}
}
@Override
public boolean promptPassword(String message) {
password = null;
// stampo il messaggio ricevuto dall'host
LOG.debug(message);
// richiedo la password.. questo step deve venire saltato nel caso
// di host riconosciuti con chiave
password = readOneLine();
if (password != null && password.length() > 0) {
return true;
} else {
return false;
}
}
/**
* Chiedo all'utente di dare l'autorizzazione per la connessione ad un
* host non verificato, questo metodo dovrebbe essere richiamato quando
* non viene verificato l'host tramite chiave oppure l'host non è
* registrato tra gli known host TODO verificare!
*/
@Override
public boolean promptYesNo(String message) {
// stampa il messaggio ricevuto dall'host
LOG.debug(message);
// richiedo la conferma dell'utente
String s = readOneLine();
if ("yes".equalsIgnoreCase(s)) {
return true;
}
return false;
}
/**
* Stampo un messaggio del framework
*/
@Override
public void showMessage(String message) {
LOG.debug(message);
}
private String readOneLine() {
BufferedReader in = new BufferedReader(new InputStreamReader(
System.in));
try {
return in.readLine();
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}
/**
* open an exec channel to execute command
*
* @param userName
* @param hostIp
* @param Port
* @param command
* @throws Exception
*/
public File execCommandInSession(String userName,String hostIp,int Port,String command,int timeOut,
String privateKeyPath,String knownHosts) throws Exception,SSHConnectionException {
File tmp = null;
JSch jsch = new JSch();
// in questo caso utilizzo rsa per accesso diretto
Logger LOG = Logger.getLogger(SSHConnectionCore.class);
private class JonnyUserInfo implements UserInfo {
private String password;
private String passphrase;
private String userName;
public JonnyUserInfo(String username) {
this.userName = username;
}
@Override
public String getPassphrase() {
return passphrase;
}
@Override
public String getPassword() {
return password;
}
@Override
public boolean promptPassphrase(String message) {
passphrase = null;
LOG.debug(message);
passphrase = readOneLine();
if (passphrase != null && passphrase.length() > 0) {
return true;
} else {
return false;
}
}
@Override
public boolean promptPassword(String message) {
password = null;
// stampo il messaggio ricevuto dall'host
LOG.debug(message);
// richiedo la password.. questo step deve venire saltato nel caso
// di host riconosciuti con chiave
password = readOneLine();
if (password != null && password.length() > 0) {
return true;
} else {
return false;
}
}
/**
* Chiedo all'utente di dare l'autorizzazione per la connessione ad un
* host non verificato, questo metodo dovrebbe essere richiamato quando
* non viene verificato l'host tramite chiave oppure l'host non è
* registrato tra gli known host TODO verificare!
*/
@Override
public boolean promptYesNo(String message) {
// stampa il messaggio ricevuto dall'host
LOG.debug(message);
// richiedo la conferma dell'utente
String s = readOneLine();
if ("yes".equalsIgnoreCase(s)) {
return true;
}
return false;
}
/**
* Stampo un messaggio del framework
*/
@Override
public void showMessage(String message) {
LOG.debug(message);
}
private String readOneLine() {
BufferedReader in = new BufferedReader(new InputStreamReader(
System.in));
try {
return in.readLine();
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}
/**
* open an exec channel to execute command
*
* @param userName
* @param hostIp
* @param Port
* @param command
* @throws Exception
*/
public File execCommandInSession(String userName,String hostIp,int Port,String command,int timeOut,
String privateKeyPath,String knownHosts) throws Exception,SSHConnectionException {
File tmp = null;
JSch jsch = new JSch();
// in questo caso utilizzo rsa per accesso diretto
// senza digitare ogni volta la passwd
LOG.debug("Identity added:"+privateKeyPath);
// utilizzo una passphrase nulla per l'rsa
jsch.addIdentity(privateKeyPath,"");
LOG.debug("Identity added:"+privateKeyPath);
// utilizzo una passphrase nulla per l'rsa
jsch.addIdentity(privateKeyPath,"");
// setto i known hosts
jsch.setKnownHosts(knownHosts);
JonnyUserInfo cui1 = new JonnyUserInfo(userName);
Session session = jsch.getSession(userName,hostIp);
LOG.debug("Working with session :" + session);
session.setUserInfo(cui1);
session.connect();
ChannelExec channel = null;
try {
channel = (ChannelExec) session.openChannel("exec");
if (channel == null)
System.exit(0);
LOG.debug("Execute command :"+command);
channel.setCommand(command);
channel.setErrStream(System.err);
FileOutputStream fos = null;
try {
tmp = File.createTempFile("command_output","txt");
fos = new FileOutputStream(tmp);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
// use System.out if you want more output or fos if file
channel.setOutputStream(fos);
channel.connect(9000);
} catch (JSchException e) {
e.printStackTrace();
throw new SSHConnectionException();
}
while (true) {
// rimango in attesa fino alla chiusura del channel
if (channel.isClosed()) {
LOG.debug("- il canale è stato chiuso con stato: "
+ channel.getExitStatus());
break;
}
try {
Thread.sleep(1000);
} catch (Exception ee) {
ee.printStackTrace();
}
}
channel.disconnect();
session.disconnect();
return (tmp);
}
}
jsch.setKnownHosts(knownHosts);
JonnyUserInfo cui1 = new JonnyUserInfo(userName);
Session session = jsch.getSession(userName,hostIp);
LOG.debug("Working with session :" + session);
session.setUserInfo(cui1);
session.connect();
ChannelExec channel = null;
try {
channel = (ChannelExec) session.openChannel("exec");
if (channel == null)
System.exit(0);
LOG.debug("Execute command :"+command);
channel.setCommand(command);
channel.setErrStream(System.err);
FileOutputStream fos = null;
try {
tmp = File.createTempFile("command_output","txt");
fos = new FileOutputStream(tmp);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
// use System.out if you want more output or fos if file
channel.setOutputStream(fos);
channel.connect(9000);
} catch (JSchException e) {
e.printStackTrace();
throw new SSHConnectionException();
}
while (true) {
// rimango in attesa fino alla chiusura del channel
if (channel.isClosed()) {
LOG.debug("- il canale è stato chiuso con stato: "
+ channel.getExitStatus());
break;
}
try {
Thread.sleep(1000);
} catch (Exception ee) {
ee.printStackTrace();
}
}
channel.disconnect();
session.disconnect();
return (tmp);
}
}
One of the most difficult thing I found was the authentication activities to obtain access directly via rsa asymmetric key exchange.
This is exactly what I did.
On a windows developer machine I've installed a Lubuntu virtual machine, to test the pure ssh connection.
This lighting me the right way.
Creating A Key
Protocol version 1 key generation
To create the most simple key, with the default encryption, open up a console, and enter the following command :
$ ssh-keygen
Will output the following :
Generating public/private rsa1 key pair. Enter file in which to save the key (/home/dave/.ssh/identity): /home/dave/.ssh/identity Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /home/dave/.ssh/identity. Your public key has been saved in /home/dave/.ssh/identity.pub. The key fingerprint is: 22:bc:0b:fe:f5:06:1d:c0:05:ea:59:09:e3:07:8a:8c dave@caprice
When asked for a "passphrase", we won't enter one. Just press enter twice.
The ssh-keygen program will now generate both your public and your
private key. For the sake of this first simple tutorial I will call
these files by their default names "identity" and the public key
"identity.pub".
Your keys are stored in the .ssh/ of the client linux box for instance, directory in your home directory,
but you can store them where ever you'd like.
Good practice is to backup
your keys on a floppy. If you do so, guard this floppy with your life!
* Note: specifying a key type may be mandatory on your system. In that case, skip to the version 2 key geneation process.
Lets have a look at your keys.
cd ~.ssh; ls -l -rw------- 1 dave dave 526 Nov 2 01:33 identity -rw-r--r-- 1 dave dave 330 Nov 2 01:33 identity.pub
The file
identity contains your private key. YOU SHOULD
GUARD THIS KEY WITH YOUR LIFE! This key is used to gain access on
systems which have your private key listed in their authorized keys
file.
I cannot stress this enough, dont have your keys drifting around.
Also, make sure your private key always is chmod 600, so other users on
the system won't have access to it.
The file
identity.pub contains your public key, which can be added to other system's authorized keys files. We will get to adding keys later.
Exactly the same but with a different public key name (identity.pub VS id_dsa.pub)
Creating a version 2 keypair is much like creating a version 1
keypair.
Except for the fact that the SSH protocol version 2 uses
different encryption algorithms for its encryption.
In this case we can
even choos it ourselves! Huray! To find out which versions are available
on your system I'd advise you to have a look in the ssh-keygen manpage.
In our example we wil create a keypair using dsa encryption. This can
be done by passing the key encryption method type to ssh-keygen. This
is done in the following way :
$ ssh-keygen -t dsa
Which will output the following :
$ ssh-keygen -t dsa
Generating public/private dsa key pair.
Enter file in which to save the key (/home/test/.ssh/id_dsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /home/test/.ssh/id_dsa. Your public key has been saved in /home/test/.ssh/id_dsa.pub. The key fingerprint is: 7b:ab:75:32:9e:b6:6c:4b:29:dc:2a:2b:8c:2f:4e:37 dave@caprice
Again, we will retain the default locations, and we will not use a
passphrase either.
Your keys are stored in the .ssh/ directory in your home directory.
Lets have a look at your keys.
cd ~.ssh; ls -l -rw------- 1 dave dave 526 Nov 3 01:21 id_dsa -rw-r--r-- 1 dave dave 330 Nov 3 01:21 id_dsa.pub
The file
id_dsa contains your version 2 private key.
The file
id_dsa.pub contains your version 2 public key, which can be added to other system's authorized keys file.
Again, I have listed a full ls -l with permissions, make sure you
have the permissions set up correctly, otherwise other users may be able
to snatch it from you. It is also a good idea to give your keys a
non-standard name, since it makes guessing the name of your keypair
files more easy.
To be able to log in to remote systems using your pair of keys,
you will first have to add your public
key on the remote server to the authorized_keys (for version 1) file,
and the authorized_keys2 (for version2) file in the .ssh/ directory in
your home directory on the remote machine.
In our example we will assume you don't have any keys in the
authorized_keys files on the remote server.
(Hint: If you do not have a
remote shell, you can always use your own useraccount on your local
machine as a remote shell (ssh localhost))
First we will upload the public keys to the remote server :
$ cd .ssh/
$ scp identity.pub dave@192.168.1.3:./identity.pub
identity.pub
100% |*****************************************************| 526
$ scp id_dsa.pub dave@192.168.1.3:./id_dsa.pub
identity.pub
100%|*****************************************************| 614
This will place your keys in your home directory on the remote
server. After that we will login on the remote server using ssh or
telnet the conventional way... with a password.
When you are logged in you should create a .ssh directory, and inside
the .ssh/ directory create an authorized_keys and an authorized_keys2
file and add the keys to the files.
Make sure the files are not readable
for other users/groups.
chmod 600 authorized_keys* does the trick.
Adding the public key for version 1 works like this:
$ ssh 192.168.1.3 -v
[I edited out the verbose output, and entered the password]
[Remember kids, always use -v so dont try this at home :) ]
$ mkdir .ssh
$ chmod 700 .ssh
$ cd .ssh
[dave@julia .ssh]$ touch authorized_keys
$ chmod 600 authorized_keys
$ cat ../identity.pub >> authorized_keys
$ rm ../identity.pub
Placing the key for version 2 works about the same :
$ cd .ssh
$ touch authorized_keys2
$ chmod 600 authorized_keys2
$ cat ../id_dsa.pub >> authorized_keys2
$ rm ../id_dsa.pub
Log in using your key
To log in using your key use the ssh command. We will add -1 to make sure we are using SSH Protocol version 1.
ssh -1 -v test@192.168.1.3
This logs you into a system using your version 1 key.
Try it again, now for version 2
ssh -2 -v test@192.168.1.3
Have a look in the output of both ssh logins and you will be able to see some differences between version 1 and 2.
Naturalli under eclipse I put the private key id_dsa, and the known_hosts file to allows the library to connect properly in the way posted before.


Nessun commento:
Posta un commento