Issues with connecting to remote windows machine using Jsch - java

I am currently working on making one Java application which will execute commands (from command prompt) of remotely located Windows machine.
For developing this I have tried following:
Used Jsch library, the application worked well when connected to Unix machines, I was able to get list of processes using 'prstat -a' command, but when I tried with Windows machine, it gave me ConnectException(Timed out)
private final static String HOSTNAME = "SOMECOMPUTERNAME.XXX.XXX.XXX.COM";//
private final static String USERNAME = "SOMEUSERNAME";
private final static String PASSWORD = "SOMEPASSWORD";
private final static int PORT = 22;
public static void main(String[] args) {
JSch jscc = new JSch();
try {
Session session = jscc.getSession(USERNAME, HOSTNAME, PORT);
session.setPassword(PASSWORD);
Properties localProperties = new Properties();
localProperties.put("StrictHostKeyChecking", "no");
session.setConfig(localProperties);
session.connect(60000);
System.out.println("Session connected");
} catch (JSchException e) {
e.printStackTrace();
}
}
The target machine info:
Windows x64 workstation
Latest version of Java installed
Doesn't use any encryption
Please guide into this, Can it be done with Jsch library, if not that which method you can recommend.
Following things you can assume:
I don't want any code in target machine. So a Java application which resides in my workstation and just executes some simple window commands, like dir or start applicationName in the target window machine
I have username and corresponding passwords
I don't have the ipaddress, just a full computer name in format as shown in the code above(HOSTNAME)
Any suggestions are welcomed.
Regards,
icr

Windows does not have SSH installed by default. You will need a SSH client for windows.
I prefer OpenSSH....its free and works perfectly

Related

StrictHostChecking with JSCH API [duplicate]

