Can we use JSch for SSH key-based communication? - java

I am using JSch for sftp communication, now i want to use facilitate the key-based authentication, key is loaded on client and server machine once by my network team and all later communication would be only user based for which we have loaded the key.
sftp -oPort=10022 jmark#192.18.0.246
as tjill#192.18.0.135
like this command work fine and connect to the sftp, how i can achieve this functionality programmatically.
if it is not possible using JSch, please suggest some other library. I came across Apache SSHD.

It is possible. Have a look at JSch.addIdentity(...)
This allows you to use key either as byte array or to read it from file.
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
public class UserAuthPubKey {
public static void main(String[] arg) {
try {
JSch jsch = new JSch();
String user = "tjill";
String host = "192.18.0.246";
int port = 10022;
String privateKey = ".ssh/id_rsa";
jsch.addIdentity(privateKey);
System.out.println("identity added ");
Session session = jsch.getSession(user, host, port);
System.out.println("session created.");
// disabling StrictHostKeyChecking may help to make connection but makes it insecure
// see http://stackoverflow.com/questions/30178936/jsch-sftp-security-with-session-setconfigstricthostkeychecking-no
//
// java.util.Properties config = new java.util.Properties();
// config.put("StrictHostKeyChecking", "no");
// session.setConfig(config);
session.connect();
System.out.println("session connected.....");
Channel channel = session.openChannel("sftp");
channel.setInputStream(System.in);
channel.setOutputStream(System.out);
channel.connect();
System.out.println("shell channel connected....");
ChannelSftp c = (ChannelSftp) channel;
String fileName = "test.txt";
c.put(fileName, "./in/");
c.exit();
System.out.println("done");
} catch (Exception e) {
System.err.println(e);
}
}
}

Related

Simple Socks over SSH tunnel in Andorid Java

I need to setup a socks proxy (tunnel) over ssh in android with java (android studio). I searched a lot but I couldn't find any solutions. This is my code:
int assigned_port;
int local_port=8588;
int remote_port=22;
String remote_host = "server";
String login = "root";
String password = "password";
try {
JSch jsch = new JSch();
// Create SSH session. Port 22 is your SSH port which
// is open in your firewall setup.
Session session = jsch.getSession(login, remote_host, 22);
session.setPassword(password);
// Additional SSH options. See your ssh_config manual for
// more options. Set options according to your requirements.
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
// config.put("Compression", "yes");
config.put("ConnectionAttempts","2");
session.setConfig(config);
// Connect
session.connect();
// Create the tunnel through port forwarding.
// This is basically instructing jsch session to send
// data received from local_port in the local machine to
// remote_port of the remote_host
// assigned_port is the port assigned by jsch for use,
// it may not always be the same as
// local_port.
assigned_port = session.setPortForwardingL(local_port,
remote_host, remote_port);
} catch (JSchException e) {
System.out.println("JSch:" + e.getMessage());
return;
}
if (assigned_port == 0) {
System.out.println("Port forwarding failed!");
return;
}
There is no error but it didn't work. I need a simple code of socks tunneling.

password protected zip file issue

User upload the file, i need to password protect the file and then zip it put in a storage server which is different from the server where my code is running. So i use AESEncrypter to encrypt the file and jcraft.jsch.ChannelSftp to transfer the file to the server.
public ResponseEntity<ResponseWrapper> uploadFile(#RequestParam("uploads") MultipartFile file) throws Exception {
FileOutputStream fos = new FileOutputStream("outputfile.zip");
AESEncrypter aesEncrypter = new AESEncrypterBC();
aze=new AesZipFileEncrypter(fos, aesEncrypter);
aze.add(file.getOriginalFilename(), file.getInputStream(), "test123");
JSch ssh = new JSch();
Session session = ssh.getSession("username", "Servername", 22);
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.setPassword("*****");
session.connect();
Channel channel = session.openChannel("sftp");
channel.connect();
sftp = (ChannelSftp) channel;
sftpChannel.put(file.getInputStream(), "/storedfiles/outputfile.zip");
}
File is getting transferred to the server, but when i download that transferred file and try to open it says "Errors were found opening ".." you cannot extract file.. do you want to fix the problems". Not sure why i am getting this issue, also it creates a file in local server, which line is causing that?
I tried replacing this line
aze=new AesZipFileEncrypter(fos, aesEncrypter);
with
aze=new AesZipFileEncrypter("outputfile.zip", aesEncrypter);
but dint work.
I placed the file in remote server, read that in output stream and then password protected, solved my issue.
public ResponseEntity<ResponseWrapper> uploadFile(#RequestParam("uploads") MultipartFile file) throws Exception {
JSch ssh = new JSch();
Session session = ssh.getSession("username", "Servername", 22);
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.setPassword("*****");
session.connect();
Channel channel = session.openChannel("sftp");
channel.connect();
sftp = (ChannelSftp) channel;
OutputStream os = sftp.put("/storedfiles/outputfile.zip");
AESEncrypter aesEncrypter = new AESEncrypterBC();
aze=new AesZipFileEncrypter(os, aesEncrypter);
aze.add(file.getOriginalFilename(), file.getInputStream(), "test123");
if(aze != null) {
aze.close();
}
}

