I am trying to execute remote commands on an SSHServer running on my local windows machine.
I am able to run simple command like "whoami" but failing to run something like "java -version" or "dir"
Here is my code so far, can you tell where I am going wrong?
SSHServer.java
import org.apache.sshd.common.file.virtualfs.VirtualFileSystemFactory;
import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.server.SshServer;
import org.apache.sshd.server.auth.password.PasswordAuthenticator;
import org.apache.sshd.server.channel.ChannelSession;
import org.apache.sshd.server.command.Command;
import org.apache.sshd.server.command.CommandFactory;
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
import org.apache.sshd.server.scp.ScpCommandFactory;
import org.apache.sshd.server.shell.InteractiveProcessShellFactory;
import org.apache.sshd.server.shell.ProcessShellCommandFactory;
import org.apache.sshd.server.shell.ProcessShellFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
public class SSHServer {
private SshServer sshServer;
private static final Logger logger = LoggerFactory.getLogger(SSHServer.class);
public SSHServer(int port) {
sshServer = SshServer.setUpDefaultServer();
initializeServer(port);
}
private void initializeServer(int port) {
sshServer.setPort(port);
sshServer.setKeyPairProvider(new SimpleGeneratorHostKeyProvider());
sshServer.setFileSystemFactory(getFileSystemFactory());
sshServer.setCommandFactory(getScpCommandFactory());
sshServer.setPasswordAuthenticator(getPasswordAuthenticator());
sshServer.setShellFactory(getProcessShellFactory());
//sshServer.setSessionHeartbeat(SessionHeartbeatController.HeartbeatType.IGNORE, TimeUnit.SECONDS, 5);
}
public int getPort() {
return sshServer.getPort();
}
public String getHost() {
return sshServer.getHost();
}
public void startServer() throws IOException {
sshServer.start();
logger.debug("SSHServer started on Port: {}", sshServer.getPort());
}
public void stopServer() throws IOException {
sshServer.stop();
logger.debug("SSHServer stopped...");
}
private ScpCommandFactory getScpCommandFactory() {
CommandFactory myCommandFactory = new CommandFactory() {
@Override
public Command createCommand(ChannelSession channelSession, String s) {
logger.info("Command on SSHServer: {}", s);
return null;
}
};
return new ScpCommandFactory.Builder().withDelegate(new ProcessShellCommandFactory()).build();
}
private VirtualFileSystemFactory getFileSystemFactory() {
return new VirtualFileSystemFactory() {
@Override
public Path getUserHomeDir(SessionContext session) {
String userHomeDir = System.getProperty("user.home");
return Paths.get(userHomeDir);
}
};
}
private PasswordAuthenticator getPasswordAuthenticator() {
return (username, password, serverSession) -> {
logger.info("authenticating user: {}", username);
return true;
};
}
private ProcessShellFactory getProcessShellFactory() {
return new InteractiveProcessShellFactory();
}
}
SSHClient.java
import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.future.ConnectFuture;
import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.common.file.virtualfs.VirtualFileSystemFactory;
import org.apache.sshd.common.session.SessionContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
public class SSHClient {
private SshClient sshClient;
private String username;
private String host;
private String password;
private int port;
private static final Logger logger = LoggerFactory.getLogger(SSHClient.class);
private SSHClient(){}
public SSHClient(String username, String password, String host, int port) {
logger.info("Creating SSHClient for username: {} for {}:{}", username, host, port);
sshClient = SshClient.setUpDefaultClient();
sshClient.setFileSystemFactory(new VirtualFileSystemFactory() {
@Override
public Path getUserHomeDir(SessionContext session) {
return Paths.get(System.getProperty("user.home"));
}
});
this.username = username;
this.password = password;
this.host = host;
this.port = port;
}
public ClientSession connect() throws IOException {
ConnectFuture connectFuture = sshClient.connect(username, host, port).verify();
logger.info("SSHClient is connected: {}", connectFuture.isConnected());
return connectFuture.getSession();
}
public void startClient() {
sshClient.start();
logger.info("SSHClient is started...");
}
public void stopClient() {
sshClient.stop();
logger.info("SSHClient is stopped...");
}
}
TestSSH.java
import org.apache.sshd.client.channel.ClientChannel;
import org.apache.sshd.client.channel.ClientChannelEvent;
import org.apache.sshd.client.session.ClientSession;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.EnumSet;
import java.util.concurrent.TimeUnit;
public class TestSSH {
public static void main(String[] args) throws IOException {
SSHServer sshServer = new SSHServer(null, 45018);
sshServer.startServer();
SSHClient sshClient = new SSHClient("", "", "localhost", 45018);
sshClient.startClient();
ClientSession clientSession = sshClient.connect();
clientSession.addPasswordIdentity("randompassword");
System.out.println(clientSession.auth().verify().isSuccess());
ClientChannel execChannel = clientSession.createChannel(ClientChannel.CHANNEL_EXEC, "whoami");
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayOutputStream err = new ByteArrayOutputStream();
execChannel.setOut(out);
execChannel.setErr(err);
execChannel.open().await(1, TimeUnit.SECONDS);
Collection<ClientChannelEvent> waitMask = execChannel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED), 10000);
waitMask.forEach(event -> System.out.println(event.name()));
System.out.println(execChannel.getExitStatus());
byte[] errBytes = err.toByteArray();
byte[] outBytes = out.toByteArray();
System.out.println(new String(outBytes, StandardCharsets.UTF_8));
System.out.println(new String(errBytes, StandardCharsets.UTF_8));
/* Scanner scanner = new Scanner(System.in);
scanner.nextInt();*/
sshServer.stopServer();
System.out.println("Exiting");
System.exit(0);
}
}
here is the output for "whoami":
2020-07-24 19:22:44,267 DEBUG c.w.v.g.s.SSHServer [main] SSHServer started on Port: 45018
2020-07-24 19:22:44,278 INFO c.w.v.g.s.SSHClient [main] Creating SSHClient for username: for localhost:45018
2020-07-24 19:22:44,369 INFO c.w.v.g.s.SSHClient [main] SSHClient is started...
2020-07-24 19:22:44,713 INFO c.w.v.g.s.SSHClient [main] SSHClient is connected: true
2020-07-24 19:22:45,835 INFO c.w.v.g.s.SSHServer [sshd-SshServer[41d477ed](port=45018)-nio2-thread-3] authenticating user:
true
CLOSED
EOF
EXIT_STATUS
OPENED
0
properOutputhere
2020-07-24 19:22:46,969 DEBUG c.w.v.g.s.SSHServer [main] SSHServer stopped...
Exiting
Process finished with exit code 0
here is the output when I try to execute "dir" using:
ClientChannel execChannel = clientSession.createChannel(ClientChannel.CHANNEL_EXEC, "dir");
output:
2020-07-24 19:25:20,128 DEBUG c.w.v.g.s.SSHServer [main] SSHServer started on Port: 45018
2020-07-24 19:25:20,140 INFO c.w.v.g.s.SSHClient [main] Creating SSHClient for username: for localhost:45018
2020-07-24 19:25:20,237 INFO c.w.v.g.s.SSHClient [main] SSHClient is started...
2020-07-24 19:25:20,566 INFO c.w.v.g.s.SSHClient [main] SSHClient is connected: true
2020-07-24 19:25:21,453 INFO c.w.v.g.s.SSHServer [sshd-SshServer[33d512c1](port=45018)-nio2-thread-3] authenticating user:
true
TIMEOUT
OPENED
null
2020-07-24 19:25:31,539 DEBUG c.w.v.g.s.SSHServer [main] SSHServer stopped...
Exiting
Process finished with exit code 0