I want to transfer file from windows to unix(linux) box using Java, then change to super user. I tried using the JSCH library, that is SFTP with java.
I am stuck at the step to change to super user.
The steps i followed are similar to how to transfer a file through SFTP in java?
I know similar questions have been asked, but i am not able to change user using this approach.
Request to please do not mark this as duplicate.
Can anyone help me with the steps, or any other approach? An example would be helpful for the same. Thanks in advance.
Edit-1 - sample snippet from the link how to transfer a file through SFTP in java?, which is used as a reference posted
public void send (String fileName) {
String SFTPHOST = "host:IP";
int SFTPPORT = 22;
String SFTPUSER = "username";
String SFTPPASS = "password";
String SFTPWORKINGDIR = "file/to/transfer";
Session session = null;
Channel channel = null;
ChannelSftp channelSftp = null;
System.out.println("preparing the host information for sftp.");
try {
JSch jsch = new JSch();
session = jsch.getSession(SFTPUSER, SFTPHOST, SFTPPORT);
session.setPassword(SFTPPASS);
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
System.out.println("Host connected.");
channel = session.openChannel("sftp");
channel.connect();
System.out.println("sftp channel opened and connected.");
channelSftp = (ChannelSftp) channel;
channelSftp.cd(SFTPWORKINGDIR);
File f = new File(fileName);
channelSftp.put(new FileInputStream(f), f.getName());
log.info("File transfered successfully to host.");
} catch (Exception ex) {
System.out.println("Exception found while tranfer the response.");
}
finally{
channelSftp.exit();
System.out.println("sftp Channel exited.");
channel.disconnect();
System.out.println("Channel disconnected.");
session.disconnect();
System.out.println("Host Session disconnected.");
}
}
With this, i am able to connect to the remote system, but cannot change the user.
Edit-2 : On doing some more research, i could find that using SFTP with JSCH api can help me transfer the file, but not change user. If i change the Channel to 'exec', i can change the user, but both do not work in same session. So both do not work simultaneously.
Is there any another way (SSH, SCP transfer perhaps?)
So the question remains unsolved - Want to transfer file and change user through Java.
Related
I am trying to copy files from one remote server to another remote. I tried to use scp. It's copying the files through putty but not through the code. I am currently using echo to copy the files. With echo I am writing a string finalStr to abc.bcc its working fine. But when using below command in Jsch its not working.
scp /home/abc.bcc user#host:/folder1/folder2/abc.bcc
I tried adding ssh public private keys but no luck. I tried with channel.setPty(true) to avoid password prompt and setting the password through bufferedWriter. But still unable to copy the files. Please suggest what needs to be changed.
JSch jsch = new JSch();
Session session;
try {
session = jsch.getSession("user", "host", 22);
session.setPassword("password");
session.setConfig("PreferredAuthentications", "publickey,keyboard-interactive,password");
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
logger.info("Connection status: " + session.isConnected());
Channel channel = session.openChannel("exec");
((ChannelExec) channel).setCommand(
"echo \"" + finalStr + "\" >> /folder1/folder2/abc.bcc");
((ChannelExec) channel).setPty(false);
channel.setInputStream(null);
((ChannelExec) channel).setErrStream(System.err);
InputStream in = channel.getInputStream();
OutputStream out = channel.getOutputStream();
channel.connect();
logger.info("Channel status : " + channel.isConnected());
out.write("\n".getBytes());
out.flush();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line;
int index = 0;
while ((line = br.readLine()) != null) {
logger.info(++index + " : " + line);
}
channel.disconnect();
session.disconnect();
}catch(....
Debug output:
debug1: Trying private key: /home/build_path/.ssh/id1
debug3: no such identity: /home/build_path/.ssh/id1: No such file or directory
debug1: Trying private key: /home/build_path/.ssh/id2
debug3: no such identity: /home/build_path/.ssh/id2: No such file or directory
debug1: Trying private key: /home/build_path/.ssh/id3
debug3: no such identity: /home/build_path/.ssh/id_3: No such file or directory
The log looks like user home is not set correctly! So it doesnt find the key files!
General approach:
get the ssh to work without the code.
to copy from one remote to another requires the hostnames and connections to be resolved on both remotes for each other. so login to one remote and try the ssh connection from there directly to the other remote. This is not guaranteed to work.
I am pretty sure once you have this resolved you get everything else working.
When proxies are involved this can get quite complicated as the proxy settings have to work correctly between all 3 machines.
I am facing those issues repeatedly and it can be very messy.
I'm developing java program to connect with windows server over ssh. For this I used jcraft on java. And the ssh server is copSSH. The implementation throws
Error: com.jcraft.jsch.JSchException: Algorithm negotiation fail
error on java. At the same time it shows
fatal: Unable to negotiate with 192.168.28.111: no matching cipher
found. Their offer: aes128-cbc,3des-cbc,blowfish-cbc [preauth]
on CopSSH.
Java code block
public void sshExecPassword(String host, String USERNAME, String PASSWORD, String command) {
App objApp = new App();
int port = 22;
try {
/**
* Create a new Jsch object This object will execute shell commands
* or scripts on server
*/
JSch jsch = new JSch();
/*
* Open a new session, with your username, host and port Set the
* password and call connect. session.connect() opens a new
* connection to remote SSH server. Once the connection is
* established, you can initiate a new channel. this channel is
* needed to connect to remotely execution program
*/
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
Session session = jsch.getSession(USERNAME, host, port);
session.setConfig(config);
session.setPassword(PASSWORD);
session.connect();
// create the excution channel over the session
ChannelExec channelExec = (ChannelExec) session.openChannel("exec");
// Gets an InputStream for this channel. All data arriving in as
// messages from the remote side can be read from this stream.
InputStream in = channelExec.getInputStream();
// Set the command that you want to execute
// In our case its the remote shell script
String str = command;
channelExec.setCommand(str);
channelExec.connect();
// Read the output from the input stream we set above
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
// retrieve the exit status of the remote command corresponding to
// this channel
int exitStatus = channelExec.getExitStatus();
// Safely disconnect channel and disconnect session. If not done
// then it may cause resource leak
channelExec.disconnect();
session.disconnect();
if (exitStatus < 0) {
System.out.println("Done, but exit status not set! " + exitStatus);
objApp.writeLogs("120","Done, but exit status not set! ");
} else if (exitStatus > 0) {
System.out.println("Done, but with error!");
objApp.writeLogs("120","Done, but with error!");
} else {
System.out.println("Done!");
objApp.writeLogs("121","SSH connection successful");
}
} catch (Exception e) {
System.err.println("Error: " + e);
final StringWriter sw = new StringWriter();
final PrintWriter pw = new PrintWriter(sw, true);
e.printStackTrace(pw);
objApp.writeLogs("120", sw.getBuffer().toString());
}
}
And the CopSSH host following versions
OpenSSH_7.1p2, OpenSSL 1.0.2e 3 Dec 2015
Can any one suggest a fix for it?
That happens due to lacking support for legacy ciphers in more recent releases of OpenSSH. Check this Copssh FAQ for a solution. Background information can also be found here.
Latest jcraft jar fix the issue
I was trying to build an small code where I want to create some string and transfer that string to a file (that should be created in runtime) located in remote server. In my case the remote server is Linux.
Can someone help me here? I was using a JSCH and ChannelSftp but unable to do the thing. Below is my code:
JSch jsch = new JSch();
session = jsch.getSession(SFTPUSER, MachineIP, SFTPPORT);
String str = "Hello";
session.setPassword(SFTPPASS);
System.out.println(SFTPPASS);
java.util.Properties config = new java.util.Properties();
System.out.println("Config done");
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
System.out.println("Config set");
session.connect();
System.out.println("Session connected");
channel = session.openChannel("sftp");
channel.connect();
System.out.println("Connection Opened\n");
channelSftp = (ChannelSftp) channel;
channelSftp.cd(SFTPWORKINGDIR);
File f=new File("Test.txt");
//unable to do anything beyond this.
Sorry if you find this stupid but I am very new to it.
ChannelSftp has versions of the put method which accept a filename on the remote system and which return an OutputStream. Anything written to the OutputStream is written to the file on the remote system. You can write binary data to an OutputStream, or convert it to a Writer if you want to write text to it:
try (OutputStream out = channelSftp.put("/some/remote/file")) {
OutputStreamWriter writer = new OutputStreamWriter(out);
writer.write("some text");
} catch (IOException e) {
....
}
#Kenster answer doesn't work for me (get a 0 bytes file), so I gets another solution:
String content = "some text";
InputStream stream = new ByteArrayInputStream (content.getBytes ());
sftpChannel.put (stream, "/some/remote/file");
Hope it'll help somebody...
I have windows machine with running ssh server. I know the path on that machine. Let it be D:/Folder1/Folder2. I'm creating sftp channel using JSCH. But when i try to cd to D:/Folder1/Folder2, "No such file: 2" error is throwed.
can anyone please help? May be i need to convert path?
the problem is the path. It is not finding the file to rename, if you are using the JSCH library you can use
channelSftp.pwd ()
to know the current location.
Example:
Sftp sftp = new Sftp();
sftp.conectar();
ChannelSftp channelSftp = sftp.getChannelSftp();
channelSftp.rename(channelSftp.pwd()+"//"+file,`channelSftp.pwd()`+"//"+"new_dir//"+file);
//or
String url = channelSftp.pwd();
String url_m = channelSftp.pwd()+"/"+directory;
channelSftp.rename(url+file,url_m+file)
I've solved the problem by using ChannelExec by opening exec channel. This worked for me. Hope will work for others too.
...
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
JSch ssh = new JSch();
session = ssh.getSession(sshSolrUsername, sshSolrHost, 22);
session.setConfig(config);
session.setPassword(sshSolrPassword);
session.connect();
channel = session.openChannel("exec");
((ChannelExec)channel ).setCommand("cd " + sourcePath);
exec.setInputStream(null);
((ChannelExec)channel ).setErrStream(System.err);
InputStream in = channel .getInputStream();
channel .connect();
int status = checkStatus(channel , in);
channel.disconnect();
...
I suggest you to read your file in inpuStream, then use the function:
put(InputStream src, String dst)
doc: https://epaul.github.io/jsch-documentation/simple.javadoc/com/jcraft/jsch/ChannelSftp.html
Example:
String fileName = "D:/Folder1/Folder2";
File initialFile = new File(fileName);
InputStream targetStream = new FileInputStream(initialFile);
channelSftp.put(targetStream, "./in/");
I'm trying to use Jsch to establish an SSH connection in Java.
I have set "StrictHostKeyChecking" to yes. I understand that the hostkey of the server has to be obtained before hand and store in the hostkey file
before the first attempt to connect to the server. How can I get the HostKey of the server. My code produces the following exception:
com.jcraft.jsch.JSchException: UnknownHostKey: ASY-PC
RSA key fingerprint is 22:fb:ee:fe:18:cd:aa:9a:9c:78:89:9f:b4:78:75:b4
How can I make connection with StrictHostKeyChecking Yes.
Here is my code.
package sshexample;
import com.jcraft.jsch.*;
import java.io.*;
public class SSHexample
{
public static void main(String[] args)
{
String user = "user";
String password = "password";
String host = "192.168.100.103";
int port=22;
try
{
JSch jsch = new JSch();
Session session = jsch.getSession(user, host, port);
session.setPassword(password);
session.setConfig("StrictHostKeyChecking", "yes");
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();
}catch(Exception e) {
e.printStackTrace();
}
}
You have to supply a KnownHostKeys file by calling following function
jsch.setKnownHosts(new FileInputStream(knownHostsFile));
this file should have all the the known hosts' fingerprints separated by new lines.
for example
hostname,10.1.1.120, ssh-rsa AAAAC3NzaC1yc2EAAAADAQABAAABAQCi5b647581SwC0uUDQw1ENjKSz3rhJMRRZEgIjHylvF4fbuAEzj645YoAf9SItb51MhetFAJrq98jYsHpedSm3IoMG+aR/P1CjsBz1RtJKlfR2NfYDCZ7Dyx11P8FnJbwbYif/GeG0xEujekwF1pyL0tNPmf0H4/GPR4mwrv/llGlB3Lo3BzxrGtl4f4X/oSHDoo7FrQkDwqOfeSM++3vPPHxyVO5zhFJ5u9f7M/uuxUeHS+YS5JWAI7NLXKgbiM9dluGzZU/6Awo3ux4x5ojL+kf29JEVxK+o6GfW2bIW+LhgIGZNThnN5nHzBVfNNHvQ7KC5ic0h2z2gbVpwJr1h
you can obtain this key from server by using any sftp client however following command may help if you are using linux or unix
ssh-keyscan -t rsa 10.1.1.120
After a few minutes of testing i found a solution for this. If you don't want to use the default knownHost File, just create your own
This how the file could look:
192.168.0.1 ssh-rsa
AAAAC3NzaC1yc2EAAAADAQABAAABAQCi5b647581SwC0uUDQw1ENjKSz3rhJMRRZEgIjHylvF4fbuAEzj645YoAf9SI
tb51MhetFAJrq98jYsHpedSm3IoMG+aR/P1CjsBz1RtJKlfR2NfYDCZ7Dyx11P8FnJbwbYif
/GeG0xEujekwF1pyL0tNPmf0H4/GPR4mwrv/llGlB3Lo3BzxrGtl4f4X
/oSHDoo7FrQkDwqOfeSM++3vPPHxyVO5zhFJ5u9f7M/uuxUeHS+YS5JWAI7NLXKgbiM9dluGzZU
/6Awo3ux4x5ojL+kf29JEVxK+o6GfW2bIW+LhgIGZNThnN5nHzBVfNNHvQ7KC5ic0h2z2gbVpwJr1h
And all those entries are separated by new lines. You get the RSA key that you want by asking your session:
session=null;
com.jcraft.jsch.Channel channel =null;
try{
ssh=new JSch();
ssh.setKnownHosts("test");
session=ssh.getSession(userTextField.getText(),ip,22);
session.setPassword(passwordField1.getText());
System.out.println(session.getHostKey());
session.connect();
channel=session.openChannel("sftp");
channel.connect();
ChannelSftp sftp=(ChannelSftp) channel;
System.out.println(sftp.getHome());
for (Object o : sftp.ls(sftp.getHome())) {
System.out.println(((ChannelSftp.LsEntry)o).getFilename());
}
} catch (JSchException e1) {
e1.printStackTrace();
addHost(session.getHostKey().getKey());
} catch (SftpException e1) {
e1.printStackTrace();
}
}
private void addHost(String key){
try {
FileWriter tmpwriter=new FileWriter("test",true);
tmpwriter.append(ip + " ssh-rsa " + key+"\n");
System.out.println(ip + " ssh-rsa " + key);
tmpwriter.flush();
tmpwriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
So session.getHostKey().getKey() is what you want to call to get the key.
You also need to call session.connect(); before you ask for the key and handle it in the catch.
As most the of the answers suggest you have to provide know host file but fail to address how to get it. You simply need to SSH to the host.
Eg ssh user#192.168.100.103
when prompted provide password. For first time connection it will you to save the hosts ssh key fingerprint. Once you are connected you can find your known_host file at
user/.ssh/known_hosts
For me on windows path is C:\Users\athakur\.ssh\known_hosts. You can directly use this file. Or edit the file and pick up entry from it corresponding to your IP address which would look something like
192.168.100.103 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA1UsgiLH5hjIScZlqPA4kNhPoXAX00mMv65N8qTvYd1D1M5DwWtTTcxK4w0wGKKVA7RERzWbtjPpSomJwT1LofZr+qafLdiEvhirIXVYHSWZqp6zTJW0jzk3p07ugjoHV3YUWKDzOaiFuOMslt8hD7pZv8nhOYfxBZdsVHdukYRP8MADXC0ZgOD5ZYZ0EglaQJYPG7n73PSMZWZT/oafUcx6bFiRF4QsXaguWuu6umX9gaV7VvoyMJg+kxPAKnGDFY7If61AG7vAchUUhlQ44SB1FFr25y+qeUg2NGqAxH/Z/ZAfvZ+pDv3Cd9s+KCnEIqxyxY/sPQ2zCvwf0Z9fTeQ==
Note : Host machines SSH fingerprint (based on hosts public key that you can find at /etc/ssh/ssh_host_rsa_key.pub) may change in SSH is reinstalled in that machine. Or you may encounter MIM attack (even it is for testing sake). In such cases you will have to pick new entry in same way mentioned above.
Maybe it's no more relevant but in my case, the similar problem was happened with docker-compose.yml in container, that was build from spring-boot application that 100 % worked locally
config-service:
image: <host>/<bla>-config-service:<version>
hostname: config-service
ports:
- 3000:3000
depends_on:
- discovery
environment:
- CONSUL_HOST=discovery
- CONSUL_PORT=<port>
- CONFIG_GIT_URI=git#<host>:<group>/<repository>.git
- CONFIG_GIT_BRANCH=development
volumes:
- ~/.ssh/:/root/.ssh/:ro
Solution was to apply hack on ~/.ssh folder.
chcon -Rt svirt_sandbox_file_t ~/.ssh
After that I suppose volumes was correctly mapped between docker container and local machine, and described exception was gone.
Based on #nothing-to-know answer, the following method can be very handy:
public static String getHostKey(String hostName, int port, String userName, char[] password) {
JSch ssh;
Session session = null;
String hostKey = "";
try {
ssh = new JSch();
session = ssh.getSession(userName, hostName, port);
session.setPassword(new String(password));
if (session.getHostKey() != null) {
hostKey = session.getHostKey().getHost() + " " + session.getHostKey().getType() + " " + session.getHostKey().getKey();
}
session.connect();
} catch (JSchException e1) {
hostKey = session.getHostKey().getHost() + " " + session.getHostKey().getType() + " " + session.getHostKey().getKey();
} finally {
session.disconnect();
return hostKey;
}
}