How to get server's SSH version without authenticating in JSch? - java

I tried to use JSch:
#Test
public void test() throws Exception {
var session = new JSch().getSession("host");
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
var version = session.getServerVersion();
System.out.println("version = " + version);
}
but I'm getting
java.lang.NullPointerException: Cannot read the array length because "str" is null
It seems that this implementation requires you to connect and authenticate.
How can I get this information with Java, without the need to authenticate?
This Python code works for me on a server that requires authentication yet I didn't have to authenticate in order to get the remote version.
import paramiko
ssh = paramiko.Transport(("host", 22))
ssh.start_client()
print(ssh.remote_version)
ssh.close()

The SSH identification string is sent in plain text right after opening the connection.
So you do not need an SSH library to obtain the string.
You can do with a simple code like shown here:
Read Data from a Java Socket
Or just try to login using dummy credentials with JSch and then read Session.getServerVersion.
You do not even have to try to login. You can abort the connection right at the host key check:
config.put("StrictHostKeyChecking", "yes");

Related

Can't connect to corporate machine with SSH JCraft JSch

I've got a problem with connecting to corporate machine with SSH using JCraft JSch.
public static void main(String[] args) throws JSchException {
JSch jSch = new JSch();
String username = "username";
String host = "host";
int port = 22;
jSch.addIdentity("Path\\to\\key\\file");
jSch.setKnownHosts("known_hosts");
/* In known_hosts file, I've got Host IP, and public key,
the same that's on server
*/
Session session = jSch.getSession(username,host,port);
Properties config = new Properties();
config.put("StrictHostKeyChecking","yes");
session.setConfig(config);
session.connect(5000);
}
That's my code, after running it, there is an error: HostKey has been changed: [host adress], if i change StrictHostKeyChecking to no, another error appears: Auth fail.
I can connect to that machine via PuTTy or WinSCP, and I dont need to use tunneling. Also the key format is right(I made that mistake allready). When I connect to the machine via PuTTy, I need to pick the right machine(there are 5), and each of them has their own key pair, and the main connection to the "menu", has also it's own key pair, it's CAPI key.
Does anyone had something like that before? Also I made a forwarding port, and tried to connect with that, but I'm not sure how it works. Can anyone tell me how to do the port forwarding, or maybe somebody has another idea.
Thanks in advice

FTPSClient, What values to give for Remote and Local

I am new to FTPSClient i trying to connect to a FTPS created in my laptop. i don't exactly what some of the methods working and their parameter meaning.
For example,
In my code i have created a FTPSClient as below:
FTPSClient ftps =new FTPSClient();
Then connected to a server use connect() method with ip address.
ftps.connect("172.xx.xx.xxx");
After every step i will check the reply code using.
ftps.getReplyCode();
In the below code i know that
username = system username
password = the password to login
ftps.login(username, password);
In the my system in Internet Information Service(IIS). Created an ftp server with ssl and given the below directory to share.
C:\Users\karan-pt2843\Desktop\FTPS
Want to send the file in below directory to the server.
D:\sam.txt
Now i want to store a file in the server in the given above directory and i tried using
remote="";
local="";
InputStream input;
input = new FileInputStream(local);
ftps.storeFile(remote, input);
input.close();
I don't know what value to give for remote and local. please help me with the values to give on them and the what happens internal.
// Use passive mode as default because most of us are
// behind firewalls these days.
ftps.enterLocalPassiveMode();
...
String remote = "samFromClient.txt"; //Place on FTP
String input = "D:/sam.txt" //Place on your Client
//Your FTP reads from the inputstream and store the file on remote-path
InputStream input = new InputStream(new FileInputStream(input));
ftps.storeFile(remote, input);
input.close();
ftps.logout();
...
Taken from: Apache example

Why is Jsch asking for Kerberos username? [duplicate]

