Convert from FTP to SFTP - java

I have the below code which works for FTP. How do I make it to work for SFTP
((ChannelExec) channel).setCommand(cmd);
channel.setXForwarding(true);
channel.setInputStream(System.in);
InputStream in=channel.getInputStream();
channel.connect();
return in;
I know that I need to use ChannelSftp instead of Channel class, but I get type cast error in the setcommand line.
Cannot cast type ChannelSftp to ChannelExec

The first thing to understand is SFTP is different than FTP or FTP/s. SFTP works off of SSH whereas FTP/s uses SSL.
That being said, JSCH provides a pretty straight forward way to use SFTP, including setting X forwarding. Take a look at the examples as well as the linked question from mabbas.
Based upon your comment, it appears that you actually want a remote shell to be invoked/executed against, try the following to see if it'll do what you need:
//connect to the remote shell
Channel channel=session.openChannel("shell");
((ChannelShell)channel).setAgentForwarding(true);
channel.setInputStream(System.in); //Send commands here
channel.setOutputStream(System.out); //output responses here
channel.connect();
You won't be able to use ChannelSftp as it does not have a setCommand or exec method

If you're using JSCH, they have several example programs which illustrate how to use the library. The SFTP client example illustrates how to open an SFTP session.
Session session=jsch.getSession(user, host, port);
...
session.connect();
Channel channel=session.openChannel("sftp");
channel.connect();
ChannelSftp c=(ChannelSftp)channel;
That's all you have to do. ChannelSftp contains functions to send and receive files, get file listings, and so on. You don't have to access the channel's input or output streams.

Related

channelExec.setCommand() Not Working when executing shell commands

I'm executing .sh file in a remote server and it is not working properly. For that i used JSch and java. and this is how i tried.
ChannelExec channelExec = (ChannelExec) session.openChannel("exec");
InputStream in = channelExec.getInputStream();
channelExec.setCommand("cd /home");
Here is a full example http://myitlearnings.com/java-code-to-run-a-remote-script-on-remote-host-using-ssh/ .
Add this below statement, so the security measure is by passed // By default StrictHostKeyChecking is set to yes as a security measure.
session.setConfig("StrictHostKeyChecking", "no");
Add full code base (ip not required while sharing the code) and error message received. Add Proper exception handling, so we will get to know what is the error you are getting and can assist better

JSch SFTP code hangs when tranferring a file

My task is to copy some files from server to local, I have searched a lot about connectivity libraries and found JSch. I have used below code but it is taking too much time to read or move the file. I don't know whether it is working or not.
JSch jsch = new JSch();
Session session = null;
try {
// set up session
session = jsch.getSession("userName","hostIP");
// use private key instead of username/password
session.setConfig(
"PreferredAuthentications",
"publickey,gssapi-with-mic,keyboard-interactive,password");
jsch.addIdentity("***.ppk");
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
// copy remote log file to localhost.
ChannelSftp channelSftp = (ChannelSftp) session.openChannel("sftp");
channelSftp.connect();
channelSftp.setInputStream(System.in);
channelSftp.setOutputStream(System.out);
System.out.println("shell channel connected....");
ChannelSftp c = (ChannelSftp) channelSftp;
System.out.println("done");
channelSftp.get("report.xml", "C:\\Users\\akrishnan");
channelSftp.exit();
} catch (Exception e) {
e.printStackTrace();
} finally {
session.disconnect();
}
Is there any library that I can use to connect the servers from my Java code using private key file (**.ppk)?
This is most likely, what causes the hang:
channelSftp.setInputStream(System.in);
channelSftp.setOutputStream(System.out);
Doing that for an "sftp" channel breaks everything. It makes no sense. Just remove those two lines.
Check the official JSch SFTP example – There are no such calls.
For a correct code for file transfers using JSch, see:
SFTP file transfer using Java JSch.
Obligatory warning: Do not use StrictHostKeyChecking=no to blindly accept all host keys. That is a security flaw. You lose a protection against MITM attacks.
For a correct (and secure) approach, see:
How to resolve Java UnknownHostKey, while using JSch SFTP library?

JSCH to write to named pipe

I'm trying to write to write to a named pipe over a connection facilitated by jsch.
// connect to server
JSch ssh = new JSch();
JSch jsch = new JSch();
Session session = jsch.getSession(user, host, port);
session.setPassword(password);
session.setConfig("StrictHostKeyChecking", "no");
System.out.println("Establishing Connection...");
session.connect();
System.out.println("Connection established.");
System.out.println("Crating SFTP Channel.");
ChannelSftp sftpChannel = (ChannelSftp) session.openChannel("sftp");
sftpChannel.connect();
System.out.println("SFTP Channel created.");
// write to pipe
OutputStream strm = sftpChannel.put(remoteFile);
// failed attempts
// BufferedWriter wrtr = new BufferedWriter(new PrintWriter(new OutputStreamWriter(strm)));
// PrintWriter wrtr = new PrintWriter(new BufferedOutputStream(strm));
// Current version
BufferedWriter wrtr = new BufferedWriter(new PrintWriter(strm));
wrtr.write("hello world");
wrtr.flush();
session.disconnect();
sftpChannel.disconnect();
wrtr.close();
The connect to server part is essentially an exact copy from: SSH connection with Java
The code will even wait for something to be reading the pipe on the other side, meaning that if I don't use:
cat pipe
It will wait till I do so, and then once I have it will print out nothing and the cat pipe call will be over. Essentially it appears that I'm writing "" to the pipe instead of "hello world"
Any help would be much appreciated, thanks.
I suspect that if you talked to any SFTP server software author, he'd tell you that interacting with named pipes through SFTP isn't supported, and that you're on your own. Having said that, you could try requesting append mode for the put operation:
OutputStream strm = sftpChannel.put(remoteFile, ChannelSftp.APPEND);
^^^^^^^^^^^^^^^^^^
BufferedWriter wrtr = new BufferedWriter(new PrintWriter(strm));
wrtr.write("hello world");
It might work, or it might not. It depends on the SFTP server.
At the protocol level, an SFTP write request specifies what file to write to, where in the file to write it, and what data to write. Based on the the OpenSSH 5.8 source code that I have at hand, that version of the SFTP server program will always seek to the correct location in the file before writing data to it. Pipes don't support seeking, so the sftp-server program would report a seek failure to the client without trying to write the data.
However, the OpenSSH 6.6 version of sftp-server will omit the seek if the file was opened in append mode. I haven't tested it, but it may be possible to write to a named pipe using that version of the server, if the client requests append mode for the file in the first place. And by extension, it may work for some other versions of the OpenSSH server as well.