I'm running a java program where I transfer a file from one folder to another, using Java SFTP. The problem I'm having is that I'm getting the following error in my Java SFTP (using JSch) :
C:\Oracle\Middleware\Oracle_Home\oracle_common\jdk\bin\javaw.exe
-server -classpath C:\JDeveloper\mywork\Java_Hello_World.adf;C:\JDeveloper\mywork\Java_Hello_World\Client\classes;C:\Users\ADMIN\Downloads\jsch-0.1.53.jar
-Djavax.net.ssl.trustStore=C:\Users\IBM_AD~1\AppData\Local\Temp\trustStore5840796204189742395.jks
FileTransfer com.jcraft.jsch.JSchException: UnknownHostKey: 127.0.0.1.
RSA key fingerprint is a2:39:3f:44:88:e9:1f:d7:d1:71:f4:85:98:fb:90:dc
at com.jcraft.jsch.Session.checkHost(Session.java:797) at
com.jcraft.jsch.Session.connect(Session.java:342) at
com.jcraft.jsch.Session.connect(Session.java:183) at
FileTransfer.main(FileTransfer.java:33) Process exited with exit code
0.
The following is my code so far:
FileTransfer fileTransfer = new FileTransfer();
JSch jsch = new JSch();
try {
String host = "127.0.0.1";
int port = 22;
String user = "user";
Session session = jsch.getSession(user, host, port);
session = jsch.getSession("username", "127.0.0.1", 22);
session.connect(); // bug here , java.net.ConnectException
ChannelSftp sftp = null;
sftp = (ChannelSftp)session.openChannel("sftp") ; //channel;
//extra config code
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
// end extra config code
sftp.rename("C:\\Users\\ADMIN\\Desktop\\Work\\ConnectOne_Bancorp\\Java_Work\\SFTP_1\\house.bmp", "C:\\Users\\ADMIN\\Desktop\\Work\\ConnectOne_Bancorp\\Java_Work\\SFTP_2\\house.bmp");
session.disconnect();
} catch (JSchException e) {
e.printStackTrace();
} catch (SftpException e) {
e.printStackTrace();
} //end-catch
My Cygwin is set up, and I checked (with netstat -a -b ) that it's running.
You are trying to skip a host key checking by setting StrictHostKeyChecking to no.
But you have to do that before the checking, i.e. before the session.connect().
Anyway, you should never do this, unless you do not care about security. The host key checking is there to protect you from man-in-the-middle attacks.
Instead, set up an expected host key to let JSch verify it.
For example:
Call JSch.setKnownHosts providing a path to a .ssh/known_hosts-like file.
To generate the .ssh/known_hosts-like file, you can use an ssh-keyscan command from OpenSSH. If you are connecting from a *nix server, you should have the command available, just run
ssh-keyscan example.com > known_hosts
It will have a format like:
example.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA0hVqZOvZ7yWgie9OHdTORJVI5fJJoH1yEGamAd5G3werH0z7e9ybtq1mGUeRkJtea7bzru0ISR0EZ9HIONoGYrDmI7S+BiwpDBUKjva4mAsvzzvsy6Ogy/apkxm6Kbcml8u4wjxaOw3NKzKqeBvR3pc+nQVA+SJUZq8D2XBRd4EDUFXeLzwqwen9G7gSLGB1hJkSuRtGRfOHbLUuCKNR8RV82i3JvlSnAwb3MwN0m3WGdlJA8J+5YAg4e6JgSKrsCObZK7W1R6iuyuH1zA+dtAHyDyYVHB4FnYZPL0hgz2PSb9c+iDEiFcT/lT4/dQ+kRW6DYn66lS8peS8zCJ9CSQ==
And reference the generated known_hosts file in your JSch code.
If you are on Windows, you can get a Windows build of ssh-keyscan from Win32-OpenSSH project or Git for Windows.
Call JSch.getHostKeyRepository().add() to provide the expected host key (e.g. hard-coded, as your other credentials).
See Creating JSch HostKey instance from a public key in .pub format.
jsch version : 0.1.55
my problem solved by running :
ssh-keyscan -t rsa <HOST_NAME> >> ~/.ssh/known_hosts
ssh-keyscan -t rsa <IP_ADDRESS_OF_HOST_NAME> >> ~/.ssh/known_hosts
**in my case jsch was looking for ip address in known_hosts file
jsch.setKnownHosts(System.getProperty("user.home")+"/.ssh/known_hosts");
Aside: by "Cygwin" I assume you mean sshd or sftpd, because Cygwin itself doesn't do SSH.
Anyway, if you want Jsch client to accept any key from the host, move the .setConfig calls that sets StrictHostKeyChecking no so it is before session.connect(). Alternatively you must provide access to a store containing the correct key(s) for your hosts(s) as #Martin explains -- and you should always do that when connecting to anything other than "localhost" or possibly a machine certain to be on the same, physically-secure network segment (such as a wired LAN hub within a single room).

How to determine if tests are running local or on the remote server

According to this tutorial, I am able to upload files on the website while running my tests locally and on the remote server.
As in the tutorial is:
For those of you doing this locally, all you need to do is use the
sendKeys command to type the local path of the file in any file field.
This works like a charm in all drivers. When moving this test to a
remote server (such as, for example, our Selenium 2 Cloud), all you
need to do is use the setFileDetector method to let WebDriver know
that you’re uploading files from your local computer to a remote
server instead of just typing a path.
on the remote server I have to use:
driver.setFileDetector(new LocalFileDetector());
...
upload.sendKeys("/Path/to/image.jpg");
and local just:
upload.sendKeys("/Path/to/image.jpg");
And this all works fine. Only the problem is, that there is no information how to determine if my tests are running local or on the remote server.
I have tried to determine instance of the webDriver:
WebDriver proxiedWebDriver = ((WebDriverFacade) getDriver()).getProxiedDriver();
if (proxiedWebDriver instanceof RemoteWebDriver) {
((RemoteWebDriver)proxiedWebDriver).setFileDetector(new LocalFileDetector());
}
but it seems like both(local and remote) cases are using RemoteWebDriver while running, because in every case I'm passing if condition.
How can I determine if my tests are running local or remote?
To get the address of the remote server you can use HttpCommandExecutor like this:
HttpCommandExecutor ce = (HttpCommandExecutor) ((RemoteWebDriver)driver).getCommandExecutor();
String remoteAddress = ce.getAddressOfRemoteServer().toString();
String localAddress = null;
try (Socket socket = new Socket()) {
socket.connect(new InetSocketAddress("google.com", 80));
localAddress = socket.getLocalAddress().getHostAddress();
} catch (IOException e) {
e.printStackTrace();
}
if (remoteAddress.contains("localhost") || remoteAddress.contains(localAddress)) System.out.println("Local machine");
else System.out.println("Remote machine");
The above code gets the Remote Server address (HUB) and compares it with your public IP address. It should give you the information if you are running local or remote server