So I'm writing a little program that needs to connect to a remote server through SFTP, pull down a file, and then processes the file. I came across JSch through some answers here and it looked perfect for the task. So far, easy to use and I've got it working, with one minor thing I'd like to fix. I'm using the following code to connect and pull the file down:
JSch jsch = new JSch();
Session session = null;
try {
session = jsch.getSession("username", "127.0.0.1", 22);
session.setConfig("StrictHostKeyChecking", "no");
session.setPassword("password");
session.connect();
Channel channel = session.openChannel("sftp");
channel.connect();
ChannelSftp sftpChannel = (ChannelSftp) channel;
sftpChannel.cd(REMOTE_FTP_DIR);
sftpChannel.lcd(INCOMING_DIR);
sftpChannel.get(TMP_FILE, TMP_FILE);
sftpChannel.exit();
session.disconnect();
} catch (JSchException e) {
e.printStackTrace();
} catch (SftpException e) {
e.printStackTrace();
}
So this works and I get the file. I'm running this code on a linux server and when I run the code JSch asks me for my Kerberos username and password. It looks like:
Kerberos username [george]:
Kerberos password for george:
I just hit enter for both questions and then the program seems to continue on with no problems. However I need this code to be automated through a cron task and so I'd rather not having it pausing the program to ask me these two questions. Is there something I'm not supplying it so that it won't ask this? Something I need to do to stop it asking? Hopefully someone has some ideas. Thanks.
Thought I'd post an answer here since in case anyone else ends up running into a similar issue. Turns out I am missing a piece of code that makes all the difference. I just needed to add
session.setConfig("PreferredAuthentications",
"publickey,keyboard-interactive,password");
before
session.connect();
and everything works perfectly now.
While the solution in the self-accepted answer is correct, it lacks any explanation.
The problem is that the OP have a Kerberos/GSSAPI authentication set as the preferred (the JSch default). Yet OP does not seem to actually use/want it, as OP claims not to specify any username or password for the Kerberos prompts.
This problem can appear spontaneously, when either Kerberos gets installed on the the client PC or the server starts to support Kerberos.
The solution is to remove the Kerberos/GSSAPI (gssapi-with-mic) from the list of preferred authentication methods in JSch:
session.setConfig(
"PreferredAuthentications", "publickey,keyboard-interactive,password");
All answers are correct, I'll just add here the way it can be done for Spring Integration when trying to integrate with an SFTP server.
So, if you are using SFTP Spring Integration and the weird user and password for Kerberos is prompting in the same way the OP is asking.
Then modify your Spring configuration (I'm using Java Spring Integration config, if you are using XML config you can try to translate it yourself - I really don't like XML config :P ):
So in the bean you are using as SessionFactory you need to add this change in config:
#Bean
public SessionFactory<LsEntry> sftpSessionFactory() {
DefaultSftpSessionFactory factory = new DefaultSftpSessionFactory(true);
factory.setHost("hostname");
factory.setPort(22);
factory.setUser("username");
factory.setPassword("superstrongpassword");
factory.setAllowUnknownKeys(true);
factory.setSessionConfig(buildSessionProperties());
return new CachingSessionFactory<>(factory);
}
/**
* Build JSch property PreferredAuthentications without "gssapi-with-mic"
* This way it won't prompt for Kerberos authentication every time it tries to connect
* to the SFTP.
*/
private Properties buildSessionProperties() {
Properties sessionProperties = new Properties();
sessionProperties.setProperty("PreferredAuthentications", "publickey,keyboard-interactive,password");
return sessionProperties;
}

Using JSCH Java [duplicate]

This question already has answers here:
Skipping Kerberos authentication prompts with JSch [duplicate]
(2 answers)
Closed 7 years ago.
I am trying to use JsCH for connecting to a remote server and then manipulate PostgreSQL.
Everything going fine if I use PUTTY and also with JSCH.
My only problem is the JsCH only accepts username and password from the Eclipse console even if I set these properties.
public void connect() {
//
int assigned_port;
final int local_port=5432;
// Remote host and port
final int remote_port=5432;
final String remote_host="myserver011";
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("companyusername", 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);
System.out.println("SSH Connection succes!");
} catch (JSchException e) {
e.printStackTrace();
LOGGER.log(Level.SEVERE, e.getMessage()); return;
}
if (assigned_port == 0) {
LOGGER.log(Level.SEVERE, "Port forwarding failed !");
return;
}
}
But the console still needs the username and password.
Kerberos username [myusername]: companyusername <---- here I set again the username
Kerberos password for companyusername : password <---- and the password
SSH Connection succes!
Opened database successfully
And then everything works. But I don't want to set these again, and I cant find anywhere the source of this "bug"?! I don't know, maybe it's a server config parameter to force the user to manually give the input?
Any advice or hint would be great.
//this works pretty well for me.
Session session;
ssh = new JSch();
session = ssh.getSession(username,hostname,port);
session.setConfig(config);
session.setPassword(password);
session.setConfig("StrictHostKeyChecking","no");
session.connect();

