diff --git a/conf/replies.properties b/conf/replies.properties
new file mode 100644
index 0000000..677cdfd
--- /dev/null
+++ b/conf/replies.properties
@@ -0,0 +1,7 @@
+hello=hello
+5BAABD7C4581F90088133C0E945302C2=\t0\t0\t0 -
+uname=Linux
+9DD46246144D353C914D7572AEDF8EA6=Linux mail.vidconnect.cyou 4.15.0-70-generic #79-Ubuntu SMP Tue Nov 12 10:36:10 UTC 2019 aarch64 aarch64 aarch64 GNU/Linux
+whoami=appadmin
+4DE8A3B5E72E54D9D2A70BD43CB5EA9E=Model:\t\t0
+99EFF9F4022855955653078ECB2B4CE4=1.9G
diff --git a/conf/springboot.yml b/conf/springboot.yml
index a4628de..2f8d567 100644
--- a/conf/springboot.yml
+++ b/conf/springboot.yml
@@ -2,3 +2,5 @@ ssh-server:
port: 1022
private-key:
location: "conf/private.key"
+ automatic-replies:
+ location: "conf/replies.properties"
diff --git a/pom.xml b/pom.xml
index 94c531f..f91ee9d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
4.0.0
com.example.sshd
echo-sshd-server
- 1.0.1
+ 1.0.2
ECHO SSH SERVER
Learning Apache Mina SSHD library
@@ -33,6 +33,10 @@
org.springframework.boot
spring-boot-starter-log4j2
+
+ commons-codec
+ commons-codec
+
org.apache.mina
mina-core
diff --git a/src/main/java/com/example/sshd/config/OnetimeCommand.java b/src/main/java/com/example/sshd/config/OnetimeCommand.java
new file mode 100644
index 0000000..9b90f91
--- /dev/null
+++ b/src/main/java/com/example/sshd/config/OnetimeCommand.java
@@ -0,0 +1,110 @@
+package com.example.sshd.config;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Properties;
+
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.sshd.server.Command;
+import org.apache.sshd.server.Environment;
+import org.apache.sshd.server.ExitCallback;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
+@Component
+@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
+public class OnetimeCommand implements Command {
+
+ private static final Logger logger = LoggerFactory.getLogger(OnetimeCommand.class);
+
+ @Autowired
+ Properties repliesProperties;
+
+ private InputStream in;
+ private OutputStream out;
+ private OutputStream err;
+ private ExitCallback callback;
+ private Environment environment;
+ private String command;
+
+ public OnetimeCommand(String cmd) {
+ command = cmd;
+ }
+
+ public InputStream getIn() {
+ return in;
+ }
+
+ public OutputStream getOut() {
+ return out;
+ }
+
+ public OutputStream getErr() {
+ return err;
+ }
+
+ public Environment getEnvironment() {
+ return environment;
+ }
+
+ @Override
+ public void setInputStream(InputStream in) {
+ this.in = in;
+ }
+
+ @Override
+ public void setOutputStream(OutputStream out) {
+ this.out = out;
+ }
+
+ @Override
+ public void setErrorStream(OutputStream err) {
+ this.err = err;
+ }
+
+ @Override
+ public void setExitCallback(ExitCallback callback) {
+ this.callback = callback;
+ }
+
+ @Override
+ public void start(Environment env) throws IOException {
+ environment = env;
+ String cmdHash = DigestUtils.md5Hex(command).toUpperCase();
+ logger.info("command = {}, cmdHash = {}", command, cmdHash);
+
+ if (StringUtils.equals(command, "exit")) {
+ logger.info("Exiting command detected: {}", command);
+ out.write(("\r\nExiting...\r\n").getBytes());
+ } else if (repliesProperties.containsKey(command)) {
+ logger.info("Known command detected: {}", command);
+ String reply = repliesProperties.getProperty(command).replace("\\r", "\r").replace("\\n", "\n")
+ .replace("\\t", "\t");
+ out.write(("\r\n" + reply + "\r\n").getBytes());
+ } else if (repliesProperties.containsKey(cmdHash)) {
+ logger.info("Known command-hash detected: {}", cmdHash);
+ String reply = repliesProperties.getProperty(cmdHash).replace("\\r", "\r").replace("\\n", "\n")
+ .replace("\\t", "\t");
+ out.write(("\r\n" + reply + "\r\n").getBytes());
+ } else {
+ logger.info("Command not found: {}", command);
+ out.write(("\r\nCommand '" + command + "' not found. Try 'exit'.\r\n").getBytes());
+ }
+ out.flush();
+ callback.onExit(0);
+ }
+
+ @Override
+ public void destroy() {
+ }
+
+ public ExitCallback getCallback() {
+ return callback;
+ }
+}
diff --git a/src/main/java/com/example/sshd/config/SshConfig.java b/src/main/java/com/example/sshd/config/SshConfig.java
index be51a98..d74052c 100644
--- a/src/main/java/com/example/sshd/config/SshConfig.java
+++ b/src/main/java/com/example/sshd/config/SshConfig.java
@@ -1,8 +1,10 @@
package com.example.sshd.config;
import java.io.File;
+import java.io.FileInputStream;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
+import java.util.Properties;
import org.apache.commons.lang3.StringUtils;
import org.apache.sshd.SshServer;
@@ -11,15 +13,19 @@ import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
import org.apache.sshd.server.session.ServerSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Scope;
@Configuration
public class SshConfig {
private static final Logger logger = LoggerFactory.getLogger(SshConfig.class);
-
+
@Value("${ssh-server.port}")
private int port;
@@ -29,6 +35,12 @@ public class SshConfig {
@Value("${ssh-server.root.username:root}")
private String rootUsername;
+ @Value("${ssh-server.automatic-replies.location}")
+ private String repliesProperties;
+
+ @Autowired
+ ApplicationContext applicationContext;
+
@Bean
public SshServer sshd() throws IOException, NoSuchAlgorithmException {
SshServer sshd = SshServer.setUpDefaultServer();
@@ -43,7 +55,18 @@ public class SshConfig {
}
});
sshd.setShellFactory(new EchoShellFactory());
+ sshd.setCommandFactory(command -> applicationContext.getBean(OnetimeCommand.class, command));
sshd.start();
return sshd;
}
+
+ @Bean
+ @Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
+ public Properties repliesProperties() throws IOException {
+ Properties prop = new Properties();
+ File configFile = new File(repliesProperties);
+ FileInputStream stream = new FileInputStream(configFile);
+ prop.load(stream);
+ return prop;
+ }
}