How to check whether user exists in Linux (JSch) - java

I am connecting/creating users in Linux machine using JSch. I am successfully able to connect Linux machine and create users. But i'm not able to check whether that user already exists or not in machine, while creating user. For this i tried command: id -u name
And my implementation is:
System.out.println("Connected");
Channel channel=session.openChannel("exec");
((ChannelExec)channel).setCommand("id -u name");
channel.setInputStream(null);
((ChannelExec)channel).setErrStream(System.err);
InputStream in=channel.getInputStream();
channel.connect();
But it doesn't tell whether its true or false. How to do this using JSch to check whether user exists in Linux?.

You are reading the InputStream that will have the user's id if you are asking for an existing user, but if you are asking for a user that is not in the system, the output will be written in the error stream. If you want to read one stream, you could modify your command to print the exit status of the last command executed.
session.connect();
ChannelExec channel = (ChannelExec) session.openChannel("exec");
channel.setCommand("id -u name; echo $?");
channel.connect();
The output if you ask for an exist user will have 2 lines, the first one will be the user's id, and the second one will be 0 that means executed successfully, if the user doesn't exists the content of the stream will be different of 0 that means command failed to execute.

Related

How to figure out if a command executed using JSch in Java has successfully completed?

I am not able to figure out whether a command has completed its execution or not before sending the next command using the JSch library in Java.
Code snippet
// Opens a new channel of type 'exec'
Channel channel = sesConnection.openChannel("exec");
// sets the command to be executed
((ChannelExec) channel).setCommand(command);
// Gets an input stream for this channel
InputStream commandOutput = channel.getInputStream();
channel.connect();
When executing commands, there are two sources you can use to decide if the command failed:
Command exit code. That's Channel.getExitStatus in JSch. Note that the method returns an actual exit code, once the command finishes only.
Command error output. That's Channel.getExtInputStream in JSch.
For an example how to read both, see How to read JSch command output?

Provide inputs to individual prompts separately with JSch

The problem is that the SSH connection requires the provision of another userid and password info after the general log in.
I am using JSch to connect to the remote server. It takes input in the form of a InputStream. And this InputStream can only be passed once. This causes problems as the session is interactive.
I've tried passing the input stream as linefeed separate values ("username\npassword\n"). This however does not work. Any suggestions would be welcome. Even if I have to look for a new Java library altogether.
try {
JSch jsch=new JSch();
Session session=jsch.getSession( "username1", "host", 22);
session.setPassword("password1");
session.setConfig("StrictHostKeyChecking", "no");
session.connect(30000);
Channel channel=session.openChannel("shell");
String data = "username2\npassword2\n";
channel.setInputStream(new ByteArrayInputStream(data.getBytes()));
channel.setOutputStream(System.out);
channel.connect(3*1000);
} catch (Exception e) {
e.printStackTrace();
}
The password is not entered properly and it does not navigate to the next set of instruction displayed by the ssh connection.
However, if I try the same with the system console (System.in) as the input stream, it works as expected.
If I understand your question correctly, it looks like the password is provided too quickly and the way the server is implemented, it discards the input that comes too early (before a prompt).
You may need to wait before sending the password.
channel.connect();
OutputStream out = channel.getOutputStream();
out.write(("username2\n").getBytes());
out.flush();
Thread.sleep(1000);
out.write(("password2\n").getBytes());
out.flush();
A more advanced solution would be to implement an Expect-like functionality.

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

Change file permissions with SFTP or SCP uing JSch

I have a user account, but on trying using this am getting exception for rssh. Is there any possibility to give permission of directory using other way other than ChannelExec. Based on the exception I come to know this account can't use ChannelExec to give permission of a directory or file. Thus is there any other way this account could give file permission without getting access to this user account for rssh. Please give you thoughts.
Code :
channelSftp = (ChannelSftp) channel;
ChannelExec channelexe = (ChannelExec) session.openChannel("exec");
channelexe.setCommand("chmod 777 -R " + depDir);
channelexe.connect();
System.out.println("channelexe.getExitStatus:"+channelexe.getExitStatus());
Output :
channelexe.getExitStatus:-1:
This account is restricted by rssh.
Allowed commands: scp sftp
If you believe this is in error, please contact your system administrator.
There's no need to use the "exec" channel for this.
Use the ChannelSftp.chmod:
public void chmod(int permissions, String path)
Note that the method takes the permissions as an integer. So you cannot use 777, as that's an octal representation of the permissions.
An equivalent decimal representation is 511 (= 7*8^2 + 7*8^1 + 7*8^0).
See also Decimal to Octal Conversion.
Though the ChannelSftp.chmod cannot set permissions recursively. The SFTP protocol does not support recursive operations of any kind.

How to run and display the result of a shell command ssh with JSch?

I try to use the library JSch - Java Secure Channel make an ssh connection in my Android app, it works.
Now I would like to execute a command and retrieve the result.
I tried several methods that works best is this. However, this method works only in part, because for some reason I can not explain, my program stops at the end of my while loop, yet I'm the result of the command that appears in my log.
Here is my code :
public static String executeRemoteCommand(String username, String password, String hostname, int port) throws Exception {
JSch jsch = new JSch();
Session session = jsch.getSession(username, hostname, port);
session.setPassword(password);
// Avoid asking for key confirmation
Properties prop = new Properties();
prop.put("StrictHostKeyChecking", "no");
session.setConfig(prop);
session.connect();
Channel channel = session.openChannel("shell");
channel.connect();
DataInputStream dataIn = new DataInputStream(channel.getInputStream());
DataOutputStream dataOut = new DataOutputStream(channel.getOutputStream());
// send ls command to the server
dataOut.writeBytes("ls\r\n");
dataOut.flush();
// and print the response
String line = dataIn.readLine();
String result = line + "\n";
while ((line = dataIn.readLine()) != null) {
result += line + "\n";
Log.i("TAG", "Line: "+line);
}
dataIn.close();
dataOut.close();
channel.disconnect();
session.disconnect();
return result;
}
Does anyone else have a better way to run a command sheel with JSch?
Thank you in advance !
Your method stops in the loop (instead of finishing it) because the remote shell doesn't close the output stream.
It has no reason to do this, since there you could send more commands.
If you only want to execute a single command (or a series of commands known before), you shouldn't use a Shell channel, but an "exec" channel.
This way the remote shell (which executes your command) will finish when your command is finished, and then the server will close the stream. So your loop will finish, and then you can close the streams.
If you think you need a shell channel (for example, if you need to fire up multiple commands in the same context, and react to one's output before deciding what would be the next one), you'll need some way to know when one command is finished (e.g. by recognizing the prompt), and then send the next one. To quit, either close the output stream or send a "logout" or "exit" command (both work with any standard unix shell, other shells might need different commands), then the remote site should close the other stream, too.
By the way, while disabling strict host key checking is convenient, it also opens up your connection to a man-in-the-middle attack, and in case of password authentication, the attacker can grab your password. The right way to do this would be to set up a correctly initialized host key repository to recognize the remote host's key.
As far as I am aware JSch is the only real option.
I have found that Jsch errors tend to take some digging. But in the first instance you will want to catch and print out the errors as a minimum.
try{
JSch jsch = new JSch();
Session session = jsch.getSession(username, hostname, port);
... omitted
} catch (Exception e) {
System.out.println(e)
}
also have a look a the example code on the site

Categories