Secure FTP using private key authentication in java

import com.jcraft.jsch.*;
import com.jcraft.jsch.JSchException;
import oracle.jdbc.driver.OracleDriver;
import java.io.*;
import java.util.*;
import java.sql.*;
import java.net.*;
public class SecureFTP {
public static void main(String[] args) throws IOException , ClassNotFoundException, JSchException, SftpException{
JSch jsch = new JSch();
File file = new File("/home/xxxxx/.ssh/id_rsa");
Session session = null;
URL keyFileURL = null;
URI keyFileURI = null;
if (file.exists())
{
keyFileURL = file.toURL();
if (keyFileURL == null)
{
System.out.println("what");
throw new RuntimeException("Key file not found in classpath");
}
}
else System.out.println("FIle not found");
try{
keyFileURI = keyFileURL.toURI();
}
catch(Exception URISyntaxException)
{
System.out.println("Wrong URL");
}
String privateKey = ".ssh/id_rsa";
//jsch.addIdentity(privateKey);
jsch.addIdentity(new File(keyFileURI).getAbsolutePath());
System.out.println(new File(keyFileURI).getAbsolutePath() + " LOL");
session = jsch.getSession("username", "servername");
//session.setPassword("password");
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
// connect
session.connect();
// get SFTP channel
Channel channel = session.openChannel("sftp");
channel.connect();
ChannelSftp schannel = (ChannelSftp) channel;
FileInputStream fis = new FileInputStream(sourcefile);
schannel.put(fis, destinationfile );
fis.close();
}
schannel.exit();
session.disconnect();
}
}
As you can see from the code I have commented out, I have tried everything possible to get this working and the only thing that works is if I set the password directly. I am trying to use the RSA private key generated, but I keep getting an auth fail.
I have added the public key to the list of authorized keys on the target server. And there is no passphrase.
Is there something else I am supposed to do? Like say, while generating the keys? Is there a step I am missing?
Is there another library I can use to implement the same function?
Make sure the necessary files exist (id_rsa and id_rsa.pub on the client, authorized_keys on the server). Make sure you can use public key authentication with another tool, like ssh, using these files.
If that looks alright, the problem may be with your Java security provider. Read on if you think you have the right files in place.
There are different formats for RSA private key storage, and SSH uses one that is not standard. Most providers expect something called a CRT RSA key, and when JSch doesn't give them a key in that format, they raise an exception which JSch silently eats and goes on to the next authentication method.
What is your provider? The following snippet will help you find out:
import java.security.KeyFactory;
…
KeyFactory f = KeyFactory.getInstance("RSA");
System.out.println(f.getProvider().getName());
Update: I did some checking around, and as of Java 5, the SunPKCS11 provider is installed with the highest precedence on Solaris systems, for performance. Since I don't run Solaris, I can't test it, but I believe this may be causing the problem.
JSch doesn't allow you to specify the provider to use for this operation through its API, so you will have to change the precedence of the installed providers. In fact, I'd suggest trying to remove the SunPKCS11 from this application; run this code once when your application starts up:
Security.removeProvider("SunPKCS11-Solaris");
Have you have copied the key into the file $HOME/.ssh/authorized_keys on the target server? If so, you should probably mention that. If not, that is required for this to work. Also, are you generating the key without a password? If the private key is password protected, you will need to provide that password to addIdentity.
After verifying those things, I'd recommend trying to connect via the command line using OpenSSH, as the Java code you have here looks correct. If the command line does not work, invoke it with -vvv to get verbose output about what it is doing. It is possible that the server is configured with PubkeyAuthentication set to no.

Categories

Resources