How to create a bot that simulate an SSH shell user interaction?

I'm trying to realize a bot that simulates an user that write/read on a ssh console in Java.
I'm using the JSCH library to manage the ssh connection.
This is the code from which I started:
JSch jsch = new JSch();
Session session = jsch.getSession(username, ipAddress, port);
session.setPassword(password);
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect(connectionTimeoutInMillis);
Channel channel = session.openChannel("shell");
InputStream is = new InputStream();
OutputStream out= new OutputStream();
channel.setInputStream(is);
channel.setOutputStream(out);
channel.connect();
channel.disconnect();
is.close();
out.close();
session.disconnect();
Obviously the InputStream and OutputStream in the code are wrong, I need to use something that the bot can use to send a String (a command line) and to receive a String(the result of the command execution), what type of streams should I use to obtain this?
Furthermore I noticed that if I send a command and use the System.out as output stream in many cases the output is empty because (I'm almost sure about this) the Java application terminates before that the command execution has produced the result. What is the best practice to tell to JSCH channel listener "wait till the command execution has completed" and then go on? I could use a Thread.sleep(someTime) after the command execution but I don't like much it for obvious reasons.
Consider using a third-party Expect-like Java library to ease the interaction with a remote shell. Here is a good set of options you can try:
Expect4J
ExpectJ
Expect-for-Java
You can also take a look at my own open source project which I created some time ago as the successor to the existing ones. It's called ExpectIt. The advantages of my library are stated on the project home page.
Here is an example of interacting with a public remote SSH service using JSch. It should be easy to adopt it for your use case.
JSch jSch = new JSch();
Session session = jSch.getSession("new", "sdf.org");
session.connect();
Channel channel = session.openChannel("shell");
Expect expect = new ExpectBuilder()
.withOutput(channel.getOutputStream())
.withInputs(channel.getInputStream(), channel.getExtInputStream())
.withErrorOnTimeout(true)
.build();
try {
expect.expect(contains("[RETURN]"));
expect.sendLine();
String ipAddress = expect.expect(regexp("Trying (.*)\\.\\.\\.")).group(1);
System.out.println("Captured IP: " + ipAddress);
expect.expect(contains("login:"));
expect.sendLine("new");
expect.expect(contains("(Y/N)"));
expect.send("N");
expect.expect(regexp(": $"));
expect.send("\b");
expect.expect(regexp("\\(y\\/n\\)"));
expect.sendLine("y");
expect.expect(contains("Would you like to sign the guestbook?"));
expect.send("n");
expect.expect(contains("[RETURN]"));
expect.sendLine();
} finally {
session.close();
ssh.close();
expect.close();
}
Here is the link to the complete workable example.

Setting ASCII mode in Jsch

I need to overcome a Unix - Windows file format (LF to CRLF) issue I'm currently having.
The ftp client I am using is Jsch from Jcraft.
The documentation online is very bare, although I have come across a flag that can be set
SSH_FXF_TEXT_MODE
that enables ASCII mode, but I don't see where I should set this in the code itself, nor do I see it mentioned in these Javadocs
Below is my own attempt at a workaround.
The "Newly Added" line shows how I take the file and convert it to an ASCII encoded string, which I then transfer across using the channelSftp put method.
Originally I would have just put the file itself across.
final JSch jsch = new JSch();
final Session session = jsch.getSession(username, host);
session.setPassword(password);
session.connect();
final Channel channel = session.openChannel("sftp");
channel.connect();
final ChannelSftp channelSftp = (ChannelSftp) channel;
channelSftp.cd(destDir);
File file = new File(pathName);
String content = FileUtils.readFileToString(file, "US-ASCII"); // Newly Added
channelSftp.put(content, fileToTransfer.getName());
Please note that I omitted exception handling and other practices just for clarity of the code snippet.
Will this workaround succeed, or will Jsch's seemingly default binary mode override the ASCII encoded string and transfer it as usual?
I will test it, I was just wondering if any of you could tell straight off?
Or indeed knew how/where to set the Text_Mode flag! :)
Also, the version of Jsch I am using is jsch-0.1.49.jar.
The text mode flag was added to SFTP protocol version 4. Jsch currently supports SFTP protocol version 3, which doesn't specify a text-mode flag.
You can see a list of SFTP specification revisions here. The RFC for protocol version 3 is here. Note that OpenSSH, the most widely used SFTP server, only supports protocol version 3 as well, and doesn't support line terminator conversion. So having the flag in Jsch wouldn't be very useful.

Categories