How to use a command-line *nix command that needs an interactive terminal over JSch SSH session in Java?

I'm trying to create code in java that sends SMS using GSM modem through minicom package that I tested successfully in Linux.
Right know I'm using JSch library to SSH and use minicom. I've successfully tested this code with normal Linux commands.
import java.io.InputStream;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
public class SSHCommandExecutor {
/**
* #param args
*/
public static void main(String[] args) {
String host="localhost";
String user="root";
String password="XXXXX";
String command1="minicom";
try{
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
JSch jsch = new JSch();
Session session=jsch.getSession(user, host, 22);
session.setPassword(password);
session.setConfig(config);
session.connect();
System.out.println("Connected");
Channel channel=session.openChannel("exec");
((ChannelExec)channel).setCommand(command1);
channel.setInputStream(null);
((ChannelExec)channel).setErrStream(System.err);
InputStream in=channel.getInputStream();
channel.connect();
byte[] tmp=new byte[1024];
while(true){
while(in.available()>0){
int i=in.read(tmp, 0, 1024);
if(i<0)break;
System.out.print(new String(tmp, 0, i));
}
if(channel.isClosed()){
System.out.println("exit-status: "+channel.getExitStatus());
break;
}
try{Thread.sleep(1000);}catch(Exception ee){}
}
channel.disconnect();
session.disconnect();
System.out.println("DONE");
}catch(Exception e){
e.printStackTrace();
}
}
}
But the problem is that I can't send commands to minicom it will output this:
No cursor motion capability (cm)
I believe it need terminal environment and I don't want to use terminal emulator in Java. I just want to send command to minicom through Java code.
Is there any way I could do this?
PS: I've tried other possibilities to solve this using smslib but it couldn't work properly in Linux cause of the rxtx and other solutions. Right now only minicom works properly.
If the problem is indeed that the command does not start on a non-interactive terminal, yet it does not really need any interactivity, you can simply make the "exec" channel "interactive" by using .setPty(true) call.
channel.setPty(true);
channel.connect();

How to send password in command using ssh command

