diff --git a/conf/replies.properties b/conf/replies.properties index 677cdfd..6f992f9 100644 --- a/conf/replies.properties +++ b/conf/replies.properties @@ -1,4 +1,4 @@ -hello=hello +prompt=$ 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 diff --git a/pom.xml b/pom.xml index f91ee9d..22a31e7 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 com.example.sshd echo-sshd-server - 1.0.2 + 1.0.3 ECHO SSH SERVER Learning Apache Mina SSHD library diff --git a/src/main/java/com/example/sshd/config/EchoShellFactory.java b/src/main/java/com/example/sshd/config/EchoShellFactory.java index b342793..e64aa21 100644 --- a/src/main/java/com/example/sshd/config/EchoShellFactory.java +++ b/src/main/java/com/example/sshd/config/EchoShellFactory.java @@ -5,23 +5,35 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; +import java.util.Properties; import java.util.UUID; -import org.apache.commons.lang3.StringUtils; import org.apache.sshd.common.Factory; 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.context.ApplicationContext; +import org.springframework.stereotype.Component; +import com.example.sshd.util.ReplyUtil; + +@Component public class EchoShellFactory implements Factory { private static final Logger logger = LoggerFactory.getLogger(EchoShellFactory.class); + @Autowired + Properties repliesProperties; + + @Autowired + ApplicationContext applicationContext; + @Override public Command create() { - return new EchoShell(); + return new EchoShell(repliesProperties); } public static class EchoShell implements Command, Runnable { @@ -32,6 +44,11 @@ public class EchoShellFactory implements Factory { private ExitCallback callback; private Environment environment; private Thread thread; + private Properties repliesProperties; + + public EchoShell(Properties repliesProperties) { + this.repliesProperties = repliesProperties; + } public InputStream getIn() { return in; @@ -83,8 +100,9 @@ public class EchoShellFactory implements Factory { @Override public void run() { + String prompt = repliesProperties.getProperty("prompt","$ "); try { - out.write("$ ".getBytes()); + out.write(prompt.getBytes()); out.flush(); BufferedReader r = new BufferedReader(new InputStreamReader(in)); @@ -93,16 +111,8 @@ public class EchoShellFactory implements Factory { while (!Thread.currentThread().isInterrupted()) { int s = r.read(); if (s == 13 || s == 10) { - - if (StringUtils.isBlank(command)) { - logger.info("Blank command detected: {}", command); - out.write(("\r\n$ ").getBytes()); - } else if (StringUtils.equals(command, "exit")) { - logger.info("Exiting command detected: {}", command); + if (!ReplyUtil.replyToCommand(repliesProperties, command, out, prompt)) { return; - } else { - logger.info("Command not found: {}", command); - out.write(("\r\nCommand '" + command + "' not found. Try 'exit'.\r\n$ ").getBytes()); } command = ""; } else { diff --git a/src/main/java/com/example/sshd/config/OnetimeCommand.java b/src/main/java/com/example/sshd/config/OnetimeCommand.java index 9b90f91..88b87b1 100644 --- a/src/main/java/com/example/sshd/config/OnetimeCommand.java +++ b/src/main/java/com/example/sshd/config/OnetimeCommand.java @@ -5,24 +5,20 @@ 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; +import com.example.sshd.util.ReplyUtil; + @Component @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public class OnetimeCommand implements Command { - private static final Logger logger = LoggerFactory.getLogger(OnetimeCommand.class); - @Autowired Properties repliesProperties; @@ -76,26 +72,7 @@ public class OnetimeCommand implements Command { @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()); - } + ReplyUtil.replyToCommand(repliesProperties, command, out, ""); out.flush(); callback.onExit(0); } diff --git a/src/main/java/com/example/sshd/config/SshConfig.java b/src/main/java/com/example/sshd/config/SshConfig.java index d74052c..1ae0db6 100644 --- a/src/main/java/com/example/sshd/config/SshConfig.java +++ b/src/main/java/com/example/sshd/config/SshConfig.java @@ -54,7 +54,7 @@ public class SshConfig { return StringUtils.equals(username, rootUsername); } }); - sshd.setShellFactory(new EchoShellFactory()); + sshd.setShellFactory(applicationContext.getBean(EchoShellFactory.class)); sshd.setCommandFactory(command -> applicationContext.getBean(OnetimeCommand.class, command)); sshd.start(); return sshd; diff --git a/src/main/java/com/example/sshd/util/ReplyUtil.java b/src/main/java/com/example/sshd/util/ReplyUtil.java new file mode 100644 index 0000000..7c952d7 --- /dev/null +++ b/src/main/java/com/example/sshd/util/ReplyUtil.java @@ -0,0 +1,41 @@ +package com.example.sshd.util; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.Properties; + +import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ReplyUtil { + + private static final Logger logger = LoggerFactory.getLogger(ReplyUtil.class); + + public static boolean replyToCommand(Properties repliesProperties, String command, OutputStream out, String prompt) + throws IOException { + + String cmdHash = DigestUtils.md5Hex(command.trim()).toUpperCase(); + + if (StringUtils.equals(command.trim(), "exit")) { + logger.info("[{}] Exiting command detected: {}", cmdHash, command.trim()); + out.write(("\r\nExiting...\r\n").getBytes()); + return false; + } else if (repliesProperties.containsKey(command.trim())) { + logger.info("[{}] Known command detected: {}", cmdHash, command.trim()); + String reply = repliesProperties.getProperty(command.trim()).replace("\\r", "\r").replace("\\n", "\n") + .replace("\\t", "\t"); + out.write(String.format("\r\n%s\r\n%s", reply, prompt).getBytes()); + } else if (repliesProperties.containsKey(cmdHash)) { + logger.info("[{}] Known command-hash detected: {}", cmdHash, command.trim()); + String reply = repliesProperties.getProperty(cmdHash).replace("\\r", "\r").replace("\\n", "\n") + .replace("\\t", "\t"); + out.write(String.format("\r\n%s\r\n%s", reply, prompt).getBytes()); + } else { + logger.info("[{}] Command not found: {}", cmdHash, command.trim()); + out.write(String.format("\r\nCommand '%s' not found. Try 'exit'.\r\n%s", command.trim(), prompt).getBytes()); + } + return true; + } +}