From a0143e96f55cc82afd27e4e051de745212a3283d Mon Sep 17 00:00:00 2001 From: Ng Yat Yan Date: Mon, 14 Oct 2024 22:11:07 +0800 Subject: [PATCH] V1.2.0 Both OnetimeCommand and EchoShell are now SessionAware! --- pom.xml | 2 +- .../example/sshd/core/EchoShellFactory.java | 29 ++++++++++++++++--- .../com/example/sshd/core/OnetimeCommand.java | 12 ++++++-- .../java/com/example/sshd/util/ReplyUtil.java | 24 ++++++++++++--- 4 files changed, 56 insertions(+), 11 deletions(-) diff --git a/pom.xml b/pom.xml index 0f51583..da71e31 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 com.example.sshd echo-sshd-server - 1.1.3 + 1.2.0 ECHO SSH SERVER Learning Apache Mina SSHD library diff --git a/src/main/java/com/example/sshd/core/EchoShellFactory.java b/src/main/java/com/example/sshd/core/EchoShellFactory.java index 5b474e0..c82556b 100644 --- a/src/main/java/com/example/sshd/core/EchoShellFactory.java +++ b/src/main/java/com/example/sshd/core/EchoShellFactory.java @@ -5,6 +5,8 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.util.Map; import java.util.Properties; import java.util.UUID; @@ -12,6 +14,8 @@ 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.apache.sshd.server.SessionAware; +import org.apache.sshd.server.session.ServerSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -30,12 +34,15 @@ public class EchoShellFactory implements Factory { @Autowired Properties hashReplies; + @Autowired + Map ipInfoMapping; + @Override public Command create() { return new EchoShell(); } - public class EchoShell implements Command, Runnable { + public class EchoShell implements Command, Runnable, SessionAware { protected InputStream in; protected OutputStream out; @@ -43,6 +50,7 @@ public class EchoShellFactory implements Factory { protected ExitCallback callback; protected Environment environment; protected Thread thread; + protected ServerSession session; @Override public void setInputStream(InputStream in) { @@ -67,8 +75,16 @@ public class EchoShellFactory implements Factory { @Override public void start(Environment env) throws IOException { environment = env; - logger.info("environment: {}", environment.getEnv()); - thread = new Thread(this, UUID.randomUUID().toString()); + + if (session.getIoSession().getRemoteAddress() instanceof InetSocketAddress) { + InetSocketAddress remoteAddress = (InetSocketAddress) session.getIoSession().getRemoteAddress(); + String remoteIpAddress = remoteAddress.getAddress().getHostAddress(); + thread = new Thread(this, remoteIpAddress); + } else { + thread = new Thread(this, session.getIoSession().getRemoteAddress().toString()); + } + + logger.info("environment: {}, thread-name: {}", environment.getEnv(), thread.getName()); thread.start(); } @@ -90,7 +106,7 @@ public class EchoShellFactory implements Factory { while (!Thread.currentThread().isInterrupted()) { int s = r.read(); if (s == 13 || s == 10) { - if (!replyUtil.replyToCommand(command, out, prompt)) { + if (!replyUtil.replyToCommand(command, out, prompt, session)) { out.flush(); return; } @@ -115,5 +131,10 @@ public class EchoShellFactory implements Factory { callback.onExit(0); } } + + @Override + public void setSession(ServerSession session) { + this.session = session; + } } } \ No newline at end of file diff --git a/src/main/java/com/example/sshd/core/OnetimeCommand.java b/src/main/java/com/example/sshd/core/OnetimeCommand.java index 4d16278..7422d71 100644 --- a/src/main/java/com/example/sshd/core/OnetimeCommand.java +++ b/src/main/java/com/example/sshd/core/OnetimeCommand.java @@ -7,6 +7,8 @@ import java.io.OutputStream; import org.apache.sshd.server.Command; import org.apache.sshd.server.Environment; import org.apache.sshd.server.ExitCallback; +import org.apache.sshd.server.SessionAware; +import org.apache.sshd.server.session.ServerSession; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.Scope; @@ -16,7 +18,7 @@ import com.example.sshd.util.ReplyUtil; @Component @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) -public class OnetimeCommand implements Command { +public class OnetimeCommand implements Command, SessionAware { @Autowired ReplyUtil replyUtil; @@ -27,6 +29,7 @@ public class OnetimeCommand implements Command { private ExitCallback callback; private Environment environment; private String command; + private ServerSession session; public OnetimeCommand(String cmd) { command = cmd; @@ -71,7 +74,7 @@ public class OnetimeCommand implements Command { @Override public void start(Environment env) throws IOException { environment = env; - replyUtil.replyToCommand(command, out, ""); + replyUtil.replyToCommand(command, out, "", session); out.flush(); callback.onExit(0); } @@ -83,4 +86,9 @@ public class OnetimeCommand implements Command { public ExitCallback getCallback() { return callback; } + + @Override + public void setSession(ServerSession session) { + this.session = session; + } } diff --git a/src/main/java/com/example/sshd/util/ReplyUtil.java b/src/main/java/com/example/sshd/util/ReplyUtil.java index 6051369..1250ceb 100644 --- a/src/main/java/com/example/sshd/util/ReplyUtil.java +++ b/src/main/java/com/example/sshd/util/ReplyUtil.java @@ -2,12 +2,15 @@ package com.example.sshd.util; import java.io.IOException; import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.util.Map; import java.util.Optional; import java.util.Properties; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; +import org.apache.sshd.server.session.ServerSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -21,17 +24,30 @@ public class ReplyUtil { @Autowired Properties hashReplies; - + @Autowired Properties regexMapping; - public boolean replyToCommand(String command, OutputStream out, String prompt) throws IOException { + @Autowired + Map ipInfoMapping; + + public boolean replyToCommand(String command, OutputStream out, String prompt, ServerSession session) + throws IOException { String cmdHash = DigestUtils.md5Hex(command.trim()).toUpperCase(); - if (StringUtils.equals(command.trim(), "exit")) { + if (StringUtils.equals(command.trim(), "about")) { + logger.info("[{}] About command detected: {}", cmdHash, command.trim()); + if (session.getIoSession().getRemoteAddress() instanceof InetSocketAddress) { + InetSocketAddress remoteAddress = (InetSocketAddress) session.getIoSession().getRemoteAddress(); + String remoteIpAddress = remoteAddress.getAddress().getHostAddress(); + out.write(String.format("\r\n%s\r\n%s", ipInfoMapping.get(remoteIpAddress), prompt).getBytes()); + } else { + out.write(String.format("\r\n%s\r\n%s", session.getIoSession().getRemoteAddress(), prompt).getBytes()); + } + } else if (StringUtils.equals(command.trim(), "exit")) { logger.info("[{}] Exiting command detected: {}", cmdHash, command.trim()); - out.write(("\r\nExiting...\r\n").getBytes()); + out.write(String.format("\r\nExiting...\r\n%s", prompt).getBytes()); return false; } else if (hashReplies.containsKey(command.trim())) { logger.info("[{}] Known command detected: {}", cmdHash, command.trim());