mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-11-16 17:41:52 +03:00
Java test WebApp
This commit is contained in:
committed by
Felipe Zimmerle
parent
a6c1627987
commit
b9080aad18
71
java/ModSecurityTestApp/build.xml
Normal file
71
java/ModSecurityTestApp/build.xml
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!-- You may freely edit this file. See commented blocks below for -->
|
||||||
|
<!-- some examples of how to customize the build. -->
|
||||||
|
<!-- (If you delete it and reopen the project it will be recreated.) -->
|
||||||
|
<!-- By default, only the Clean and Build commands use this build script. -->
|
||||||
|
<!-- Commands such as Run, Debug, and Test only use this build script if -->
|
||||||
|
<!-- the Compile on Save feature is turned off for the project. -->
|
||||||
|
<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
|
||||||
|
<!-- in the project's Project Properties dialog box.-->
|
||||||
|
<project name="ModSecurityTestApp" default="default" basedir=".">
|
||||||
|
<description>Builds, tests, and runs the project ModSecurityTestApp.</description>
|
||||||
|
<import file="nbproject/build-impl.xml"/>
|
||||||
|
<!--
|
||||||
|
|
||||||
|
There exist several targets which are by default empty and which can be
|
||||||
|
used for execution of your tasks. These targets are usually executed
|
||||||
|
before and after some main targets. They are:
|
||||||
|
|
||||||
|
-pre-init: called before initialization of project properties
|
||||||
|
-post-init: called after initialization of project properties
|
||||||
|
-pre-compile: called before javac compilation
|
||||||
|
-post-compile: called after javac compilation
|
||||||
|
-pre-compile-single: called before javac compilation of single file
|
||||||
|
-post-compile-single: called after javac compilation of single file
|
||||||
|
-pre-compile-test: called before javac compilation of JUnit tests
|
||||||
|
-post-compile-test: called after javac compilation of JUnit tests
|
||||||
|
-pre-compile-test-single: called before javac compilation of single JUnit test
|
||||||
|
-post-compile-test-single: called after javac compilation of single JUunit test
|
||||||
|
-pre-dist: called before archive building
|
||||||
|
-post-dist: called after archive building
|
||||||
|
-post-clean: called after cleaning build products
|
||||||
|
-pre-run-deploy: called before deploying
|
||||||
|
-post-run-deploy: called after deploying
|
||||||
|
|
||||||
|
Example of pluging an obfuscator after the compilation could look like
|
||||||
|
|
||||||
|
<target name="-post-compile">
|
||||||
|
<obfuscate>
|
||||||
|
<fileset dir="${build.classes.dir}"/>
|
||||||
|
</obfuscate>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
For list of available properties check the imported
|
||||||
|
nbproject/build-impl.xml file.
|
||||||
|
|
||||||
|
|
||||||
|
Other way how to customize the build is by overriding existing main targets.
|
||||||
|
The target of interest are:
|
||||||
|
|
||||||
|
init-macrodef-javac: defines macro for javac compilation
|
||||||
|
init-macrodef-junit: defines macro for junit execution
|
||||||
|
init-macrodef-debug: defines macro for class debugging
|
||||||
|
do-dist: archive building
|
||||||
|
run: execution of project
|
||||||
|
javadoc-build: javadoc generation
|
||||||
|
|
||||||
|
Example of overriding the target for project execution could look like
|
||||||
|
|
||||||
|
<target name="run" depends="<PROJNAME>-impl.jar">
|
||||||
|
<exec dir="bin" executable="launcher.exe">
|
||||||
|
<arg file="${dist.jar}"/>
|
||||||
|
</exec>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
Notice that overridden target depends on jar target and not only on
|
||||||
|
compile target as regular run target does. Again, for list of available
|
||||||
|
properties which you can use check the target you are overriding in
|
||||||
|
nbproject/build-impl.xml file.
|
||||||
|
|
||||||
|
-->
|
||||||
|
</project>
|
||||||
2
java/ModSecurityTestApp/src/conf/MANIFEST.MF
Normal file
2
java/ModSecurityTestApp/src/conf/MANIFEST.MF
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Manifest-Version: 1.0
|
||||||
|
|
||||||
@@ -0,0 +1,126 @@
|
|||||||
|
package org.modsecurity;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.net.Inet6Address;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import javax.servlet.FilterConfig;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.ServletRequest;
|
||||||
|
import javax.servlet.ServletResponse;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
public final class ModSecurity {
|
||||||
|
|
||||||
|
public static final int DONE = -2;
|
||||||
|
public static final int DECLINED = -1;
|
||||||
|
public static final int OK = 0;
|
||||||
|
|
||||||
|
//From build/classes: >"c:\Program Files\Java\jdk1.7.0_05\bin\javah.exe" -classpath c:\work\apache-tomcat-7.0.39\lib\servlet-api.jar;. org.modsecurity.ModSecurity
|
||||||
|
|
||||||
|
private FilterConfig filterConfig;
|
||||||
|
private String confFilename;
|
||||||
|
private long confTime;
|
||||||
|
private final static String pathToLib = "c:\\work\\mod_security\\java\\Debug\\";
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
//TODO: bad practice, native libraries should be loaded in server's classloader
|
||||||
|
System.load("c:\\work\\mod_security\\java\\libs\\zlib1.dll");
|
||||||
|
System.load("c:\\work\\mod_security\\java\\libs\\libxml2.dll");
|
||||||
|
System.load("c:\\work\\mod_security\\java\\libs\\pcre.dll");
|
||||||
|
System.load("c:\\work\\mod_security\\java\\libs\\libapr-1.dll");
|
||||||
|
System.load("c:\\work\\mod_security\\java\\libs\\libapriconv-1.dll");
|
||||||
|
System.load("c:\\work\\mod_security\\java\\libs\\libaprutil-1.dll");
|
||||||
|
System.load("c:\\work\\mod_security\\java\\Debug\\ModSecurityJNI.dll");
|
||||||
|
} catch (UnsatisfiedLinkError err) {
|
||||||
|
err.printStackTrace();
|
||||||
|
}
|
||||||
|
//java.lang.reflect.Field loadedLibraries = ClassLoader.class.getDeclaredField("loadedLibraryNames");
|
||||||
|
//loadedLibraries.setAccessible(true);
|
||||||
|
//final Vector<String> libraries = (Vector<String>) loadedLibraries.get(ClassLoader.getSystemClassLoader());
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModSecurity(FilterConfig fc, String confFile) throws ServletException {
|
||||||
|
this.filterConfig = fc;
|
||||||
|
this.confFilename = confFile;
|
||||||
|
confTime = new File(confFilename).lastModified();
|
||||||
|
|
||||||
|
this.initialize();
|
||||||
|
filterConfig.getServletContext().log("ModSecurity started.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private native int initialize();
|
||||||
|
|
||||||
|
public native int destroy();
|
||||||
|
|
||||||
|
public native int onRequest(String config, ServletRequest request, HttpServletRequest httprequest, String requestID, boolean reloadConfig);
|
||||||
|
|
||||||
|
public native int onResponse(ServletResponse response, HttpServletResponse htttpResponse, String requestID);
|
||||||
|
|
||||||
|
public static String[][] getHttpRequestHeaders(HttpServletRequest req) {
|
||||||
|
ArrayList<String> aList = Collections.list(req.getHeaderNames());
|
||||||
|
String[][] result = new String[aList.size()][2];
|
||||||
|
|
||||||
|
for (int i = 0; i < aList.size(); i++) {
|
||||||
|
result[i][0] = aList.get(i);
|
||||||
|
result[i][1] = req.getHeader(aList.get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String[][] getHttpResponseHeaders(HttpServletResponse resp) {
|
||||||
|
|
||||||
|
Collection<String> headerNames = resp.getHeaderNames();
|
||||||
|
String[][] result = new String[headerNames.size()][2];
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (String headerName : headerNames) {
|
||||||
|
result[i][0] = headerName;
|
||||||
|
result[i][1] = resp.getHeader(headerName);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isIPv6(String addr) {
|
||||||
|
try {
|
||||||
|
InetAddress inetAddress = InetAddress.getByName(addr);
|
||||||
|
|
||||||
|
if (inetAddress instanceof Inet6Address) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (UnknownHostException ex) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void log(int level, String msg) {
|
||||||
|
//if (level == 1) {
|
||||||
|
filterConfig.getServletContext().log(msg);
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean checkModifiedConfig() {
|
||||||
|
if (new File(confFilename).lastModified() > confTime) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAppPath() {
|
||||||
|
return filterConfig.getServletContext().getContextPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getConfFilename() {
|
||||||
|
return this.confFilename;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
package org.modsecurity;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.UUID;
|
||||||
|
import javax.servlet.Filter;
|
||||||
|
import javax.servlet.FilterChain;
|
||||||
|
import javax.servlet.FilterConfig;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.ServletRequest;
|
||||||
|
import javax.servlet.ServletResponse;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Docs: http://docs.oracle.com/javaee/6/tutorial/doc/bnagb.html
|
||||||
|
*/
|
||||||
|
public class ModSecurityFilter implements Filter {
|
||||||
|
|
||||||
|
ModSecurity modsecurity;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(FilterConfig fc) throws ServletException {
|
||||||
|
String confFilename = fc.getInitParameter("conf");
|
||||||
|
if (confFilename == null) {
|
||||||
|
throw new ServletException("ModSecurity: parameter 'conf' not available in web.xml");
|
||||||
|
} else {
|
||||||
|
confFilename = fc.getServletContext().getRealPath(confFilename);
|
||||||
|
}
|
||||||
|
|
||||||
|
modsecurity = new ModSecurity(fc, confFilename);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doFilter(ServletRequest request, ServletResponse response, FilterChain fc) throws IOException, ServletException {
|
||||||
|
HttpServletRequest httpReq = (HttpServletRequest) request;
|
||||||
|
HttpServletResponse httpResp = (HttpServletResponse) response;
|
||||||
|
|
||||||
|
String requestID = UUID.randomUUID().toString();
|
||||||
|
|
||||||
|
int status = modsecurity.onRequest(modsecurity.getConfFilename(), request, httpReq, requestID, modsecurity.checkModifiedConfig());
|
||||||
|
|
||||||
|
if (status != ModSecurity.DECLINED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fc.doFilter(request, response);
|
||||||
|
|
||||||
|
status = modsecurity.onResponse(response, httpResp, requestID);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy() {
|
||||||
|
if (modsecurity != null) {
|
||||||
|
modsecurity.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
2
java/ModSecurityTestApp/web/META-INF/context.xml
Normal file
2
java/ModSecurityTestApp/web/META-INF/context.xml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Context antiJARLocking="true" path="/ModSecurityTestApp"/>
|
||||||
12
java/ModSecurityTestApp/web/Post.jsp
Normal file
12
java/ModSecurityTestApp/web/Post.jsp
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<%@page contentType="text/html" pageEncoding="UTF-8"%>
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>JSP Page</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p><%= request.getParameter( "data" ) %></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
214
java/ModSecurityTestApp/web/WEB-INF/modsecurity.conf
Normal file
214
java/ModSecurityTestApp/web/WEB-INF/modsecurity.conf
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
# based on modsecurity.conf-recommended
|
||||||
|
# -- Rule engine initialization ----------------------------------------------
|
||||||
|
|
||||||
|
# Enable ModSecurity, attaching it to every transaction. Use detection
|
||||||
|
# only to start with, because that minimises the chances of post-installation
|
||||||
|
# disruption.
|
||||||
|
#
|
||||||
|
SecRuleEngine On
|
||||||
|
|
||||||
|
|
||||||
|
# -- Request body handling ---------------------------------------------------
|
||||||
|
|
||||||
|
# Allow ModSecurity to access request bodies. If you don't, ModSecurity
|
||||||
|
# won't be able to see any POST parameters, which opens a large security
|
||||||
|
# hole for attackers to exploit.
|
||||||
|
#
|
||||||
|
SecRequestBodyAccess On
|
||||||
|
|
||||||
|
|
||||||
|
# Enable XML request body parser.
|
||||||
|
# Initiate XML Processor in case of xml content-type
|
||||||
|
#
|
||||||
|
SecRule REQUEST_HEADERS:Content-Type "text/xml" \
|
||||||
|
"id:'200000',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML"
|
||||||
|
|
||||||
|
|
||||||
|
# Maximum request body size we will accept for buffering. If you support
|
||||||
|
# file uploads then the value given on the first line has to be as large
|
||||||
|
# as the largest file you are willing to accept. The second value refers
|
||||||
|
# to the size of data, with files excluded. You want to keep that value as
|
||||||
|
# low as practical.
|
||||||
|
#
|
||||||
|
SecRequestBodyLimit 13107200
|
||||||
|
SecRequestBodyNoFilesLimit 131072
|
||||||
|
|
||||||
|
# Store up to 128 KB of request body data in memory. When the multipart
|
||||||
|
# parser reachers this limit, it will start using your hard disk for
|
||||||
|
# storage. That is slow, but unavoidable.
|
||||||
|
#
|
||||||
|
SecRequestBodyInMemoryLimit 131072
|
||||||
|
|
||||||
|
# What do do if the request body size is above our configured limit.
|
||||||
|
# Keep in mind that this setting will automatically be set to ProcessPartial
|
||||||
|
# when SecRuleEngine is set to DetectionOnly mode in order to minimize
|
||||||
|
# disruptions when initially deploying ModSecurity.
|
||||||
|
#
|
||||||
|
SecRequestBodyLimitAction Reject
|
||||||
|
|
||||||
|
# Verify that we've correctly processed the request body.
|
||||||
|
# As a rule of thumb, when failing to process a request body
|
||||||
|
# you should reject the request (when deployed in blocking mode)
|
||||||
|
# or log a high-severity alert (when deployed in detection-only mode).
|
||||||
|
#
|
||||||
|
SecRule REQBODY_ERROR "!@eq 0" \
|
||||||
|
"id:'200001', phase:2,t:none,log,deny,status:400,msg:'Failed to parse request body.',logdata:'%{reqbody_error_msg}',severity:2"
|
||||||
|
|
||||||
|
# By default be strict with what we accept in the multipart/form-data
|
||||||
|
# request body. If the rule below proves to be too strict for your
|
||||||
|
# environment consider changing it to detection-only. You are encouraged
|
||||||
|
# _not_ to remove it altogether.
|
||||||
|
#
|
||||||
|
SecRule MULTIPART_STRICT_ERROR "!@eq 0" \
|
||||||
|
"id:'200002',phase:2,t:none,log,deny,status:44, \
|
||||||
|
msg:'Multipart request body failed strict validation: \
|
||||||
|
PE %{REQBODY_PROCESSOR_ERROR}, \
|
||||||
|
BQ %{MULTIPART_BOUNDARY_QUOTED}, \
|
||||||
|
BW %{MULTIPART_BOUNDARY_WHITESPACE}, \
|
||||||
|
DB %{MULTIPART_DATA_BEFORE}, \
|
||||||
|
DA %{MULTIPART_DATA_AFTER}, \
|
||||||
|
HF %{MULTIPART_HEADER_FOLDING}, \
|
||||||
|
LF %{MULTIPART_LF_LINE}, \
|
||||||
|
SM %{MULTIPART_MISSING_SEMICOLON}, \
|
||||||
|
IQ %{MULTIPART_INVALID_QUOTING}, \
|
||||||
|
IP %{MULTIPART_INVALID_PART}, \
|
||||||
|
IH %{MULTIPART_INVALID_HEADER_FOLDING}, \
|
||||||
|
FL %{MULTIPART_FILE_LIMIT_EXCEEDED}'"
|
||||||
|
|
||||||
|
# Did we see anything that might be a boundary?
|
||||||
|
#
|
||||||
|
SecRule MULTIPART_UNMATCHED_BOUNDARY "!@eq 0" \
|
||||||
|
"id:'200003',phase:2,t:none,log,deny,status:44,msg:'Multipart parser detected a possible unmatched boundary.'"
|
||||||
|
|
||||||
|
# PCRE Tuning
|
||||||
|
# We want to avoid a potential RegEx DoS condition
|
||||||
|
#
|
||||||
|
SecPcreMatchLimit 1000
|
||||||
|
SecPcreMatchLimitRecursion 1000
|
||||||
|
|
||||||
|
# Some internal errors will set flags in TX and we will need to look for these.
|
||||||
|
# All of these are prefixed with "MSC_". The following flags currently exist:
|
||||||
|
#
|
||||||
|
# MSC_PCRE_LIMITS_EXCEEDED: PCRE match limits were exceeded.
|
||||||
|
#
|
||||||
|
SecRule TX:/^MSC_/ "!@streq 0" \
|
||||||
|
"id:'200004',phase:2,t:none,deny,msg:'ModSecurity internal error flagged: %{MATCHED_VAR_NAME}'"
|
||||||
|
|
||||||
|
|
||||||
|
# -- Response body handling --------------------------------------------------
|
||||||
|
|
||||||
|
# Allow ModSecurity to access response bodies.
|
||||||
|
# You should have this directive enabled in order to identify errors
|
||||||
|
# and data leakage issues.
|
||||||
|
#
|
||||||
|
# Do keep in mind that enabling this directive does increases both
|
||||||
|
# memory consumption and response latency.
|
||||||
|
#
|
||||||
|
#SecResponseBodyAccess On
|
||||||
|
|
||||||
|
# Which response MIME types do you want to inspect? You should adjust the
|
||||||
|
# configuration below to catch documents but avoid static files
|
||||||
|
# (e.g., images and archives).
|
||||||
|
#
|
||||||
|
SecResponseBodyMimeType text/plain text/html text/xml
|
||||||
|
|
||||||
|
# Buffer response bodies of up to 512 KB in length.
|
||||||
|
SecResponseBodyLimit 524288
|
||||||
|
|
||||||
|
# What happens when we encounter a response body larger than the configured
|
||||||
|
# limit? By default, we process what we have and let the rest through.
|
||||||
|
# That's somewhat less secure, but does not break any legitimate pages.
|
||||||
|
#
|
||||||
|
SecResponseBodyLimitAction ProcessPartial
|
||||||
|
|
||||||
|
|
||||||
|
# -- Filesystem configuration ------------------------------------------------
|
||||||
|
|
||||||
|
# The location where ModSecurity stores temporary files (for example, when
|
||||||
|
# it needs to handle a file upload that is larger than the configured limit).
|
||||||
|
#
|
||||||
|
# This default setting is chosen due to all systems have /tmp available however,
|
||||||
|
# this is less than ideal. It is recommended that you specify a location that's private.
|
||||||
|
#
|
||||||
|
SecTmpDir c:\inetpub\temp\
|
||||||
|
|
||||||
|
# The location where ModSecurity will keep its persistent data. This default setting
|
||||||
|
# is chosen due to all systems have /tmp available however, it
|
||||||
|
# too should be updated to a place that other users can't access.
|
||||||
|
#
|
||||||
|
SecDataDir c:\inetpub\temp\
|
||||||
|
|
||||||
|
|
||||||
|
# -- File uploads handling configuration -------------------------------------
|
||||||
|
|
||||||
|
# The location where ModSecurity stores intercepted uploaded files. This
|
||||||
|
# location must be private to ModSecurity. You don't want other users on
|
||||||
|
# the server to access the files, do you?
|
||||||
|
#
|
||||||
|
#SecUploadDir /opt/modsecurity/var/upload/
|
||||||
|
|
||||||
|
# By default, only keep the files that were determined to be unusual
|
||||||
|
# in some way (by an external inspection script). For this to work you
|
||||||
|
# will also need at least one file inspection rule.
|
||||||
|
#
|
||||||
|
#SecUploadKeepFiles RelevantOnly
|
||||||
|
|
||||||
|
# Uploaded files are by default created with permissions that do not allow
|
||||||
|
# any other user to access them. You may need to relax that if you want to
|
||||||
|
# interface ModSecurity to an external program (e.g., an anti-virus).
|
||||||
|
#
|
||||||
|
#SecUploadFileMode 0600
|
||||||
|
|
||||||
|
|
||||||
|
# -- Debug log configuration -------------------------------------------------
|
||||||
|
|
||||||
|
# The default debug log configuration is to duplicate the error, warning
|
||||||
|
# and notice messages from the error log.
|
||||||
|
#
|
||||||
|
#SecDebugLog /opt/modsecurity/var/log/debug.log
|
||||||
|
#SecDebugLogLevel 3
|
||||||
|
|
||||||
|
|
||||||
|
# -- Audit log configuration -------------------------------------------------
|
||||||
|
|
||||||
|
# Log the transactions that are marked by a rule, as well as those that
|
||||||
|
# trigger a server error (determined by a 5xx or 4xx, excluding 404,
|
||||||
|
# level response status codes).
|
||||||
|
#
|
||||||
|
#SecAuditEngine RelevantOnly
|
||||||
|
#SecAuditLogRelevantStatus "^(?:5|4(?!04))"
|
||||||
|
|
||||||
|
# Log everything we know about a transaction.
|
||||||
|
#SecAuditLogParts ABIJDEFHZ
|
||||||
|
|
||||||
|
# Use a single file for logging. This is much easier to look at, but
|
||||||
|
# assumes that you will use the audit log only ocassionally.
|
||||||
|
#
|
||||||
|
#SecAuditLogType Serial
|
||||||
|
#SecAuditLog c:\inetpub\log\modsec_audit.log
|
||||||
|
|
||||||
|
# Specify the path for concurrent audit logging.
|
||||||
|
#SecAuditLogStorageDir c:\inetpub\log\
|
||||||
|
|
||||||
|
|
||||||
|
# -- Miscellaneous -----------------------------------------------------------
|
||||||
|
|
||||||
|
# Use the most commonly used application/x-www-form-urlencoded parameter
|
||||||
|
# separator. There's probably only one application somewhere that uses
|
||||||
|
# something else so don't expect to change this value.
|
||||||
|
#
|
||||||
|
SecArgumentSeparator &
|
||||||
|
|
||||||
|
# Settle on version 0 (zero) cookies, as that is what most applications
|
||||||
|
# use. Using an incorrect cookie version may open your installation to
|
||||||
|
# evasion attacks (against the rules that examine named cookies).
|
||||||
|
#
|
||||||
|
SecCookieFormat 0
|
||||||
|
|
||||||
|
# Specify your Unicode Code Point.
|
||||||
|
# This mapping is used by the t:urlDecodeUni transformation function
|
||||||
|
# to properly map encoded data to your language. Properly setting
|
||||||
|
# these directives helps to reduce false positives and negatives.
|
||||||
|
#
|
||||||
|
#SecUnicodeCodePage 20127
|
||||||
|
#SecUnicodeMapFile unicode.mapping
|
||||||
22
java/ModSecurityTestApp/web/WEB-INF/web.xml
Normal file
22
java/ModSecurityTestApp/web/WEB-INF/web.xml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||||
|
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
|
||||||
|
|
||||||
|
<web-app>
|
||||||
|
|
||||||
|
<display-name>ModSecurity for Java</display-name>
|
||||||
|
|
||||||
|
<filter>
|
||||||
|
<filter-name>ModSecurityFilter</filter-name>
|
||||||
|
<filter-class>org.modsecurity.ModSecurityFilter</filter-class>
|
||||||
|
<init-param>
|
||||||
|
<param-name>conf</param-name>
|
||||||
|
<param-value>/WEB-INF/modsecurity.conf</param-value>
|
||||||
|
</init-param>
|
||||||
|
</filter>
|
||||||
|
|
||||||
|
<filter-mapping>
|
||||||
|
<filter-name>ModSecurityFilter</filter-name>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</filter-mapping>
|
||||||
|
|
||||||
|
</web-app>
|
||||||
14
java/ModSecurityTestApp/web/index.jsp
Normal file
14
java/ModSecurityTestApp/web/index.jsp
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<%@page contentType="text/html" pageEncoding="UTF-8"%>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>JSP Page</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<form method="post" action="Post.jsp">
|
||||||
|
Post Action: <input type="text" name="data" />
|
||||||
|
<input type="submit" />
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -17,10 +17,10 @@
|
|||||||
#define MODSECURITY_LOG_MET "log"
|
#define MODSECURITY_LOG_MET "log"
|
||||||
#define MODSECURITY_LOG_SIG "(ILjava/lang/String;)V"
|
#define MODSECURITY_LOG_SIG "(ILjava/lang/String;)V"
|
||||||
|
|
||||||
#define MODSECURITY__HTTPHEADERS_MET "getHttpHeaders"
|
#define MODSECURITY__HTTPREQHEADERS_MET "getHttpRequestHeaders"
|
||||||
#define MODSECURITY__HTTPHEADERS_SIG "(Ljavax/servlet/http/HttpServletRequest;)[[Ljava/lang/String;"
|
#define MODSECURITY__HTTPREQHEADERS_SIG "(Ljavax/servlet/http/HttpServletRequest;)[[Ljava/lang/String;"
|
||||||
//#define MODSECURITY__REQUESTBODY_MET "getRequestBody"
|
#define MODSECURITY__HTTPRESHEADERS_MET "getHttpResponseHeaders"
|
||||||
//#define MODSECURITY__REQUESTBODY_SIG "(Ljavax/servlet/http/HttpServletRequest;)Ljava/lang/String;"
|
#define MODSECURITY__HTTPRESHEADERS_SIG "(Ljavax/servlet/http/HttpServletResponse;)[[Ljava/lang/String;"
|
||||||
#define MODSECURITY__ISPV6_MET "isIPv6"
|
#define MODSECURITY__ISPV6_MET "isIPv6"
|
||||||
#define MODSECURITY__ISPV6_SIG "(Ljava/lang/String;)Z"
|
#define MODSECURITY__ISPV6_SIG "(Ljava/lang/String;)Z"
|
||||||
|
|
||||||
@@ -39,11 +39,14 @@
|
|||||||
#define HTTPSERVLETREQUEST_METHOD_MET "getMethod"
|
#define HTTPSERVLETREQUEST_METHOD_MET "getMethod"
|
||||||
#define HTTPSERVLETREQUEST_PROTOCOL_MET "getProtocol"
|
#define HTTPSERVLETREQUEST_PROTOCOL_MET "getProtocol"
|
||||||
|
|
||||||
|
|
||||||
#define HTTPSERVLETREQUEST_REQUESTURL_MET "getRequestURL"
|
#define HTTPSERVLETREQUEST_REQUESTURL_MET "getRequestURL"
|
||||||
#define HTTPSERVLETREQUEST_REQUESTURL_SIG "()Ljava/lang/StringBuffer;"
|
#define HTTPSERVLETREQUEST_REQUESTURL_SIG "()Ljava/lang/StringBuffer;"
|
||||||
|
|
||||||
|
|
||||||
|
#define SERVLETRESPONSE_CONTENTTYPE_MET "getContentType"
|
||||||
|
#define SERVLETRESPONSE_CHARENCODING_MET "getCharacterEncoding"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//typedef struct {
|
//typedef struct {
|
||||||
JavaVM *jvm;
|
JavaVM *jvm;
|
||||||
@@ -52,11 +55,16 @@ directory_config *config;
|
|||||||
//} JavaModSecurityContext;
|
//} JavaModSecurityContext;
|
||||||
jmethodID logMethod;
|
jmethodID logMethod;
|
||||||
|
|
||||||
#define JAVASERVLET_CONTEXT "JavaServletContext"
|
|
||||||
|
apr_table_t *requests;
|
||||||
|
apr_pool_t *requestsPool;
|
||||||
|
|
||||||
|
|
||||||
|
#define JAVASERVLET_INSTREAM "RequestInStream"
|
||||||
|
|
||||||
void storeJavaServletContext(request_rec *r, jobject obj)
|
void storeJavaServletContext(request_rec *r, jobject obj)
|
||||||
{
|
{
|
||||||
apr_table_setn(r->notes, JAVASERVLET_CONTEXT, (const char *)obj);
|
apr_table_setn(r->notes, JAVASERVLET_INSTREAM, (const char *)obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
jobject getJavaServletContext(request_rec *r)
|
jobject getJavaServletContext(request_rec *r)
|
||||||
@@ -65,14 +73,14 @@ jobject getJavaServletContext(request_rec *r)
|
|||||||
request_rec *rx = NULL;
|
request_rec *rx = NULL;
|
||||||
|
|
||||||
/* Look in the current request first. */
|
/* Look in the current request first. */
|
||||||
obj = (jobject)apr_table_get(r->notes, JAVASERVLET_CONTEXT);
|
obj = (jobject)apr_table_get(r->notes, JAVASERVLET_INSTREAM);
|
||||||
if (obj != NULL)
|
if (obj != NULL)
|
||||||
return obj;
|
return obj;
|
||||||
|
|
||||||
/* If this is a subrequest then look in the main request. */
|
/* If this is a subrequest then look in the main request. */
|
||||||
if (r->main != NULL)
|
if (r->main != NULL)
|
||||||
{
|
{
|
||||||
obj = (jobject)apr_table_get(r->main->notes, JAVASERVLET_CONTEXT);
|
obj = (jobject)apr_table_get(r->main->notes, JAVASERVLET_INSTREAM);
|
||||||
if (obj != NULL)
|
if (obj != NULL)
|
||||||
{
|
{
|
||||||
return obj;
|
return obj;
|
||||||
@@ -83,7 +91,7 @@ jobject getJavaServletContext(request_rec *r)
|
|||||||
rx = r->prev;
|
rx = r->prev;
|
||||||
while(rx != NULL)
|
while(rx != NULL)
|
||||||
{
|
{
|
||||||
obj = (jobject)apr_table_get(rx->notes, JAVASERVLET_CONTEXT);
|
obj = (jobject)apr_table_get(rx->notes, JAVASERVLET_INSTREAM);
|
||||||
if (obj != NULL)
|
if (obj != NULL)
|
||||||
{
|
{
|
||||||
return obj;
|
return obj;
|
||||||
@@ -94,11 +102,11 @@ jobject getJavaServletContext(request_rec *r)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
apr_status_t memCleanup(void *mem)
|
//apr_status_t memCleanup(void *mem)
|
||||||
{
|
//{
|
||||||
free(mem);
|
// free(mem);
|
||||||
return APR_SUCCESS;
|
// return APR_SUCCESS;
|
||||||
}
|
//}
|
||||||
|
|
||||||
apr_sockaddr_t *CopySockAddr(jclass msClass, JNIEnv *env, apr_pool_t *pool, char *addrstr, jstring addrStrJstr)
|
apr_sockaddr_t *CopySockAddr(jclass msClass, JNIEnv *env, apr_pool_t *pool, char *addrstr, jstring addrStrJstr)
|
||||||
{
|
{
|
||||||
@@ -142,24 +150,30 @@ apr_sockaddr_t *CopySockAddr(jclass msClass, JNIEnv *env, apr_pool_t *pool, char
|
|||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline char* fromJString(JNIEnv *env, jstring jStr, apr_pool_t *pool)
|
||||||
char* fromJStringMethod(JNIEnv *env, jmethodID method, jobject obj, request_rec *r)
|
|
||||||
{
|
{
|
||||||
char *str;
|
char *str;
|
||||||
jstring jStr = (jstring) (env)->CallObjectMethod(obj, method);
|
|
||||||
if (jStr != NULL)
|
if (jStr != NULL)
|
||||||
{
|
{
|
||||||
str = (char*) (env)->GetStringUTFChars(jStr, 0);
|
const char *jCStr = (env)->GetStringUTFChars(jStr, NULL);
|
||||||
(env)->ReleaseStringUTFChars(jStr, str);
|
int len = strlen(jCStr);
|
||||||
|
str = (char*) apr_palloc(pool, len + 1);
|
||||||
|
memcpy(str, jCStr, len);
|
||||||
|
str[len] = '\0'; //null terminate
|
||||||
|
(env)->ReleaseStringUTFChars(jStr, jCStr); //release java heap memory
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
str = "";
|
str = "";
|
||||||
|
|
||||||
apr_pool_cleanup_register(r->pool, str, memCleanup, apr_pool_cleanup_null);
|
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline char* fromJStringMethod(JNIEnv *env, jmethodID method, jobject obj, apr_pool_t *pool)
|
||||||
|
{
|
||||||
|
jstring jStr = (jstring) (env)->CallObjectMethod(obj, method);
|
||||||
|
|
||||||
|
return fromJString(env, jStr, pool);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void logSec(void *obj, int level, char *str)
|
void logSec(void *obj, int level, char *str)
|
||||||
@@ -167,7 +181,7 @@ void logSec(void *obj, int level, char *str)
|
|||||||
JNIEnv *env;
|
JNIEnv *env;
|
||||||
jstring jStr;
|
jstring jStr;
|
||||||
|
|
||||||
if (!(jvm)->AttachCurrentThread((void **)&env, NULL))
|
if (!(jvm)->AttachCurrentThread((void **)&env, NULL)) //get the Enviroment from the JavaVM
|
||||||
{
|
{
|
||||||
jStr = (env)->NewStringUTF(str);
|
jStr = (env)->NewStringUTF(str);
|
||||||
|
|
||||||
@@ -182,7 +196,7 @@ void logSec(void *obj, int level, char *str)
|
|||||||
|
|
||||||
apr_status_t ReadBodyCallback(request_rec *r, char *buf, unsigned int length, unsigned int *readcnt, int *is_eos)
|
apr_status_t ReadBodyCallback(request_rec *r, char *buf, unsigned int length, unsigned int *readcnt, int *is_eos)
|
||||||
{
|
{
|
||||||
jobject inputStream = getJavaServletContext(r);
|
jobject inputStream = getJavaServletContext(r); //servlet request input stream
|
||||||
JNIEnv *env;
|
JNIEnv *env;
|
||||||
|
|
||||||
*readcnt = 0;
|
*readcnt = 0;
|
||||||
@@ -195,12 +209,14 @@ apr_status_t ReadBodyCallback(request_rec *r, char *buf, unsigned int length, un
|
|||||||
|
|
||||||
if (!(jvm)->AttachCurrentThread((void **)&env, NULL))
|
if (!(jvm)->AttachCurrentThread((void **)&env, NULL))
|
||||||
{
|
{
|
||||||
jclass inputStreamClass = env->FindClass(SERVLETINPUTSTREAM_JAVACLASS);
|
//read request body from the servlet input stream using 'read' method
|
||||||
|
jclass inputStreamClass = env->FindClass(SERVLETINPUTSTREAM_JAVACLASS);
|
||||||
jmethodID read = (env)->GetMethodID(inputStreamClass, INPUTSTREAM_READ_MET, INPUTSTREAM_READ_SIG);
|
jmethodID read = (env)->GetMethodID(inputStreamClass, INPUTSTREAM_READ_MET, INPUTSTREAM_READ_SIG);
|
||||||
|
|
||||||
jbyteArray byteArrayBuf = (env)->NewByteArray(length);
|
jbyteArray byteArrayBuf = (env)->NewByteArray(length);
|
||||||
|
|
||||||
jint count = (env)->CallIntMethod(inputStream, read, byteArrayBuf, 0, length);
|
jint count = (env)->CallIntMethod(inputStream, read, byteArrayBuf, 0, length);
|
||||||
|
jbyte* bufferPtr = (env)->GetByteArrayElements(byteArrayBuf, NULL);
|
||||||
|
|
||||||
if (count == -1 || count > length || env->ExceptionCheck() == JNI_TRUE) //end of stream
|
if (count == -1 || count > length || env->ExceptionCheck() == JNI_TRUE) //end of stream
|
||||||
{
|
{
|
||||||
@@ -210,13 +226,10 @@ apr_status_t ReadBodyCallback(request_rec *r, char *buf, unsigned int length, un
|
|||||||
{
|
{
|
||||||
*readcnt = count;
|
*readcnt = count;
|
||||||
|
|
||||||
jbyte* bufferPtr = (env)->GetByteArrayElements(byteArrayBuf, NULL);
|
|
||||||
|
|
||||||
memcpy(buf, bufferPtr, *readcnt);
|
memcpy(buf, bufferPtr, *readcnt);
|
||||||
|
|
||||||
(env)->ReleaseByteArrayElements(byteArrayBuf, bufferPtr, NULL);
|
|
||||||
(env)->DeleteLocalRef(byteArrayBuf);
|
|
||||||
}
|
}
|
||||||
|
(env)->ReleaseByteArrayElements(byteArrayBuf, bufferPtr, NULL);
|
||||||
|
(env)->DeleteLocalRef(byteArrayBuf);
|
||||||
|
|
||||||
(jvm)->DetachCurrentThread();
|
(jvm)->DetachCurrentThread();
|
||||||
}
|
}
|
||||||
@@ -242,9 +255,9 @@ apr_status_t WriteResponseCallback(request_rec *r, char *buf, unsigned int lengt
|
|||||||
JNIEXPORT jint JNICALL Java_org_modsecurity_ModSecurity_initialize(JNIEnv *env, jobject obj)
|
JNIEXPORT jint JNICALL Java_org_modsecurity_ModSecurity_initialize(JNIEnv *env, jobject obj)
|
||||||
{
|
{
|
||||||
(env)->GetJavaVM(&jvm);
|
(env)->GetJavaVM(&jvm);
|
||||||
modSecurityInstance = (env)->NewGlobalRef(obj);
|
modSecurityInstance = (env)->NewGlobalRef(obj); //Save the ModSecurity object for further use
|
||||||
//modSecurityClass = env->GetObjectClass(obj);
|
|
||||||
logMethod = (env)->GetMethodID(env->GetObjectClass(obj), MODSECURITY_LOG_MET, MODSECURITY_LOG_SIG);
|
logMethod = (env)->GetMethodID(env->GetObjectClass(obj), MODSECURITY_LOG_MET, MODSECURITY_LOG_SIG); //log method ID
|
||||||
|
|
||||||
modsecSetLogHook(NULL, logSec);
|
modsecSetLogHook(NULL, logSec);
|
||||||
|
|
||||||
@@ -254,107 +267,37 @@ JNIEXPORT jint JNICALL Java_org_modsecurity_ModSecurity_initialize(JNIEnv *env,
|
|||||||
modsecSetWriteResponse(WriteResponseCallback);
|
modsecSetWriteResponse(WriteResponseCallback);
|
||||||
|
|
||||||
modsecInit();
|
modsecInit();
|
||||||
//char *compname = (char *)malloc(128);
|
|
||||||
//s->server_hostname = compname;
|
|
||||||
modsecStartConfig();
|
modsecStartConfig();
|
||||||
config = modsecGetDefaultConfig();
|
config = modsecGetDefaultConfig();
|
||||||
modsecFinalizeConfig();
|
modsecFinalizeConfig();
|
||||||
modsecInitProcess();
|
modsecInitProcess();
|
||||||
config = NULL;
|
config = NULL;
|
||||||
|
|
||||||
|
//table for requests
|
||||||
|
apr_pool_create(&requestsPool, NULL);
|
||||||
|
requests = apr_table_make(requestsPool, 10);
|
||||||
|
|
||||||
return APR_SUCCESS;
|
return APR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jint JNICALL Java_org_modsecurity_ModSecurity_destroy(JNIEnv *env, jobject obj)
|
JNIEXPORT jint JNICALL Java_org_modsecurity_ModSecurity_destroy(JNIEnv *env, jobject obj)
|
||||||
{
|
{
|
||||||
(env)->DeleteGlobalRef(modSecurityInstance);
|
(env)->DeleteGlobalRef(modSecurityInstance);
|
||||||
//(env)->DeleteGlobalRef(modSecurityClass);
|
|
||||||
|
apr_pool_destroy(requestsPool);
|
||||||
|
|
||||||
|
modsecTerminate();
|
||||||
|
|
||||||
return APR_SUCCESS;
|
return APR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
//int getPort(request_rec *r)
|
|
||||||
//{
|
|
||||||
// int port = 0;
|
|
||||||
// char *port_str = NULL;
|
|
||||||
//
|
|
||||||
// if(r->hostname != NULL)
|
|
||||||
// {
|
|
||||||
// int k = 0;
|
|
||||||
// char *ptr = (char *)r->hostname;
|
|
||||||
//
|
|
||||||
// while(*ptr != 0 && *ptr != ':')
|
|
||||||
// ptr++;
|
|
||||||
//
|
|
||||||
// if(*ptr == ':')
|
|
||||||
// {
|
|
||||||
// *ptr = 0;
|
|
||||||
// port_str = ptr + 1;
|
|
||||||
// port = atoi(port_str);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return port;
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
inline void setHeaders(JNIEnv *env, jclass modSecurityClass, jobject httpServletR, apr_table_t *reqHeaders, apr_pool_t *pool, const char *headersMet, const char *headersSig)
|
||||||
|
|
||||||
JNIEXPORT jint JNICALL Java_org_modsecurity_ModSecurity_onRequest(JNIEnv *env, jobject obj, jstring configPath, jobject servletRequest, jobject httpServletRequest, jstring requestID, jboolean reloadConfig)
|
|
||||||
{
|
{
|
||||||
conn_rec *c;
|
//All headers are returned in a table by a static method from ModSecurity class
|
||||||
request_rec *r;
|
jmethodID getHttpHeaders = (env)->GetStaticMethodID(modSecurityClass, headersMet, headersSig);
|
||||||
|
jobjectArray headersTable = (jobjectArray) (env)->CallStaticObjectMethod(modSecurityClass, getHttpHeaders, httpServletR);
|
||||||
const char *path = (env)->GetStringUTFChars(configPath, NULL);
|
|
||||||
const char *reqID = (env)->GetStringUTFChars(requestID, NULL);
|
|
||||||
|
|
||||||
if (config == NULL || reloadConfig)
|
|
||||||
{
|
|
||||||
config = modsecGetDefaultConfig();
|
|
||||||
const char *err = modsecProcessConfig(config, path, NULL);
|
|
||||||
|
|
||||||
if(err != NULL)
|
|
||||||
{
|
|
||||||
logSec(NULL, 0, (char*)err);
|
|
||||||
return DONE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
c = modsecNewConnection();
|
|
||||||
modsecProcessConnection(c);
|
|
||||||
r = modsecNewRequest(c, config);
|
|
||||||
|
|
||||||
|
|
||||||
jclass httpServletRequestClass = env->GetObjectClass(httpServletRequest);
|
|
||||||
jclass servletRequestClass = env->GetObjectClass(servletRequest);
|
|
||||||
jclass modSecurityClass = env->GetObjectClass(obj);
|
|
||||||
|
|
||||||
|
|
||||||
jmethodID getInputStream = (env)->GetMethodID(servletRequestClass, SERVLETREQUEST_INPUTSTREAM_MET, SERVLETREQUEST_INPUTSTREAM_SIG);
|
|
||||||
jobject inputStream = (env)->CallObjectMethod(servletRequest, getInputStream);
|
|
||||||
//jobject gref = env->NewGlobalRef(inputStream);
|
|
||||||
//apr_pool_cleanup_register(r->pool, gref, jDeleteGlobalRef, apr_pool_cleanup_null);
|
|
||||||
|
|
||||||
storeJavaServletContext(r, inputStream);
|
|
||||||
|
|
||||||
jmethodID getServerName = (env)->GetMethodID(servletRequestClass, SERVLETREQUEST_SERVERNAME_MET, STRINGRETURN_SIG);
|
|
||||||
r->hostname = fromJStringMethod(env, getServerName, servletRequest, r);
|
|
||||||
|
|
||||||
jmethodID getServerPort = (env)->GetMethodID(servletRequestClass, SERVLETREQUEST_SERVERPORT_MET, SERVLETREQUEST_SERVERPORT_SIG);
|
|
||||||
int port = (env)->CallIntMethod(servletRequest, getServerPort);
|
|
||||||
size_t len = (size_t) ceil(log10((float) abs(port)));
|
|
||||||
char *port_str = (char*) apr_palloc(r->pool, len);
|
|
||||||
itoa(port, port_str, 10);
|
|
||||||
|
|
||||||
|
|
||||||
jmethodID getPathInfo = (env)->GetMethodID(httpServletRequestClass, HTTPSERVLETREQUEST_PATHINFO_MET, STRINGRETURN_SIG);
|
|
||||||
r->path_info = fromJStringMethod(env, getPathInfo, httpServletRequest, r);
|
|
||||||
|
|
||||||
|
|
||||||
jmethodID getQueryString = (env)->GetMethodID(httpServletRequestClass, HTTPSERVLETREQUEST_QUERYSTRING_MET, STRINGRETURN_SIG);
|
|
||||||
r->args = fromJStringMethod(env, getQueryString, httpServletRequest, r);
|
|
||||||
|
|
||||||
|
|
||||||
jmethodID getHttpHeaders = (env)->GetStaticMethodID(modSecurityClass, MODSECURITY__HTTPHEADERS_MET, MODSECURITY__HTTPHEADERS_SIG);
|
|
||||||
jobjectArray headersTable = (jobjectArray) (env)->CallStaticObjectMethod(modSecurityClass, getHttpHeaders, httpServletRequest);
|
|
||||||
jsize size = (env)->GetArrayLength(headersTable);
|
jsize size = (env)->GetArrayLength(headersTable);
|
||||||
|
|
||||||
for (int i = 0; i < size; i++)
|
for (int i = 0; i < size; i++)
|
||||||
@@ -367,26 +310,88 @@ JNIEXPORT jint JNICALL Java_org_modsecurity_ModSecurity_onRequest(JNIEnv *env, j
|
|||||||
|
|
||||||
if (headerNameJStr != NULL && headerValueJStr != NULL)
|
if (headerNameJStr != NULL && headerValueJStr != NULL)
|
||||||
{
|
{
|
||||||
headerName = (env)->GetStringUTFChars(headerNameJStr, 0);
|
headerName = fromJString(env, headerNameJStr, pool);
|
||||||
apr_pool_cleanup_register(r->pool, headerName, memCleanup, apr_pool_cleanup_null);
|
//apr_pool_cleanup_register(r->pool, headerName, memCleanup, apr_pool_cleanup_null);
|
||||||
|
|
||||||
headerValue = (env)->GetStringUTFChars(headerValueJStr, 0);
|
headerValue = fromJString(env, headerValueJStr, pool);
|
||||||
apr_pool_cleanup_register(r->pool, headerValue, memCleanup, apr_pool_cleanup_null);
|
//apr_pool_cleanup_register(r->pool, headerValue, memCleanup, apr_pool_cleanup_null);
|
||||||
|
|
||||||
apr_table_setn(r->headers_in, headerName, headerValue);
|
apr_table_setn(reqHeaders, headerName, headerValue);
|
||||||
|
|
||||||
(env)->ReleaseStringUTFChars(headerNameJStr, headerName);
|
env->DeleteLocalRef(headerNameJStr);
|
||||||
(env)->ReleaseStringUTFChars(headerValueJStr, headerValue);
|
env->DeleteLocalRef(headerValueJStr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jint JNICALL Java_org_modsecurity_ModSecurity_onRequest(JNIEnv *env, jobject obj, jstring configPath, jobject servletRequest, jobject httpServletRequest, jstring requestID, jboolean reloadConfig)
|
||||||
|
{
|
||||||
|
//critical section ?
|
||||||
|
conn_rec *c;
|
||||||
|
request_rec *r;
|
||||||
|
|
||||||
|
const char *path = (env)->GetStringUTFChars(configPath, NULL); //path to modsecurity.conf
|
||||||
|
|
||||||
|
|
||||||
|
if (config == NULL || reloadConfig)
|
||||||
|
{
|
||||||
|
config = modsecGetDefaultConfig();
|
||||||
|
const char *err = modsecProcessConfig(config, path, NULL);
|
||||||
|
|
||||||
|
if(err != NULL)
|
||||||
|
{
|
||||||
|
logSec(NULL, 0, (char*)err);
|
||||||
|
|
||||||
|
(env)->ReleaseStringUTFChars(configPath, path);
|
||||||
|
return DONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c = modsecNewConnection();
|
||||||
|
modsecProcessConnection(c);
|
||||||
|
r = modsecNewRequest(c, config);
|
||||||
|
|
||||||
|
const char *reqID = fromJString(env, requestID, r->pool); //unique ID of this request
|
||||||
|
apr_table_setn(requests, reqID, (const char*) r); //store this request for response processing
|
||||||
|
|
||||||
|
|
||||||
|
jclass httpServletRequestClass = env->GetObjectClass(httpServletRequest); //HttpServletRequest interface
|
||||||
|
jclass servletRequestClass = env->GetObjectClass(servletRequest); //ServletRequest interface
|
||||||
|
jclass modSecurityClass = env->GetObjectClass(obj); //ModSecurity class
|
||||||
|
|
||||||
|
|
||||||
|
jmethodID getInputStream = (env)->GetMethodID(servletRequestClass, SERVLETREQUEST_INPUTSTREAM_MET, SERVLETREQUEST_INPUTSTREAM_SIG);
|
||||||
|
jobject inputStream = (env)->CallObjectMethod(servletRequest, getInputStream); //Request body input stream used in the read body callback
|
||||||
|
|
||||||
|
storeJavaServletContext(r, inputStream);
|
||||||
|
|
||||||
|
jmethodID getServerName = (env)->GetMethodID(servletRequestClass, SERVLETREQUEST_SERVERNAME_MET, STRINGRETURN_SIG);
|
||||||
|
r->hostname = fromJStringMethod(env, getServerName, servletRequest, r->pool);
|
||||||
|
|
||||||
|
jmethodID getServerPort = (env)->GetMethodID(servletRequestClass, SERVLETREQUEST_SERVERPORT_MET, SERVLETREQUEST_SERVERPORT_SIG);
|
||||||
|
int port = (env)->CallIntMethod(servletRequest, getServerPort); //server port
|
||||||
|
size_t len = (size_t) ceil(log10((float) port));
|
||||||
|
char *port_str = (char*) apr_palloc(r->pool, len);
|
||||||
|
itoa(port, port_str, 10);
|
||||||
|
|
||||||
|
|
||||||
|
jmethodID getPathInfo = (env)->GetMethodID(httpServletRequestClass, HTTPSERVLETREQUEST_PATHINFO_MET, STRINGRETURN_SIG);
|
||||||
|
r->path_info = fromJStringMethod(env, getPathInfo, httpServletRequest, r->pool);
|
||||||
|
|
||||||
|
|
||||||
|
jmethodID getQueryString = (env)->GetMethodID(httpServletRequestClass, HTTPSERVLETREQUEST_QUERYSTRING_MET, STRINGRETURN_SIG);
|
||||||
|
r->args = fromJStringMethod(env, getQueryString, httpServletRequest, r->pool);
|
||||||
|
|
||||||
|
|
||||||
|
setHeaders(env, modSecurityClass, httpServletRequest, r->headers_in, r->pool, MODSECURITY__HTTPREQHEADERS_MET, MODSECURITY__HTTPREQHEADERS_SIG);
|
||||||
|
|
||||||
|
|
||||||
jmethodID getCharacterEncoding = (env)->GetMethodID(servletRequestClass, SERVLETREQUEST_CHARENCODING_MET, STRINGRETURN_SIG);
|
jmethodID getCharacterEncoding = (env)->GetMethodID(servletRequestClass, SERVLETREQUEST_CHARENCODING_MET, STRINGRETURN_SIG);
|
||||||
r->content_encoding = fromJStringMethod(env, getCharacterEncoding, servletRequest, r);
|
r->content_encoding = fromJStringMethod(env, getCharacterEncoding, servletRequest, r->pool);
|
||||||
|
|
||||||
|
|
||||||
jmethodID getContentType = (env)->GetMethodID(servletRequestClass, SERVLETREQUEST_CONTENTTYPE_MET, STRINGRETURN_SIG);
|
jmethodID getContentType = (env)->GetMethodID(servletRequestClass, SERVLETREQUEST_CONTENTTYPE_MET, STRINGRETURN_SIG);
|
||||||
r->content_type = fromJStringMethod(env, getContentType, servletRequest, r);
|
r->content_type = fromJStringMethod(env, getContentType, servletRequest, r->pool);
|
||||||
|
|
||||||
|
|
||||||
const char *lng = apr_table_get(r->headers_in, "Content-Languages");
|
const char *lng = apr_table_get(r->headers_in, "Content-Languages");
|
||||||
@@ -397,7 +402,7 @@ JNIEXPORT jint JNICALL Java_org_modsecurity_ModSecurity_onRequest(JNIEnv *env, j
|
|||||||
}
|
}
|
||||||
|
|
||||||
jmethodID getMethod = (env)->GetMethodID(httpServletRequestClass, HTTPSERVLETREQUEST_METHOD_MET, STRINGRETURN_SIG);
|
jmethodID getMethod = (env)->GetMethodID(httpServletRequestClass, HTTPSERVLETREQUEST_METHOD_MET, STRINGRETURN_SIG);
|
||||||
const char* method = fromJStringMethod(env, getMethod, httpServletRequest, r);
|
const char* method = fromJStringMethod(env, getMethod, httpServletRequest, r->pool);
|
||||||
|
|
||||||
//#define SETMETHOD(m) if(strcmp(method,#m) == 0){ r->method = method; r->method_number = M_##m; }
|
//#define SETMETHOD(m) if(strcmp(method,#m) == 0){ r->method = method; r->method_number = M_##m; }
|
||||||
|
|
||||||
@@ -421,7 +426,7 @@ JNIEXPORT jint JNICALL Java_org_modsecurity_ModSecurity_onRequest(JNIEnv *env, j
|
|||||||
else if (strcmp(method, "UNLOCK") == 0) { r->method = method; r->method_number = M_UNLOCK; }
|
else if (strcmp(method, "UNLOCK") == 0) { r->method = method; r->method_number = M_UNLOCK; }
|
||||||
|
|
||||||
jmethodID getProtocol = (env)->GetMethodID(httpServletRequestClass, HTTPSERVLETREQUEST_PROTOCOL_MET, STRINGRETURN_SIG);
|
jmethodID getProtocol = (env)->GetMethodID(httpServletRequestClass, HTTPSERVLETREQUEST_PROTOCOL_MET, STRINGRETURN_SIG);
|
||||||
r->protocol = fromJStringMethod(env, getProtocol, httpServletRequest, r);
|
r->protocol = fromJStringMethod(env, getProtocol, httpServletRequest, r->pool);
|
||||||
|
|
||||||
r->request_time = apr_time_now();
|
r->request_time = apr_time_now();
|
||||||
|
|
||||||
@@ -438,12 +443,25 @@ JNIEXPORT jint JNICALL Java_org_modsecurity_ModSecurity_onRequest(JNIEnv *env, j
|
|||||||
r->parsed_uri.user = NULL;
|
r->parsed_uri.user = NULL;
|
||||||
r->parsed_uri.fragment = NULL;
|
r->parsed_uri.fragment = NULL;
|
||||||
|
|
||||||
|
//the request Url is in a StringBuffer object
|
||||||
jmethodID getRequestURL = (env)->GetMethodID(httpServletRequestClass, HTTPSERVLETREQUEST_REQUESTURL_MET, HTTPSERVLETREQUEST_REQUESTURL_SIG);
|
jmethodID getRequestURL = (env)->GetMethodID(httpServletRequestClass, HTTPSERVLETREQUEST_REQUESTURL_MET, HTTPSERVLETREQUEST_REQUESTURL_SIG);
|
||||||
jobject stringBuffer = (env)->CallObjectMethod(httpServletRequest, getRequestURL);
|
jobject stringBuffer = (env)->CallObjectMethod(httpServletRequest, getRequestURL);
|
||||||
if (stringBuffer != NULL)
|
if (stringBuffer != NULL)
|
||||||
{
|
{
|
||||||
jmethodID toStringBuff = (env)->GetMethodID((env)->GetObjectClass(stringBuffer), TOSTRING_MET, STRINGRETURN_SIG);
|
jmethodID toStringBuff = (env)->GetMethodID((env)->GetObjectClass(stringBuffer), TOSTRING_MET, STRINGRETURN_SIG);
|
||||||
r->unparsed_uri = fromJStringMethod(env, toStringBuff, stringBuffer, r);
|
char *url = fromJStringMethod(env, toStringBuff, stringBuffer, r->pool);
|
||||||
|
|
||||||
|
if (strcmp(r->args, "") != 0)
|
||||||
|
{
|
||||||
|
r->unparsed_uri = (char*)apr_palloc(r->pool, strlen(url) + 1 + strlen(r->args)); //unparsed uri with full query
|
||||||
|
strcpy(r->unparsed_uri, url);
|
||||||
|
strcat(r->unparsed_uri, "?");
|
||||||
|
strcat(r->unparsed_uri, r->args);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
r->unparsed_uri = url;
|
||||||
|
}
|
||||||
r->uri = r->unparsed_uri;
|
r->uri = r->unparsed_uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -460,8 +478,8 @@ JNIEXPORT jint JNICALL Java_org_modsecurity_ModSecurity_onRequest(JNIEnv *env, j
|
|||||||
|
|
||||||
jmethodID getRemoteAddr = (env)->GetMethodID(servletRequestClass, SERVLETREQUEST_REMOTEADDR_MET, STRINGRETURN_SIG);
|
jmethodID getRemoteAddr = (env)->GetMethodID(servletRequestClass, SERVLETREQUEST_REMOTEADDR_MET, STRINGRETURN_SIG);
|
||||||
jstring remoteAddrJStr = (jstring) (env)->CallObjectMethod(servletRequest, getRemoteAddr);
|
jstring remoteAddrJStr = (jstring) (env)->CallObjectMethod(servletRequest, getRemoteAddr);
|
||||||
char *remoteAddr = (char*) (env)->GetStringUTFChars(remoteAddrJStr, 0);
|
char *remoteAddr = fromJString(env, remoteAddrJStr, r->pool);
|
||||||
apr_pool_cleanup_register(r->pool, remoteAddr, memCleanup, apr_pool_cleanup_null);
|
//apr_pool_cleanup_register(r->pool, remoteAddr, memCleanup, apr_pool_cleanup_null);
|
||||||
|
|
||||||
#if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER < 3
|
#if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER < 3
|
||||||
c->remote_addr = CopySockAddr(modSecurityClass, env, r->pool, remoteAddr, remoteAddrJStr);
|
c->remote_addr = CopySockAddr(modSecurityClass, env, r->pool, remoteAddr, remoteAddrJStr);
|
||||||
@@ -472,13 +490,58 @@ JNIEXPORT jint JNICALL Java_org_modsecurity_ModSecurity_onRequest(JNIEnv *env, j
|
|||||||
#endif
|
#endif
|
||||||
c->remote_host = NULL;
|
c->remote_host = NULL;
|
||||||
|
|
||||||
|
|
||||||
int status = modsecProcessRequest(r);
|
int status = modsecProcessRequest(r);
|
||||||
|
|
||||||
(env)->ReleaseStringUTFChars(remoteAddrJStr, remoteAddr);
|
|
||||||
(env)->ReleaseStringUTFChars(configPath, path);
|
(env)->ReleaseStringUTFChars(configPath, path);
|
||||||
(env)->ReleaseStringUTFChars(requestID, reqID);
|
|
||||||
(env)->DeleteLocalRef(inputStream);
|
(env)->DeleteLocalRef(inputStream);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
JNIEXPORT jint JNICALL Java_org_modsecurity_ModSecurity_onResponse(JNIEnv *env, jobject obj, jobject servletResponse, jobject httpServletResponse, jstring requestID)
|
||||||
|
{
|
||||||
|
const char *reqID = env->GetStringUTFChars(requestID, NULL);
|
||||||
|
request_rec *r = (request_rec*) apr_table_get(requests, reqID);
|
||||||
|
|
||||||
|
if (r == NULL)
|
||||||
|
{
|
||||||
|
env->ReleaseStringUTFChars(requestID, reqID);
|
||||||
|
return DONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
jclass httpServletResponseClass = env->GetObjectClass(httpServletResponse); //HttpServletResponse interface
|
||||||
|
jclass servletResponseClass = env->GetObjectClass(servletResponse); //ServletResponse interface
|
||||||
|
jclass modSecurityClass = env->GetObjectClass(obj); //ModSecurity class
|
||||||
|
|
||||||
|
jmethodID getContentType = (env)->GetMethodID(servletResponseClass, SERVLETRESPONSE_CONTENTTYPE_MET, STRINGRETURN_SIG);
|
||||||
|
char *ct = fromJStringMethod(env, getContentType, servletResponse, r->pool);
|
||||||
|
if(strcmp(ct, "") == 0)
|
||||||
|
ct = "text/html";
|
||||||
|
r->content_type = ct;
|
||||||
|
|
||||||
|
|
||||||
|
jmethodID getCharEncoding = (env)->GetMethodID(servletResponseClass, SERVLETRESPONSE_CHARENCODING_MET, STRINGRETURN_SIG);
|
||||||
|
r->content_encoding = fromJStringMethod(env, getCharEncoding, servletResponse, r->pool);
|
||||||
|
|
||||||
|
|
||||||
|
setHeaders(env, modSecurityClass, httpServletResponse, r->headers_out, r->pool, MODSECURITY__HTTPRESHEADERS_MET, MODSECURITY__HTTPRESHEADERS_SIG);
|
||||||
|
|
||||||
|
const char *lng = apr_table_get(r->headers_out, "Content-Languages");
|
||||||
|
if(lng != NULL)
|
||||||
|
{
|
||||||
|
r->content_languages = apr_array_make(r->pool, 1, sizeof(const char *));
|
||||||
|
*(const char **)apr_array_push(r->content_languages) = lng;
|
||||||
|
}
|
||||||
|
|
||||||
|
//modsecProcessResponse(r);
|
||||||
|
|
||||||
|
apr_table_unset(requests, reqID); //remove this request from the requests table
|
||||||
|
modsecFinishRequest(r);
|
||||||
|
|
||||||
|
env->ReleaseStringUTFChars(requestID, reqID);
|
||||||
|
|
||||||
|
return DONE;
|
||||||
}
|
}
|
||||||
@@ -7,6 +7,12 @@
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
#undef org_modsecurity_ModSecurity_DONE
|
||||||
|
#define org_modsecurity_ModSecurity_DONE -2L
|
||||||
|
#undef org_modsecurity_ModSecurity_DECLINED
|
||||||
|
#define org_modsecurity_ModSecurity_DECLINED -1L
|
||||||
|
#undef org_modsecurity_ModSecurity_OK
|
||||||
|
#define org_modsecurity_ModSecurity_OK 0L
|
||||||
/*
|
/*
|
||||||
* Class: org_modsecurity_ModSecurity
|
* Class: org_modsecurity_ModSecurity
|
||||||
* Method: initialize
|
* Method: initialize
|
||||||
@@ -31,6 +37,14 @@ JNIEXPORT jint JNICALL Java_org_modsecurity_ModSecurity_destroy
|
|||||||
JNIEXPORT jint JNICALL Java_org_modsecurity_ModSecurity_onRequest
|
JNIEXPORT jint JNICALL Java_org_modsecurity_ModSecurity_onRequest
|
||||||
(JNIEnv *, jobject, jstring, jobject, jobject, jstring, jboolean);
|
(JNIEnv *, jobject, jstring, jobject, jobject, jstring, jboolean);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_modsecurity_ModSecurity
|
||||||
|
* Method: onResponse
|
||||||
|
* Signature: (Ljavax/servlet/ServletResponse;Ljavax/servlet/http/HttpServletResponse;Ljava/lang/String)I
|
||||||
|
*/
|
||||||
|
JNIEXPORT jint JNICALL Java_org_modsecurity_ModSecurity_onResponse
|
||||||
|
(JNIEnv *, jobject, jobject, jobject, jstring);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user