I am using Jsch library to connect with my server. After connecting i am passing command which require password to proceed further hence i am passing my password in command only but nothing happens.
Code:
JSch jsch = new JSch();
jsch.removeAllIdentity();
Session session = jsch.getSession(user, host, port);
session.setPassword(password);
.setConfig("StrictHostKeyChecking", "no");
session.setConfig("PubkeyAuthentication", "no");
System.out.println("Establishing Connection...");
session.setConfig("PreferredAuthentications",
"publickey,keyboard-interactive,password");
session.connect();
System.out.println("Connection established.");
System.out.println("Crating SFTP Channel.");`
Channel shellChannel = session.openChannel("shell");
shellChannel.connect();
((ChannelShell) shellChannel).setPty(true);
shellChannel.setInputStream(System.in);
shellChannel.setOutputStream(System.out);
PrintStream shellStream = new PrintStream(
shellChannel.getOutputStream());
shellChannel.connect();
shellStream
.println("cd /usr/local/apache2/; ls; cd ../www; ls; git fetch origin; <mypasssword>");
shellStream.flush();
System.out.println("SFTP Channel created.");`
When i run this code git ask password to proceed further.
Note: i cannot disable password for git fetch origin.
I tried your code to access my linux box - it does log in successfully, but then fails to send any commands. I'm not sure if that's the problem you are having - but I will add my solution here, just in case.
Moved the shellStream.println(); command to its own function:
public static void sendCommand(String c) {
shellStream.print(c + "\n");
shellStream.flush();
}
Had to make shellChannel and shellStream global variables in the process.
Changed shellStream.println(); to shellStream.print("\n");, as the aforementioned refused to work.
After this line of your code:
shellStream = new PrintStream(shellChannel.getOutputStream());
Added my command sequence:
Thread.sleep(1000); // wait for it to connect
sendCommand("sudo su"); // the command I tried
Thread.sleep(1000); // not sure how long you need to wait
sendCommand("mypassword");
Thread.sleep(1000);
// etc.
By the way, you are calling shellChannel.connect(); twice in your code - I removed the last one.
Here's the final working version of your code:
import java.io.IOException;
import java.io.PrintStream;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelShell;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
public class MyShell {
static String user = "daniel";
static String host = "localhost";
static int port = 22;
static String password = "mypass";
static Session session;
static Channel shellChannel;
static PrintStream shellStream;
public static void main(String[] args) throws JSchException, IOException,
InterruptedException {
JSch jsch = new JSch();
jsch.removeAllIdentity();
session = jsch.getSession(user, host, port);
session.setPassword(password);
session.setConfig("StrictHostKeyChecking", "no");
session.setConfig("PubkeyAuthentication", "no");
System.out.println("Establishing Connection...");
session.setConfig("PreferredAuthentications",
"publickey,keyboard-interactive,password");
session.connect();
System.out.println("Connection established.");
System.out.println("Crating SFTP Channel.");
shellChannel = session.openChannel("shell");
shellChannel.connect();
((ChannelShell) shellChannel).setPty(true);
shellChannel.setInputStream(System.in);
shellChannel.setOutputStream(System.out);
shellStream = new PrintStream(shellChannel.getOutputStream());
Thread.sleep(1000);
sendCommand("sudo su");
Thread.sleep(1000);
sendCommand("mypass");
Thread.sleep(1000);
sendCommand("ls");
}
public static void sendCommand(String c) {
shellStream.print(c + "\n");
shellStream.flush();
}
}
session.setConfig("PreferredAuthentications", "publickey,keyboard-interactive,password");
Keyboard-interactive here mean the password must be tipped with a keyboard. SSH is quite peaky about that, even if there's ways to pass a password through the command line.
The best way would be to use a pubkey auth, but if that's not a option, try to login using only password
session.setConfig("PreferredAuthentications", "password");
Also you may just send the password using
session.setPassword("password");

JSchException: Auth fail and fingerprint

I'm trying to connect to my SFTP server from a Java script.
I'm using JSch lib for my purpose. Username, password and hostname are correct but I obtain an: Auth fail error.
I've also tried to add the following lines before session.connect(), but the problem still remains.
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
What do I have to put inside knownhosts.txt? The fingerprint of my server key?
public static void upload(ArrayList<File> a) {
try{
JSch jsch = new JSch();
jsch.setKnownHosts("knownhosts.txt");
Session session = jsch.getSession("username", "hostname", 22);
session.setPassword("mypassword");
session.connect();
Channel channel = session.openChannel("sftp");
channel.connect();
ChannelSftp channelSftp = (ChannelSftp) channel;
channelSftp.cd("/var/www/");
for(File object: a){
channelSftp.put(new FileInputStream(object), object.getName(), channelSftp.OVERWRITE);
}
channelSftp.exit();
session.disconnect();
} catch (Exception ex) {
ex.printStackTrace();
}
}
Do you have some advices? Thanks in advance!
Does your network/SMTP server support IP6? If your client has IP6 support, later versions of Java default to IP6, but many SMTP servers are configured on IP4. See this article here for Sending email using JSP for directions on configuring your JVM to force IP4. This needs to be set on the JVM as it is instantiated.

Categories