Run Oracle Exp command from Java SSH on Remote Server [duplicate]

I have a piece of code which connects to a Unix server and executes commands.
I have been trying with simple commands and they work fine.
I am able to login and get the output of the commands.
I need to run an Ab-initio graph through Java.
I am using the air sandbox run graph command for this.
It runs fine, when I login using SSH client and run the command. I am able to run the graph. However, when I try to run the command through Java it gives me a "air not found" error.
Is there any kind of limit on what kind of Unix commands JSch supports?
Any idea why I'm not able to run the command through my Java code?
Here's the code:
public static void connect(){
try{
JSch jsch=new JSch();
String host="*****";
String user="*****";
String config =
"Host foo\n"+
" User "+user+"\n"+
" Hostname "+host+"\n";
ConfigRepository configRepository =
com.jcraft.jsch.OpenSSHConfig.parse(config);
jsch.setConfigRepository(configRepository);
Session session=jsch.getSession("foo");
String passwd ="*****";
session.setPassword(passwd);
UserInfo ui = new MyUserInfo(){
public boolean promptYesNo(String message){
int foo = 0;
return foo==0;
}
};
session.setUserInfo(ui);
session.connect();
String command="air sandbox run <graph-path>";
Channel channel=session.openChannel("exec");
((ChannelExec)channel).setCommand(command);
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;
page_message=new String(tmp, 0, i);
System.out.print(page_message);
}
if(channel.isClosed()){
if(in.available()>0) continue;
System.out.println("exit-status: "+channel.getExitStatus());
break;
}
try{Thread.sleep(1000);}catch(Exception ee){}
}
channel.disconnect();
session.disconnect();
}
catch(Exception e){
System.out.println(e);
}
}
public static void main(String arg[]){
connect();
}
public String return_message(){
String ret_message=page_message;
return ret_message;
}
public static abstract class MyUserInfo
implements UserInfo, UIKeyboardInteractive{
public String getPassword(){ return null; }
public boolean promptYesNo(String str){ return false; }
public String getPassphrase(){ return null; }
public boolean promptPassphrase(String message){ return false; }
public boolean promptPassword(String message){ return false; }
public void showMessage(String message){ }
public String[] promptKeyboardInteractive(String destination,
String name,
String instruction,
String[] prompt,
boolean[] echo){
return null;
}
}
The "exec" channel in the JSch (rightfully) does not allocate a pseudo terminal (PTY) for the session. As a consequence a different set of startup scripts is (might be) sourced (particularly for non-interactive sessions, .bash_profile is not sourced). And/or different branches in the scripts are taken, based on absence/presence of the TERM environment variable. So the environment might differ from the interactive session, you use with your SSH client.
So, in your case, the PATH is probably set differently; and consequently the air executable cannot be found.
To verify that this is the root cause, disable the pseudo terminal allocation in your SSH client. For example in PuTTY, it's Connection > SSH > TTY > Don't allocate a pseudo terminal. Then, go to Connection > SSH > Remote command and enter your air ... command. Check Session > Close window on exit > Never and open the session. You should get the same "air not found" error.
Ways to fix this, in preference order:
Fix the command not to rely on a specific environment. Use a full path to air in the command. E.g.:
/bin/air sandbox run <graph-path>
If you do not know the full path, on common *nix systems, you can use which air command in your interactive SSH session.
Fix your startup scripts to set the PATH the same for both interactive and non-interactive sessions.
Try running the script explicitly via login shell (use --login switch with common *nix shells):
bash --login -c "air sandbox run sandbox run <graph-path>"
If the command itself relies on a specific environment setup and you cannot fix the startup scripts, you can change the environment in the command itself. Syntax for that depends on the remote system and/or the shell. In common *nix systems, this works:
String command="PATH=\"$PATH;/path/to/air\" && air sandbox run <graph-path>";
Another (not recommended) approach is to force the pseudo terminal allocation for the "exec" channel using the .setPty method:
Channel channel = session.openChannel("exec");
((ChannelExec)channel).setPty(true);
Using the pseudo terminal to automate a command execution can bring you nasty side effects. See for example Is there a simple way to get rid of junk values that come when you SSH using Python's Paramiko library and fetch output from CLI of a remote machine?
For a similar issues, see
Certain Unix commands fail with "... not found", when executed through Java using JSch even with setPty enabled
Commands executed using JSch behaves differently than in SSH terminal (bypasses confirm prompt message of "yes/"no")
JSch: Is there a way to expose user environment variables to "exec" channel?
Command (.4gl) executed with SSH.NET SshClient.RunCommand fails with "No such file or directory"
you could try to find out where "air" resides with
whereis air
and then use this outcome.
something like
/usr/bin/air sandbox run graph
You can use an ~/.ssh/environment file to set your AB_HOME and PATH variables.

Certain Unix commands fail with "... not found", when executed through Java using JSch

I have a piece of code which connects to a Unix server and executes commands.
I have been trying with simple commands and they work fine.
I am able to login and get the output of the commands.
I need to run an Ab-initio graph through Java.
I am using the air sandbox run graph command for this.
It runs fine, when I login using SSH client and run the command. I am able to run the graph. However, when I try to run the command through Java it gives me a "air not found" error.
Is there any kind of limit on what kind of Unix commands JSch supports?
Any idea why I'm not able to run the command through my Java code?
Here's the code:
public static void connect(){
try{
JSch jsch=new JSch();
String host="*****";
String user="*****";
String config =
"Host foo\n"+
" User "+user+"\n"+
" Hostname "+host+"\n";
ConfigRepository configRepository =
com.jcraft.jsch.OpenSSHConfig.parse(config);
jsch.setConfigRepository(configRepository);
Session session=jsch.getSession("foo");
String passwd ="*****";
session.setPassword(passwd);
UserInfo ui = new MyUserInfo(){
public boolean promptYesNo(String message){
int foo = 0;
return foo==0;
}
};
session.setUserInfo(ui);
session.connect();
String command="air sandbox run <graph-path>";
Channel channel=session.openChannel("exec");
((ChannelExec)channel).setCommand(command);
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;
page_message=new String(tmp, 0, i);
System.out.print(page_message);
}
if(channel.isClosed()){
if(in.available()>0) continue;
System.out.println("exit-status: "+channel.getExitStatus());
break;
}
try{Thread.sleep(1000);}catch(Exception ee){}
}
channel.disconnect();
session.disconnect();
}
catch(Exception e){
System.out.println(e);
}
}
public static void main(String arg[]){
connect();
}
public String return_message(){
String ret_message=page_message;
return ret_message;
}
public static abstract class MyUserInfo
implements UserInfo, UIKeyboardInteractive{
public String getPassword(){ return null; }
public boolean promptYesNo(String str){ return false; }
public String getPassphrase(){ return null; }
public boolean promptPassphrase(String message){ return false; }
public boolean promptPassword(String message){ return false; }
public void showMessage(String message){ }
public String[] promptKeyboardInteractive(String destination,
String name,
String instruction,
String[] prompt,
boolean[] echo){
return null;
}
}
The "exec" channel in the JSch (rightfully) does not allocate a pseudo terminal (PTY) for the session. As a consequence a different set of startup scripts is (might be) sourced (particularly for non-interactive sessions, .bash_profile is not sourced). And/or different branches in the scripts are taken, based on absence/presence of the TERM environment variable. So the environment might differ from the interactive session, you use with your SSH client.
So, in your case, the PATH is probably set differently; and consequently the air executable cannot be found.
To verify that this is the root cause, disable the pseudo terminal allocation in your SSH client. For example in PuTTY, it's Connection > SSH > TTY > Don't allocate a pseudo terminal. Then, go to Connection > SSH > Remote command and enter your air ... command. Check Session > Close window on exit > Never and open the session. You should get the same "air not found" error.
Ways to fix this, in preference order:
Fix the command not to rely on a specific environment. Use a full path to air in the command. E.g.:
/bin/air sandbox run <graph-path>
If you do not know the full path, on common *nix systems, you can use which air command in your interactive SSH session.
Fix your startup scripts to set the PATH the same for both interactive and non-interactive sessions.
Try running the script explicitly via login shell (use --login switch with common *nix shells):
bash --login -c "air sandbox run sandbox run <graph-path>"
If the command itself relies on a specific environment setup and you cannot fix the startup scripts, you can change the environment in the command itself. Syntax for that depends on the remote system and/or the shell. In common *nix systems, this works:
String command="PATH=\"$PATH;/path/to/air\" && air sandbox run <graph-path>";
Another (not recommended) approach is to force the pseudo terminal allocation for the "exec" channel using the .setPty method:
Channel channel = session.openChannel("exec");
((ChannelExec)channel).setPty(true);
Using the pseudo terminal to automate a command execution can bring you nasty side effects. See for example Is there a simple way to get rid of junk values that come when you SSH using Python's Paramiko library and fetch output from CLI of a remote machine?
For a similar issues, see
Certain Unix commands fail with "... not found", when executed through Java using JSch even with setPty enabled
Commands executed using JSch behaves differently than in SSH terminal (bypasses confirm prompt message of "yes/"no")
JSch: Is there a way to expose user environment variables to "exec" channel?
Command (.4gl) executed with SSH.NET SshClient.RunCommand fails with "No such file or directory"
you could try to find out where "air" resides with
whereis air
and then use this outcome.
something like
/usr/bin/air sandbox run graph
You can use an ~/.ssh/environment file to set your AB_HOME and PATH variables.

How to access data from cassandra installed on CENTOS server from windows?

my casssndra is installed in CENTOS server and i want to access the data of that data base from my own system . i've witten web service for that but i dont know how to connect it from my windows system . any body knows how to do that ??
public class Dbconnection {
public static Session connector(String CASSANDRA_HOST , int CASSANDRA_PORT ,String CASSANDRA_KEYSPACE){
static Cluster cluster;
static Session session;
try {
cluster = Cluster.builder().addContactPoint(CASSANDRA_HOST).withPort(CASSANDRA_PORT).build();
session = cluster.connect(CASSANDRA_KEYSPACE);
}
catch (Exception e){
System.out.println("INVALID CONNECTION STRING");
}
if(session!=null)
System.out.println("Connection Opened Successfully at "+CASSANDRA_HOST+":"+CASSANDRA_PORT+" With Workspace "+CASSANDRA_KEYSPACE);
return session;
}public static void main(String[] args)
Session session=Dbconnection.connector("192.168.30.17" ,9042,'temperature');}
instead of "197.168.30.17" when i put localhost it gets connected to locally installed cassandra .
but it not getting connected to cassndrawhich i've installed on Centos server .(IP:192.168.30.17)
Can you check if you can reach the server running cassandra from your system?
Also check if the firewall in the machine running cassandra is allowing traffic for that port?

Categories