mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-09-29 19:24:29 +03:00
Very first commit: libmodsecurity
Check the README.md file for further information about the libmodsecurity.
This commit is contained in:
0
test/.empty
Normal file
0
test/.empty
Normal file
55
test/Makefile.am
Normal file
55
test/Makefile.am
Normal file
@@ -0,0 +1,55 @@
|
||||
|
||||
ACLOCAL_AMFLAGS = -I build
|
||||
|
||||
|
||||
SUBDIRS = \
|
||||
benchmark
|
||||
|
||||
# make clean
|
||||
CLEANFILES =
|
||||
|
||||
# make maintainer-clean
|
||||
MAINTAINERCLEANFILES = \
|
||||
Makefile.in
|
||||
|
||||
|
||||
|
||||
bin_PROGRAMS = unit-tests regression-tests
|
||||
|
||||
# unit_tests
|
||||
|
||||
unit_tests_SOURCES = \
|
||||
unit/unit.cc \
|
||||
unit/unit_test.cc
|
||||
|
||||
unit_tests_LDADD = \
|
||||
$(top_builddir)/src/.libs/libmodsecurity.a \
|
||||
$(YAJL_LDADD)
|
||||
|
||||
unit_tests_CPPFLAGS = \
|
||||
-std=c++11 \
|
||||
-Icommon \
|
||||
-O0 \
|
||||
-g \
|
||||
-I$(top_builddir)/headers \
|
||||
$(YAJL_CFLAGS)
|
||||
|
||||
# regression
|
||||
|
||||
regression_tests_SOURCES = \
|
||||
regression/regression.cc \
|
||||
regression/regression_test.cc \
|
||||
regression/custom_debug_log.cc
|
||||
|
||||
regression_tests_LDADD = \
|
||||
$(top_builddir)/src/.libs/libmodsecurity.a \
|
||||
$(YAJL_LDADD)
|
||||
|
||||
regression_tests_CPPFLAGS = \
|
||||
-std=c++11 \
|
||||
-Icommon \
|
||||
-O0 \
|
||||
-g \
|
||||
-I$(top_builddir)/headers \
|
||||
$(YAJL_CFLAGS)
|
||||
|
17
test/benchmark/Makefile.am
Normal file
17
test/benchmark/Makefile.am
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
|
||||
bin_PROGRAMS = benchmark
|
||||
|
||||
benchmark_SOURCES = \
|
||||
benchmark.cc
|
||||
|
||||
benchmark_LDADD = \
|
||||
$(top_builddir)/src/.libs/libmodsecurity.a
|
||||
|
||||
benchmark_CPPFLAGS = \
|
||||
-std=c++11 \
|
||||
-I$(top_builddir)/headers
|
||||
|
||||
MAINTAINERCLEANFILES = \
|
||||
Makefile.in
|
||||
|
3
test/benchmark/basic_rules.conf
Normal file
3
test/benchmark/basic_rules.conf
Normal file
@@ -0,0 +1,3 @@
|
||||
SecRule ARGS "@contains /test.txt" "allow"
|
||||
SecRule ARGS:teste "@contains /test.txt" " allow,deny"
|
||||
SecRule ARGS "@contains /test.txt" "allow, allow,deny"
|
163
test/benchmark/benchmark.cc
Normal file
163
test/benchmark/benchmark.cc
Normal file
@@ -0,0 +1,163 @@
|
||||
/**
|
||||
* ModSecurity, http://www.modsecurity.org/
|
||||
* Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
||||
*
|
||||
* You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* If any of the files related to licensing are missing or if you have any
|
||||
* other questions related to licensing please contact Trustwave Holdings, Inc.
|
||||
* directly using the email address security@modsecurity.org.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include "modsecurity/modsecurity.h"
|
||||
#include "modsecurity/rules.h"
|
||||
|
||||
using ModSecurity::Assay;
|
||||
|
||||
char request_header[] = "" \
|
||||
"GET /tutorials/other/top-20-mysql-best-practices/ HTTP/1.1\n\r" \
|
||||
"Host: net.tutsplus.com\n\r" \
|
||||
"User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5)" \
|
||||
" Gecko/20091102 Firefox/3.5.5 (.NET CLR 3.5.30729)\n\r" \
|
||||
"Accept: text/html,application/xhtml+xml,application/xml; " \
|
||||
"q=0.9,*/*;q=0.8\n\r" \
|
||||
"Accept-Language: en-us,en;q=0.5\n\r" \
|
||||
"Accept-Encoding: gzip,deflate\n\r" \
|
||||
"Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\n\r" \
|
||||
"Keep-Alive: 300\n\r" \
|
||||
"Connection: keep-alive\n\r" \
|
||||
"Cookie: PHPSESSID=r2t5uvjq435r4q7ib3vtdjq120\n\r" \
|
||||
"Pragma: no-cache\n\r" \
|
||||
"Cache-Control: no-cache\n\r";
|
||||
|
||||
char request_uri[] = "GET /test.pl?param1=test¶2=test2";
|
||||
|
||||
char request_body[] = "";
|
||||
|
||||
char response_headers[] = "" \
|
||||
"HTTP/1.1 200 OK\n\r" \
|
||||
"Content-Type: text/xml; charset=utf-8\n\r" \
|
||||
"Content-Length: length\n\r";
|
||||
|
||||
unsigned char response_body[] = "" \
|
||||
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\r" \
|
||||
"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " \
|
||||
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" " \
|
||||
"xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n\r" \
|
||||
" <soap:Body>\n\r" \
|
||||
" <EnlightenResponse xmlns=\"http://clearforest.com/\">\n\r" \
|
||||
" <EnlightenResult>string</EnlightenResult>\n\r" \
|
||||
" </EnlightenResponse>\n\r" \
|
||||
" </soap:Body>\n\r" \
|
||||
"</soap:Envelope>\n\r";
|
||||
|
||||
char ip[] = "200.249.12.31";
|
||||
|
||||
char rules_file[] = "basic_rules.conf";
|
||||
|
||||
|
||||
#define NUM_REQUESTS 1000
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int i = 0;
|
||||
ModSecurity::ModSecurity *modsec;
|
||||
ModSecurity::Rules *rules;
|
||||
|
||||
modsec = new ModSecurity::ModSecurity();
|
||||
rules = new ModSecurity::Rules();
|
||||
rules->loadFromUri(rules_file);
|
||||
|
||||
for (i = 0; i < NUM_REQUESTS; i++) {
|
||||
std::cout << "Proceding with request " << i << std::endl;
|
||||
|
||||
Assay *modsecAssay = new Assay(modsec, rules);
|
||||
modsecAssay->processConnection(ip);
|
||||
|
||||
if (modsecAssay->intervention()) {
|
||||
std::cout << "There is an intervention" << std::endl;
|
||||
continue;
|
||||
}
|
||||
modsecAssay->processURI(request_uri);
|
||||
if (modsecAssay->intervention()) {
|
||||
std::cout << "There is an intervention" << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
modsecAssay->addRequestHeader((char *) "Host",
|
||||
(char *) "net.tutsplus.com");
|
||||
modsecAssay->addRequestHeader((char *) "User-Agent", (char *)
|
||||
"Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) " \
|
||||
"Gecko/20091102 Firefox/3.5.5 (.NET CLR 3.5.30729)\n\r");
|
||||
modsecAssay->addRequestHeader((char *) "Accept",
|
||||
(char *) "text/html,application/xhtml+xml,application/xml;" \
|
||||
"q=0.9,*/*;q=0.8");
|
||||
modsecAssay->addRequestHeader((char *) "Accept-Language",
|
||||
(char *) "en-us,en;q=0.5");
|
||||
modsecAssay->addRequestHeader((char *) "Accept-Encoding",
|
||||
(char *) "gzip,deflate");
|
||||
modsecAssay->addRequestHeader((char *) "Accept-Charset",
|
||||
(char *) "ISO-8859-1,utf-8;q=0.7,*;q=0.7");
|
||||
modsecAssay->addRequestHeader((char *) "Keep-Alive",
|
||||
(char *) "300");
|
||||
modsecAssay->addRequestHeader((char *) "Connection",
|
||||
(char *) "keep-alive");
|
||||
modsecAssay->addRequestHeader((char *) "Cookie",
|
||||
(char *) "PHPSESSID=r2t5uvjq435r4q7ib3vtdjq120");
|
||||
modsecAssay->addRequestHeader((char *) "Pragma",
|
||||
(char *) "no-cache");
|
||||
modsecAssay->addRequestHeader((char *) "Cache-Control",
|
||||
(char *) "no-cache");
|
||||
modsecAssay->processRequestHeaders();
|
||||
|
||||
if (modsecAssay->intervention()) {
|
||||
std::cout << "There is an intervention" << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
modsecAssay->processRequestBody();
|
||||
|
||||
if (modsecAssay->intervention()) {
|
||||
std::cout << "There is an intervention" << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
modsecAssay->addResponseHeader((char *) "HTTP/1.1",
|
||||
(char *) "200 OK");
|
||||
modsecAssay->addResponseHeader((char *) "Content-Type",
|
||||
(char *) "text/xml; charset=utf-8");
|
||||
modsecAssay->addResponseHeader((char *) "Content-Length",
|
||||
(char *) "200");
|
||||
|
||||
modsecAssay->processResponseHeaders();
|
||||
|
||||
if (modsecAssay->intervention()) {
|
||||
std::cout << "There is an intervention" << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
modsecAssay->appendResponseBody(response_body,
|
||||
strlen((const char*)response_body));
|
||||
modsecAssay->processResponseBody();
|
||||
|
||||
if (modsecAssay->intervention()) {
|
||||
std::cout << "There is an intervention" << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
delete modsecAssay;
|
||||
}
|
||||
|
||||
delete modsec;
|
||||
}
|
31
test/common/colors.h
Normal file
31
test/common/colors.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* ModSecurity, http://www.modsecurity.org/
|
||||
* Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
||||
*
|
||||
* You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* If any of the files related to licensing are missing or if you have any
|
||||
* other questions related to licensing please contact Trustwave Holdings, Inc.
|
||||
* directly using the email address security@modsecurity.org.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TEST_COMMON_COLORS_H_
|
||||
#define TEST_COMMON_COLORS_H_
|
||||
|
||||
|
||||
#define KNRM "\x1B[0m"
|
||||
#define KRED "\x1B[31m"
|
||||
#define KGRN "\x1B[32m"
|
||||
#define KYEL "\x1B[33m"
|
||||
#define KBLU "\x1B[34m"
|
||||
#define KMAG "\x1B[35m"
|
||||
#define KCYN "\x1B[36m"
|
||||
#define KWHT "\x1B[37m"
|
||||
#define RESET "\033[0m"
|
||||
|
||||
|
||||
#endif // TEST_COMMON_COLORS_H_
|
153
test/common/modsecurity_test.cc
Normal file
153
test/common/modsecurity_test.cc
Normal file
@@ -0,0 +1,153 @@
|
||||
/**
|
||||
* ModSecurity, http://www.modsecurity.org/
|
||||
* Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
||||
*
|
||||
* You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* If any of the files related to licensing are missing or if you have any
|
||||
* other questions related to licensing please contact Trustwave Holdings, Inc.
|
||||
* directly using the email address security@modsecurity.org.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/modsecurity_test.h"
|
||||
|
||||
#include <yajl/yajl_tree.h>
|
||||
#include <dirent.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <cstdlib>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "modsecurity/modsecurity.h"
|
||||
|
||||
namespace modsecurity_test {
|
||||
|
||||
template <class T>
|
||||
std::string ModSecurityTest<T>::header() {
|
||||
std::stringstream i;
|
||||
|
||||
i << "ModSecurity " << MODSECURITY_VERSION << " - tests" << std::endl;
|
||||
#if not HAS_GETOPT
|
||||
i << "(options are not available -- missing GetOpt)" << std::endl;
|
||||
#endif
|
||||
i << std::endl;
|
||||
|
||||
return i.str();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool ModSecurityTest<T>::load_test_json(std::string file) {
|
||||
std::vector<yajl_val> tests;
|
||||
char errbuf[1024];
|
||||
yajl_val node;
|
||||
|
||||
std::ifstream myfile;
|
||||
myfile.open(file.c_str());
|
||||
if (myfile.is_open() == false) {
|
||||
std::cout << "Problems opening file: " << file << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string str((std::istreambuf_iterator<char>(myfile)),
|
||||
std::istreambuf_iterator<char>());
|
||||
node = yajl_tree_parse((const char *) str.c_str(), errbuf, sizeof(errbuf));
|
||||
if (node == NULL) {
|
||||
std::cout << "Problems parsing file: " << file << std::endl;
|
||||
if (strlen(errbuf) > 0) {
|
||||
std::cout << errbuf << std::endl;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t num_tests = node->u.array.len;
|
||||
for ( int i = 0; i < num_tests; i++ ) {
|
||||
yajl_val obj = node->u.array.values[i];
|
||||
|
||||
T *u = T::from_yajl_node(obj);
|
||||
u->filename = file;
|
||||
u->name = u->filename + ":" + u->name;
|
||||
|
||||
if (this->count(u->name) == 0) {
|
||||
std::vector<T *> *vector = new std::vector<T *>;
|
||||
vector->push_back(u);
|
||||
std::pair<std::string, std::vector<T *> *> a(u->name, vector);
|
||||
this->insert(a);
|
||||
} else {
|
||||
std::vector<T *> *vec = this->at(u->name);
|
||||
vec->push_back(u);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <class T>
|
||||
std::pair<std::string, std::vector<T *>>* ModSecurityTest<T>::load_tests() {
|
||||
DIR *dir;
|
||||
struct dirent *ent;
|
||||
|
||||
if ((dir = opendir(this->target_folder.c_str())) == NULL) {
|
||||
std::cout << "Problems opening directory: " << this->target_folder;
|
||||
std::cout << std::endl;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while ((ent = readdir(dir)) != NULL) {
|
||||
std::string filename = ent->d_name;
|
||||
std::string json = ".json";
|
||||
if (filename.size() < json.size()
|
||||
|| !std::equal(json.rbegin(), json.rend(), filename.rbegin())) {
|
||||
continue;
|
||||
}
|
||||
if (load_test_json(this->target_folder + "/" + filename) == false) {
|
||||
std::cout << "Problems loading tests from: " << filename;
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void ModSecurityTest<T>::cmd_options(int argc, char **argv) {
|
||||
int option_char;
|
||||
|
||||
#if HAS_GETOPT
|
||||
GetOpt getopt(argc, argv, "hvct:");
|
||||
|
||||
while ((option_char = getopt()) != EOF) {
|
||||
switch (option_char) {
|
||||
case 'h':
|
||||
print_help();
|
||||
return;
|
||||
break;
|
||||
case 'v':
|
||||
this->verbose = true;
|
||||
break;
|
||||
case 'c':
|
||||
this->color = false;
|
||||
break;
|
||||
case 't':
|
||||
this->target_folder = getopt.optarg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (argv[1]) {
|
||||
this->target_folder = argv[1];
|
||||
} else {
|
||||
this->target_folder = default_test_path;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace modsecurity_test
|
49
test/common/modsecurity_test.h
Normal file
49
test/common/modsecurity_test.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* ModSecurity, http://www.modsecurity.org/
|
||||
* Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
||||
*
|
||||
* You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* If any of the files related to licensing are missing or if you have any
|
||||
* other questions related to licensing please contact Trustwave Holdings, Inc.
|
||||
* directly using the email address security@modsecurity.org.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
#ifndef TEST_COMMON_MODSECURITY_TEST_H_
|
||||
#define TEST_COMMON_MODSECURITY_TEST_H_
|
||||
|
||||
|
||||
extern void print_help();
|
||||
extern std::string default_test_path;
|
||||
|
||||
namespace modsecurity_test {
|
||||
|
||||
template <class T> class ModSecurityTest :
|
||||
public std::unordered_map<std::string, std::vector<T *> *> {
|
||||
public:
|
||||
std::string header();
|
||||
void cmd_options(int, char **);
|
||||
std::pair<std::string, std::vector<T *>>* load_tests();
|
||||
bool load_test_json(std::string);
|
||||
|
||||
std::string target_folder;
|
||||
bool verbose = false;
|
||||
bool color = false;
|
||||
};
|
||||
|
||||
} // namespace modsecurity_test
|
||||
|
||||
#include "modsecurity_test.cc"
|
||||
|
||||
|
||||
#endif // TEST_COMMON_MODSECURITY_TEST_H_
|
35
test/common/modsecurity_test_results.h
Normal file
35
test/common/modsecurity_test_results.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* ModSecurity, http://www.modsecurity.org/
|
||||
* Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
||||
*
|
||||
* You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* If any of the files related to licensing are missing or if you have any
|
||||
* other questions related to licensing please contact Trustwave Holdings, Inc.
|
||||
* directly using the email address security@modsecurity.org.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#ifndef TEST_COMMON_MODSECURITY_TEST_RESULTS_H_
|
||||
#define TEST_COMMON_MODSECURITY_TEST_RESULTS_H_
|
||||
|
||||
namespace modsecurity_test {
|
||||
|
||||
template <class T> class ModSecurityTestResults : public std::vector<T *> {
|
||||
public:
|
||||
std::string log_raw_debug_log;
|
||||
int status;
|
||||
std::string location;
|
||||
};
|
||||
|
||||
} // namespace modsecurity_test
|
||||
|
||||
#endif // TEST_COMMON_MODSECURITY_TEST_RESULTS_H_
|
48
test/regression/custom_debug_log.cc
Normal file
48
test/regression/custom_debug_log.cc
Normal file
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* ModSecurity, http://www.modsecurity.org/
|
||||
* Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
||||
*
|
||||
* You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* If any of the files related to licensing are missing or if you have any
|
||||
* other questions related to licensing please contact Trustwave Holdings, Inc.
|
||||
* directly using the email address security@modsecurity.org.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "regression/custom_debug_log.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <regex>
|
||||
|
||||
#include "modsecurity/debug_log.h"
|
||||
|
||||
namespace modsecurity_test {
|
||||
|
||||
CustomDebugLog *CustomDebugLog::new_instance() {
|
||||
return new CustomDebugLog();
|
||||
}
|
||||
|
||||
|
||||
bool CustomDebugLog::write_log(int level, const std::string& message) {
|
||||
m_log << "[" << level << "] " << message << std::endl;
|
||||
}
|
||||
|
||||
|
||||
bool CustomDebugLog::contains(const std::string& pattern) {
|
||||
std::regex re(pattern);
|
||||
std::smatch match;
|
||||
|
||||
return (std::regex_search(m_log.str(), match, re) && match.size() >= 1);
|
||||
}
|
||||
|
||||
std::string CustomDebugLog::log_messages() {
|
||||
return m_log.str();
|
||||
}
|
||||
|
||||
|
||||
} // namespace modsecurity_test
|
40
test/regression/custom_debug_log.h
Normal file
40
test/regression/custom_debug_log.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* ModSecurity, http://www.modsecurity.org/
|
||||
* Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
||||
*
|
||||
* You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* If any of the files related to licensing are missing or if you have any
|
||||
* other questions related to licensing please contact Trustwave Holdings, Inc.
|
||||
* directly using the email address security@modsecurity.org.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "modsecurity/debug_log.h"
|
||||
|
||||
#ifndef TEST_REGRESSION_CUSTOM_DEBUG_LOG_H_
|
||||
#define TEST_REGRESSION_CUSTOM_DEBUG_LOG_H_
|
||||
|
||||
namespace modsecurity_test {
|
||||
|
||||
class CustomDebugLog : public ModSecurity::DebugLog {
|
||||
public:
|
||||
CustomDebugLog *new_instance();
|
||||
|
||||
bool write_log(int level, const std::string& message) override;
|
||||
bool contains(const std::string& pattern);
|
||||
std::string log_messages();
|
||||
|
||||
private:
|
||||
std::stringstream m_log;
|
||||
};
|
||||
|
||||
} // namespace modsecurity_test
|
||||
|
||||
#endif // TEST_REGRESSION_CUSTOM_DEBUG_LOG_H_
|
199
test/regression/regression.cc
Normal file
199
test/regression/regression.cc
Normal file
@@ -0,0 +1,199 @@
|
||||
/**
|
||||
* ModSecurity, http://www.modsecurity.org/
|
||||
* Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
||||
*
|
||||
* You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* If any of the files related to licensing are missing or if you have any
|
||||
* other questions related to licensing please contact Trustwave Holdings, Inc.
|
||||
* directly using the email address security@modsecurity.org.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include "modsecurity/modsecurity.h"
|
||||
#include "modsecurity/rules.h"
|
||||
|
||||
#include "common/modsecurity_test.h"
|
||||
#include "regression/regression_test.h"
|
||||
#include "common/modsecurity_test_results.h"
|
||||
#include "regression/custom_debug_log.h"
|
||||
|
||||
using modsecurity_test::CustomDebugLog;
|
||||
using modsecurity_test::ModSecurityTest;
|
||||
using modsecurity_test::ModSecurityTestResults;
|
||||
using modsecurity_test::RegressionTest;
|
||||
|
||||
std::string default_test_path = "test-cases/regression";
|
||||
|
||||
void print_help() {
|
||||
std::cout << "Use ./regression-tests /path/to/file" << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
|
||||
void actions(ModSecurityTestResults<RegressionTest> *r,
|
||||
ModSecurity::ModSecurityIntervention *it) {
|
||||
if (it != NULL) {
|
||||
if (it->pause != 0) {
|
||||
// FIXME:
|
||||
}
|
||||
if (it->status != 0) {
|
||||
r->status = it->status;
|
||||
}
|
||||
if (it->url != NULL) {
|
||||
r->location = it->url;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void perform_unit_test(std::vector<RegressionTest *> *tests,
|
||||
ModSecurityTestResults<RegressionTest> *res) {
|
||||
ModSecurity::ModSecurity *modsec;
|
||||
ModSecurity::Rules *modsec_rules;
|
||||
ModSecurity::Assay *modsec_assay;
|
||||
|
||||
CustomDebugLog *debug_log = new CustomDebugLog();
|
||||
|
||||
for (RegressionTest *t : *tests) {
|
||||
ModSecurityTestResults<RegressionTest> r;
|
||||
r.status = 200;
|
||||
|
||||
modsec = new ModSecurity::ModSecurity();
|
||||
modsec_rules = new ModSecurity::Rules(debug_log);
|
||||
|
||||
if (modsec_rules->load((char *)(t->rules.c_str())) == false) {
|
||||
std::cerr << "Problems parsing the rules, aborting!" << std::endl;
|
||||
return;
|
||||
}
|
||||
modsec_assay = new ModSecurity::Assay(modsec, modsec_rules);
|
||||
|
||||
if (t->ip.empty() == false) {
|
||||
// FIXME: no cast please.
|
||||
modsec_assay->processConnection((char *)(t->ip.c_str()));
|
||||
actions(&r, modsec_assay->intervention());
|
||||
if (r.status != 200) {
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
if (t->uri.empty() == false) {
|
||||
modsec_assay->processURI((char *)(t->uri.c_str()));
|
||||
actions(&r, modsec_assay->intervention());
|
||||
if (r.status != 200) {
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
for (std::pair<std::string, std::string> headers :
|
||||
t->request_headers) {
|
||||
modsec_assay->addRequestHeader((char *)headers.first.c_str(),
|
||||
(char *)headers.second.c_str());
|
||||
}
|
||||
|
||||
modsec_assay->processRequestHeaders();
|
||||
actions(&r, modsec_assay->intervention());
|
||||
if (r.status != 200) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
modsec_assay->appendRequestBody(
|
||||
(unsigned char *)t->request_body.c_str(),
|
||||
t->request_body.size());
|
||||
modsec_assay->processRequestBody();
|
||||
actions(&r, modsec_assay->intervention());
|
||||
if (r.status != 200) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
for (std::pair<std::string, std::string> headers :
|
||||
t->response_headers) {
|
||||
modsec_assay->addResponseHeader((char *)headers.first.c_str(),
|
||||
(char *)headers.second.c_str());
|
||||
}
|
||||
|
||||
modsec_assay->processResponseHeaders();
|
||||
actions(&r, modsec_assay->intervention());
|
||||
if (r.status != 200) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
modsec_assay->appendResponseBody(
|
||||
(unsigned char *)t->response_body.c_str(),
|
||||
t->response_body.size());
|
||||
modsec_assay->processResponseBody();
|
||||
actions(&r, modsec_assay->intervention());
|
||||
if (r.status != 200) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
end:
|
||||
CustomDebugLog *d = reinterpret_cast<CustomDebugLog *>
|
||||
(modsec_rules->debug_log);
|
||||
|
||||
std::cout << "- " << t->name << " ...";
|
||||
|
||||
if (!d->contains(t->debug_log)) {
|
||||
std::cout << "Debug log was not matching the expected results.";
|
||||
std::cout << std::endl;
|
||||
} else if (r.status != t->http_code) {
|
||||
std::cout << "HTTP code mismatch. expecting: " + \
|
||||
std::to_string(t->http_code) + \
|
||||
" got: " + std::to_string(r.status) + "\n";
|
||||
} else {
|
||||
std::cout << "passed!" << std::endl;
|
||||
goto after_debug_log;
|
||||
}
|
||||
|
||||
std::cout << "Debug log:" << std::endl;
|
||||
std::cout << "" << d->log_messages() << "" <<std::endl;
|
||||
after_debug_log:
|
||||
|
||||
res->log_raw_debug_log = d->log_messages();
|
||||
|
||||
delete modsec_assay;
|
||||
delete modsec_rules;
|
||||
delete modsec;
|
||||
|
||||
res->insert(res->end(), r.begin(), r.end());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
ModSecurityTest<RegressionTest> test;
|
||||
ModSecurityTestResults<RegressionTest> results;
|
||||
|
||||
test.cmd_options(argc, argv);
|
||||
std::cout << test.header();
|
||||
|
||||
test.load_tests();
|
||||
|
||||
std::ofstream test_log;
|
||||
test_log.open("regression_test_log.txt");
|
||||
|
||||
for (std::pair<std::string, std::vector<RegressionTest *> *> a : test) {
|
||||
std::vector<RegressionTest *> *tests = a.second;
|
||||
ModSecurityTestResults<RegressionTest> res;
|
||||
|
||||
perform_unit_test(tests, &res);
|
||||
|
||||
test_log << res.log_raw_debug_log;
|
||||
}
|
||||
|
||||
test_log.close();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
180
test/regression/regression_test.cc
Normal file
180
test/regression/regression_test.cc
Normal file
@@ -0,0 +1,180 @@
|
||||
/**
|
||||
* ModSecurity, http://www.modsecurity.org/
|
||||
* Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
||||
*
|
||||
* You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* If any of the files related to licensing are missing or if you have any
|
||||
* other questions related to licensing please contact Trustwave Holdings, Inc.
|
||||
* directly using the email address security@modsecurity.org.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "regression/regression_test.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <sstream>
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
|
||||
namespace modsecurity_test {
|
||||
|
||||
std::string RegressionTest::print() {
|
||||
std::stringstream i;
|
||||
|
||||
#if 0
|
||||
i << KRED << "Test failed." << RESET << " From: " \
|
||||
i << this->filename << std::endl;
|
||||
i << "{" << std::endl;
|
||||
i << " \"ret\": \"" << this->ret << "\"" << std::endl;
|
||||
i << " \"type\": \"" << this->type << "\"" << std::endl;
|
||||
i << " \"name\": \"" << this->name << "\"" << std::endl;
|
||||
i << " \"input\": \"" << this->input << "\"" << std::endl;
|
||||
i << " \"param\": \"" << this->param << "\"" << std::endl;
|
||||
i << "}" << std::endl;
|
||||
i << "Expecting: " << this->ret << " - operator returned: " << \
|
||||
this->obtained << std::endl;
|
||||
#endif
|
||||
return i.str();
|
||||
}
|
||||
|
||||
|
||||
inline std::string RegressionTest::yajl_array_to_str(const yajl_val &node) {
|
||||
std::stringstream i;
|
||||
for (int z = 0; z < node->u.array.len; z++) {
|
||||
yajl_val val3 = node->u.array.values[z];
|
||||
const char *key = YAJL_GET_STRING(val3);
|
||||
i << key << "\n";
|
||||
}
|
||||
return i.str();
|
||||
}
|
||||
|
||||
|
||||
inline std::vector<std::string> RegressionTest::yajl_array_to_vec_str(
|
||||
const yajl_val &node) {
|
||||
std::vector<std::string> vec;
|
||||
for (int z = 0; z < node->u.array.len; z++) {
|
||||
yajl_val val3 = node->u.array.values[z];
|
||||
const char *key = YAJL_GET_STRING(val3);
|
||||
vec.push_back(key);
|
||||
}
|
||||
return vec;
|
||||
}
|
||||
|
||||
|
||||
inline std::unordered_map<std::string, std::string>
|
||||
RegressionTest::yajl_array_to_map(const yajl_val &node) {
|
||||
std::unordered_map<std::string, std::string> vec;
|
||||
for (int z = 0; z < node->u.object.len; z++) {
|
||||
const char *key = node->u.object.keys[z];
|
||||
yajl_val val3 = node->u.object.values[z];
|
||||
const char *value = YAJL_GET_STRING(val3);
|
||||
std::pair<std::string, std::string> a(key, value);
|
||||
vec.insert(a);
|
||||
}
|
||||
return vec;
|
||||
}
|
||||
|
||||
|
||||
RegressionTest *RegressionTest::from_yajl_node(const yajl_val &node) {
|
||||
size_t nelem = node->u.object.len;
|
||||
RegressionTest *u = new RegressionTest();
|
||||
u->http_code = 200;
|
||||
|
||||
for (int i = 0; i < nelem; i++) {
|
||||
const char *key = node->u.object.keys[ i ];
|
||||
yajl_val val = node->u.object.values[ i ];
|
||||
|
||||
if (strcmp(key, "enabled") == 0) {
|
||||
u->enabled = YAJL_GET_INTEGER(val);
|
||||
}
|
||||
if (strcmp(key, "version_min") == 0) {
|
||||
u->version_min = YAJL_GET_INTEGER(val);
|
||||
}
|
||||
if (strcmp(key, "version_max") == 0) {
|
||||
u->version_max = YAJL_GET_INTEGER(val);
|
||||
}
|
||||
if (strcmp(key, "title") == 0) {
|
||||
u->title = YAJL_GET_STRING(val);
|
||||
}
|
||||
if (strcmp(key, "url") == 0) {
|
||||
u->url = YAJL_GET_STRING(val);
|
||||
}
|
||||
if (strcmp(key, "github_issue") == 0) {
|
||||
u->github_issue = YAJL_GET_INTEGER(val);
|
||||
}
|
||||
if (strcmp(key, "request") == 0) {
|
||||
for (int j = 0; j < val->u.object.len; j++) {
|
||||
const char *key2 = val->u.object.keys[j];
|
||||
yajl_val val2 = val->u.object.values[j];
|
||||
|
||||
if (strcmp(key2, "uri") == 0) {
|
||||
u->uri = YAJL_GET_STRING(val2);
|
||||
}
|
||||
if (strcmp(key2, "ip") == 0) {
|
||||
u->ip = YAJL_GET_STRING(val2);
|
||||
}
|
||||
if (strcmp(key2, "headers") == 0) {
|
||||
u->request_headers = yajl_array_to_map(val2);
|
||||
}
|
||||
if (strcmp(key2, "body") == 0) {
|
||||
u->request_body = yajl_array_to_str(val2);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (strcmp(key, "response") == 0) {
|
||||
for (int j = 0; j < val->u.object.len; j++) {
|
||||
const char *key2 = val->u.object.keys[j];
|
||||
yajl_val val2 = val->u.object.values[j];
|
||||
|
||||
if (strcmp(key2, "headers") == 0) {
|
||||
u->response_headers = yajl_array_to_map(val2);
|
||||
}
|
||||
if (strcmp(key2, "body") == 0) {
|
||||
u->response_body = yajl_array_to_str(val2);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (strcmp(key, "expected") == 0) {
|
||||
for (int j = 0; j < val->u.object.len; j++) {
|
||||
const char *key2 = val->u.object.keys[j];
|
||||
yajl_val val2 = val->u.object.values[j];
|
||||
|
||||
if (strcmp(key2, "audit_log") == 0) {
|
||||
u->audit_log = yajl_array_to_str(val2);
|
||||
}
|
||||
if (strcmp(key2, "debug_log") == 0) {
|
||||
u->debug_log = YAJL_GET_STRING(val2);
|
||||
}
|
||||
if (strcmp(key2, "error_log") == 0) {
|
||||
u->error_log = yajl_array_to_str(val2);
|
||||
}
|
||||
if (strcmp(key2, "http_code") == 0) {
|
||||
u->http_code = YAJL_GET_INTEGER(val2);
|
||||
}
|
||||
if (strcmp(key2, "redirect_url") == 0) {
|
||||
u->redirect_url = YAJL_GET_STRING(val2);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (strcmp(key, "rules") == 0) {
|
||||
std::stringstream i;
|
||||
for (int j = 0; j < val->u.array.len; j++) {
|
||||
yajl_val val2 = val->u.array.values[ j ];
|
||||
const char *key = YAJL_GET_STRING(val2);
|
||||
i << key << "\n";
|
||||
}
|
||||
u->rules = i.str();
|
||||
}
|
||||
}
|
||||
|
||||
u->name = u->title;
|
||||
|
||||
return u;
|
||||
}
|
||||
|
||||
} // namespace modsecurity_test
|
69
test/regression/regression_test.h
Normal file
69
test/regression/regression_test.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* ModSecurity, http://www.modsecurity.org/
|
||||
* Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
||||
*
|
||||
* You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* If any of the files related to licensing are missing or if you have any
|
||||
* other questions related to licensing please contact Trustwave Holdings, Inc.
|
||||
* directly using the email address security@modsecurity.org.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <yajl/yajl_tree.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#ifndef TEST_REGRESSION_REGRESSION_TEST_H_
|
||||
#define TEST_REGRESSION_REGRESSION_TEST_H_
|
||||
|
||||
namespace modsecurity_test {
|
||||
|
||||
class RegressionTest {
|
||||
public:
|
||||
static RegressionTest *from_yajl_node(const yajl_val &);
|
||||
|
||||
std::string print();
|
||||
std::string filename;
|
||||
std::string name;
|
||||
std::string title;
|
||||
|
||||
std::string rules;
|
||||
|
||||
std::string url;
|
||||
int enabled;
|
||||
int version_min;
|
||||
int version_max;
|
||||
int github_issue;
|
||||
|
||||
std::unordered_map<std::string, std::string> request_headers;
|
||||
std::unordered_map<std::string, std::string> response_headers;
|
||||
std::string request_body;
|
||||
std::string response_body;
|
||||
|
||||
std::string audit_log;
|
||||
std::string debug_log;
|
||||
std::string error_log;
|
||||
|
||||
std::string ip;
|
||||
std::string uri;
|
||||
|
||||
static inline std::string yajl_array_to_str(const yajl_val &node);
|
||||
static inline std::vector<std::string> yajl_array_to_vec_str(
|
||||
const yajl_val &node);
|
||||
static inline std::unordered_map<std::string,
|
||||
std::string> yajl_array_to_map(const yajl_val &node);
|
||||
|
||||
int http_code;
|
||||
std::string redirect_url;
|
||||
};
|
||||
|
||||
} // namespace modsecurity_test
|
||||
|
||||
#endif // TEST_REGRESSION_REGRESSION_TEST_H_
|
316
test/test-cases/regression/actions.json
Normal file
316
test/test-cases/regression/actions.json
Normal file
@@ -0,0 +1,316 @@
|
||||
[
|
||||
{
|
||||
"enabled": 1,
|
||||
"version_min": 300000,
|
||||
"version_max": 0,
|
||||
"title": "actions :: trim,block",
|
||||
"request": {
|
||||
"ip": "200.249.12.31",
|
||||
"headers": {
|
||||
"Host": "net.tutsplus.com",
|
||||
"User-Agent": "Mozilla\/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko\/20091102 Firefox\/3.5.5 (.NET CLR 3.5.30729)",
|
||||
"Accept": "text\/html,application\/xhtml+xml,application\/xml;q=0.9,*\/*;q=0.8",
|
||||
"Accept-Language": "en-us,en;q=0.5",
|
||||
"Accept-Encoding": "gzip,deflate",
|
||||
"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7",
|
||||
"Keep-Alive": "300",
|
||||
"Connection": "keep-alive",
|
||||
"Cookie": "PHPSESSID=r2t5uvjq435r4q7ib3vtdjq120",
|
||||
"Pragma": "no-cache",
|
||||
"Cache-Control": "no-cache"
|
||||
},
|
||||
"uri": "GET \/test.pl?param1= test ¶m2=test2",
|
||||
"body": ""
|
||||
},
|
||||
"response": {
|
||||
"headers": {
|
||||
"Content-Type": "text\/xml; charset=utf-8\n\r",
|
||||
"Content-Length": "length\n\r"
|
||||
},
|
||||
"body": [
|
||||
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\r",
|
||||
"<soap:Envelope xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\" xmlns:xsd=\"http:\/\/www.w3.org\/2001\/XMLSchema\" xmlns:soap=\"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/\">\n\r",
|
||||
" <soap:Body>\n\r",
|
||||
" <EnlightenResponse xmlns=\"http:\/\/clearforest.com\/\">\n\r",
|
||||
" <EnlightenResult>string<\/EnlightenResult>\n\r",
|
||||
" <\/EnlightenResponse>\n\r",
|
||||
" <\/soap:Body>\n\r",
|
||||
"<\/soap:Envelope>\n\r"
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"audit_log": "",
|
||||
"debug_log": "\\[9\\] T \\(0\\) trim: \"test\"",
|
||||
"error_log": "",
|
||||
"http_code": 403
|
||||
},
|
||||
"rules": [
|
||||
"SecRuleEngine On",
|
||||
"SecDebugLog \/tmp\/modsec_debug.log",
|
||||
"SecDebugLogLevel 9",
|
||||
"SecRule ARGS \"@contains test\" \"t:trim,block\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled": 1,
|
||||
"version_min": 300000,
|
||||
"version_max": 0,
|
||||
"title": "actions :: trim,redirect:http://www.google.com",
|
||||
"request": {
|
||||
"ip": "200.249.12.31",
|
||||
"headers": {
|
||||
"Host": "net.tutsplus.com",
|
||||
"User-Agent": "Mozilla\/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko\/20091102 Firefox\/3.5.5 (.NET CLR 3.5.30729)",
|
||||
"Accept": "text\/html,application\/xhtml+xml,application\/xml;q=0.9,*\/*;q=0.8",
|
||||
"Accept-Language": "en-us,en;q=0.5",
|
||||
"Accept-Encoding": "gzip,deflate",
|
||||
"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7",
|
||||
"Keep-Alive": "300",
|
||||
"Connection": "keep-alive",
|
||||
"Cookie": "PHPSESSID=r2t5uvjq435r4q7ib3vtdjq120",
|
||||
"Pragma": "no-cache",
|
||||
"Cache-Control": "no-cache"
|
||||
},
|
||||
"uri": "GET \/test.pl?param1= test ¶m2=test2",
|
||||
"body": ""
|
||||
},
|
||||
"response": {
|
||||
"headers": {
|
||||
"Content-Type": "text\/xml; charset=utf-8\n\r",
|
||||
"Content-Length": "length\n\r"
|
||||
},
|
||||
"body": [
|
||||
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\r",
|
||||
"<soap:Envelope xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\" xmlns:xsd=\"http:\/\/www.w3.org\/2001\/XMLSchema\" xmlns:soap=\"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/\">\n\r",
|
||||
" <soap:Body>\n\r",
|
||||
" <EnlightenResponse xmlns=\"http:\/\/clearforest.com\/\">\n\r",
|
||||
" <EnlightenResult>string<\/EnlightenResult>\n\r",
|
||||
" <\/EnlightenResponse>\n\r",
|
||||
" <\/soap:Body>\n\r",
|
||||
"<\/soap:Envelope>\n\r"
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"audit_log": "",
|
||||
"debug_log": "\\[9\\] T \\(0\\) trim: \"test\"",
|
||||
"error_log": "",
|
||||
"http_code": 302,
|
||||
"redirect_url": "http://www.google.com"
|
||||
},
|
||||
"rules": [
|
||||
"SecRuleEngine On",
|
||||
"SecDebugLog \/tmp\/modsec_debug.log",
|
||||
"SecDebugLogLevel 9",
|
||||
"SecRule ARGS \"@contains test\" \"t:trim,redirect:http://www.google.com\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled": 1,
|
||||
"version_min": 300000,
|
||||
"version_max": 0,
|
||||
"title": "actions :: trim,status:500,redirect:http://www.google.com",
|
||||
"request": {
|
||||
"ip": "200.249.12.31",
|
||||
"headers": {
|
||||
"Host": "net.tutsplus.com",
|
||||
"User-Agent": "Mozilla\/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko\/20091102 Firefox\/3.5.5 (.NET CLR 3.5.30729)",
|
||||
"Accept": "text\/html,application\/xhtml+xml,application\/xml;q=0.9,*\/*;q=0.8",
|
||||
"Accept-Language": "en-us,en;q=0.5",
|
||||
"Accept-Encoding": "gzip,deflate",
|
||||
"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7",
|
||||
"Keep-Alive": "300",
|
||||
"Connection": "keep-alive",
|
||||
"Cookie": "PHPSESSID=r2t5uvjq435r4q7ib3vtdjq120",
|
||||
"Pragma": "no-cache",
|
||||
"Cache-Control": "no-cache"
|
||||
},
|
||||
"uri": "GET \/test.pl?param1= test ¶m2=test2",
|
||||
"body": ""
|
||||
},
|
||||
"response": {
|
||||
"headers": {
|
||||
"Content-Type": "text\/xml; charset=utf-8\n\r",
|
||||
"Content-Length": "length\n\r"
|
||||
},
|
||||
"body": [
|
||||
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\r",
|
||||
"<soap:Envelope xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\" xmlns:xsd=\"http:\/\/www.w3.org\/2001\/XMLSchema\" xmlns:soap=\"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/\">\n\r",
|
||||
" <soap:Body>\n\r",
|
||||
" <EnlightenResponse xmlns=\"http:\/\/clearforest.com\/\">\n\r",
|
||||
" <EnlightenResult>string<\/EnlightenResult>\n\r",
|
||||
" <\/EnlightenResponse>\n\r",
|
||||
" <\/soap:Body>\n\r",
|
||||
"<\/soap:Envelope>\n\r"
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"audit_log": "",
|
||||
"debug_log": "\\[9\\] T \\(0\\) trim: \"test\"",
|
||||
"error_log": "",
|
||||
"http_code": 500,
|
||||
"redirect_url": "http://www.google.com"
|
||||
},
|
||||
"rules": [
|
||||
"SecRuleEngine On",
|
||||
"SecDebugLog \/tmp\/modsec_debug.log",
|
||||
"SecDebugLogLevel 9",
|
||||
"SecRule ARGS \"@contains test\" \"t:trim,status:500,redirect:http://www.google.com\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled": 1,
|
||||
"version_min": 300000,
|
||||
"version_max": 0,
|
||||
"title": "actions :: trim,status:500",
|
||||
"request": {
|
||||
"ip": "200.249.12.31",
|
||||
"headers": {
|
||||
"Host": "net.tutsplus.com",
|
||||
"User-Agent": "Mozilla\/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko\/20091102 Firefox\/3.5.5 (.NET CLR 3.5.30729)",
|
||||
"Accept": "text\/html,application\/xhtml+xml,application\/xml;q=0.9,*\/*;q=0.8",
|
||||
"Accept-Language": "en-us,en;q=0.5",
|
||||
"Accept-Encoding": "gzip,deflate",
|
||||
"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7",
|
||||
"Keep-Alive": "300",
|
||||
"Connection": "keep-alive",
|
||||
"Cookie": "PHPSESSID=r2t5uvjq435r4q7ib3vtdjq120",
|
||||
"Pragma": "no-cache",
|
||||
"Cache-Control": "no-cache"
|
||||
},
|
||||
"uri": "GET \/test.pl?param1= test ¶m2=test2",
|
||||
"body": ""
|
||||
},
|
||||
"response": {
|
||||
"headers": {
|
||||
"Content-Type": "text\/xml; charset=utf-8\n\r",
|
||||
"Content-Length": "length\n\r"
|
||||
},
|
||||
"body": [
|
||||
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\r",
|
||||
"<soap:Envelope xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\" xmlns:xsd=\"http:\/\/www.w3.org\/2001\/XMLSchema\" xmlns:soap=\"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/\">\n\r",
|
||||
" <soap:Body>\n\r",
|
||||
" <EnlightenResponse xmlns=\"http:\/\/clearforest.com\/\">\n\r",
|
||||
" <EnlightenResult>string<\/EnlightenResult>\n\r",
|
||||
" <\/EnlightenResponse>\n\r",
|
||||
" <\/soap:Body>\n\r",
|
||||
"<\/soap:Envelope>\n\r"
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"audit_log": "",
|
||||
"debug_log": "\\[9\\] T \\(0\\) trim: \"test\"",
|
||||
"error_log": "",
|
||||
"http_code": 500
|
||||
},
|
||||
"rules": [
|
||||
"SecRuleEngine On",
|
||||
"SecDebugLog \/tmp\/modsec_debug.log",
|
||||
"SecDebugLogLevel 9",
|
||||
"SecRule ARGS \"@contains test\" \"t:trim,status:500\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled": 1,
|
||||
"version_min": 300000,
|
||||
"version_max": 0,
|
||||
"title": "actions :: phase:1,trim,status:500",
|
||||
"request": {
|
||||
"ip": "200.249.12.31",
|
||||
"headers": {
|
||||
"Host": "net.tutsplus.com",
|
||||
"User-Agent": "Mozilla\/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko\/20091102 Firefox\/3.5.5 (.NET CLR 3.5.30729)",
|
||||
"Accept": "text\/html,application\/xhtml+xml,application\/xml;q=0.9,*\/*;q=0.8",
|
||||
"Accept-Language": "en-us,en;q=0.5",
|
||||
"Accept-Encoding": "gzip,deflate",
|
||||
"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7",
|
||||
"Keep-Alive": "300",
|
||||
"Connection": "keep-alive",
|
||||
"Cookie": "PHPSESSID=r2t5uvjq435r4q7ib3vtdjq120",
|
||||
"Pragma": "no-cache",
|
||||
"Cache-Control": "no-cache"
|
||||
},
|
||||
"uri": "GET \/test.pl?param1= test ¶m2=test2",
|
||||
"body": ""
|
||||
},
|
||||
"response": {
|
||||
"headers": {
|
||||
"Content-Type": "text\/xml; charset=utf-8\n\r",
|
||||
"Content-Length": "length\n\r"
|
||||
},
|
||||
"body": [
|
||||
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\r",
|
||||
"<soap:Envelope xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\" xmlns:xsd=\"http:\/\/www.w3.org\/2001\/XMLSchema\" xmlns:soap=\"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/\">\n\r",
|
||||
" <soap:Body>\n\r",
|
||||
" <EnlightenResponse xmlns=\"http:\/\/clearforest.com\/\">\n\r",
|
||||
" <EnlightenResult>string<\/EnlightenResult>\n\r",
|
||||
" <\/EnlightenResponse>\n\r",
|
||||
" <\/soap:Body>\n\r",
|
||||
"<\/soap:Envelope>\n\r"
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"audit_log": "",
|
||||
"debug_log": "\\[9\\] T \\(0\\) trim: \"test\"",
|
||||
"error_log": "",
|
||||
"http_code": 500
|
||||
},
|
||||
"rules": [
|
||||
"SecRuleEngine On",
|
||||
"SecDebugLog \/tmp\/modsec_debug.log",
|
||||
"SecDebugLogLevel 9",
|
||||
"SecRule ARGS \"@contains test\" \"phase:1,t:trim,status:500\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled": 1,
|
||||
"version_min": 300000,
|
||||
"version_max": 0,
|
||||
"title": "actions :: phase:4,trim,status:500",
|
||||
"request": {
|
||||
"ip": "200.249.12.31",
|
||||
"headers": {
|
||||
"Host": "net.tutsplus.com",
|
||||
"User-Agent": "Mozilla\/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko\/20091102 Firefox\/3.5.5 (.NET CLR 3.5.30729)",
|
||||
"Accept": "text\/html,application\/xhtml+xml,application\/xml;q=0.9,*\/*;q=0.8",
|
||||
"Accept-Language": "en-us,en;q=0.5",
|
||||
"Accept-Encoding": "gzip,deflate",
|
||||
"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7",
|
||||
"Keep-Alive": "300",
|
||||
"Connection": "keep-alive",
|
||||
"Cookie": "PHPSESSID=r2t5uvjq435r4q7ib3vtdjq120",
|
||||
"Pragma": "no-cache",
|
||||
"Cache-Control": "no-cache"
|
||||
},
|
||||
"uri": "GET \/test.pl?param1= test ¶m2=test2",
|
||||
"body": ""
|
||||
},
|
||||
"response": {
|
||||
"headers": {
|
||||
"Content-Type": "text\/xml; charset=utf-8\n\r",
|
||||
"Content-Length": "length\n\r"
|
||||
},
|
||||
"body": [
|
||||
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\r",
|
||||
"<soap:Envelope xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\" xmlns:xsd=\"http:\/\/www.w3.org\/2001\/XMLSchema\" xmlns:soap=\"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/\">\n\r",
|
||||
" <soap:Body>\n\r",
|
||||
" <EnlightenResponse xmlns=\"http:\/\/clearforest.com\/\">\n\r",
|
||||
" <EnlightenResult>string<\/EnlightenResult>\n\r",
|
||||
" <\/EnlightenResponse>\n\r",
|
||||
" <\/soap:Body>\n\r",
|
||||
"<\/soap:Envelope>\n\r"
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"audit_log": "",
|
||||
"debug_log": "\\[9\\] T \\(0\\) trim: \"test\"",
|
||||
"error_log": "",
|
||||
"http_code": 500
|
||||
},
|
||||
"rules": [
|
||||
"SecRuleEngine On",
|
||||
"SecDebugLog \/tmp\/modsec_debug.log",
|
||||
"SecDebugLogLevel 9",
|
||||
"SecRule ARGS \"@contains test\" \"phase:4,t:trim,status:500\""
|
||||
]
|
||||
}
|
||||
]
|
57
test/test-cases/regression/debug_log.json
Normal file
57
test/test-cases/regression/debug_log.json
Normal file
@@ -0,0 +1,57 @@
|
||||
[
|
||||
{
|
||||
"enabled": 1,
|
||||
"version_min": 300000,
|
||||
"version_max": 0,
|
||||
"title": "Debug log",
|
||||
"request": {
|
||||
"ip": "200.249.12.31",
|
||||
"headers": {
|
||||
"Host": "net.tutsplus.com",
|
||||
"User-Agent": "Mozilla\/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko\/20091102 Firefox\/3.5.5 (.NET CLR 3.5.30729)",
|
||||
"Accept": "text\/html,application\/xhtml+xml,application\/xml;q=0.9,*\/*;q=0.8",
|
||||
"Accept-Language": "en-us,en;q=0.5",
|
||||
"Accept-Encoding": "gzip,deflate",
|
||||
"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7",
|
||||
"Keep-Alive": "300",
|
||||
"Connection": "keep-alive",
|
||||
"Cookie": "PHPSESSID=r2t5uvjq435r4q7ib3vtdjq120",
|
||||
"Pragma": "no-cache",
|
||||
"Cache-Control": "no-cache"
|
||||
},
|
||||
"uri": "GET \/test.pl?param1=test¶2=test2",
|
||||
"body": ""
|
||||
},
|
||||
"response": {
|
||||
"headers": {
|
||||
"Content-Type": "text\/xml; charset=utf-8\n\r",
|
||||
"Content-Length": "length\n\r"
|
||||
},
|
||||
"body": [
|
||||
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\r",
|
||||
"<soap:Envelope xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\" xmlns:xsd=\"http:\/\/www.w3.org\/2001\/XMLSchema\" xmlns:soap=\"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/\">\n\r",
|
||||
" <soap:Body>\n\r",
|
||||
" <EnlightenResponse xmlns=\"http:\/\/clearforest.com\/\">\n\r",
|
||||
" <EnlightenResult>string<\/EnlightenResult>\n\r",
|
||||
" <\/EnlightenResponse>\n\r",
|
||||
" <\/soap:Body>\n\r",
|
||||
"<\/soap:Envelope>\n\r"
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"audit_log": "",
|
||||
"debug_log": ".*",
|
||||
"error_log": ""
|
||||
},
|
||||
"rules": [
|
||||
"SecRuleEngine On",
|
||||
"SecDebugLog \/tmp\/modsec_debug.log",
|
||||
"SecDebugLogLevel 9",
|
||||
"SecRule ARGS \"@contains test\" \"pass\"",
|
||||
"SecRule ARGS \"@contains /test.txt\" \"allow\"",
|
||||
"SecRule ARGS:teste \"@contains /test.txt\" \" allow,deny\"",
|
||||
"SecRule ARGS \"@contains /test.txt\" \"allow, allow,deny\""
|
||||
|
||||
]
|
||||
}
|
||||
]
|
34
test/test-cases/regression/issue-394.json
Normal file
34
test/test-cases/regression/issue-394.json
Normal file
@@ -0,0 +1,34 @@
|
||||
[
|
||||
{
|
||||
"enabled": 1,
|
||||
"version_min": 209000,
|
||||
"version_max": -1,
|
||||
"title": "Segmentation fault when uploading file with SecStreamInBodyInspection enabled",
|
||||
"url": "https:\/\/github.com\/SpiderLabs\/ModSecurity\/issues\/394",
|
||||
"gihub_issue": 394,
|
||||
"request": {
|
||||
"headers": "",
|
||||
"body": ""
|
||||
},
|
||||
"response": {
|
||||
"headers": "",
|
||||
"body": ""
|
||||
},
|
||||
"expected": {
|
||||
"audit_logs": "",
|
||||
"debug_logs": "",
|
||||
"error_logs": ""
|
||||
},
|
||||
"rules": [
|
||||
"SecRuleEngine On",
|
||||
"SecRequestBodyAccess On",
|
||||
"SecResponseBodyAccess On",
|
||||
"SecAuditEngine On",
|
||||
"SecAuditLogType Serial",
|
||||
"SecAuditLog logs\/modsec_audit.log",
|
||||
"SecAuditLogParts ABCDEFHJKZ",
|
||||
"SecDebugLog \/tmp\/modsec_debug.log",
|
||||
"SecDebugLogLevel 9"
|
||||
]
|
||||
}
|
||||
]
|
104
test/test-cases/regression/transformations.json
Normal file
104
test/test-cases/regression/transformations.json
Normal file
@@ -0,0 +1,104 @@
|
||||
[
|
||||
{
|
||||
"enabled": 1,
|
||||
"version_min": 300000,
|
||||
"version_max": 0,
|
||||
"title": "Testing transformations :: pass,t:trim",
|
||||
"request": {
|
||||
"ip": "200.249.12.31",
|
||||
"headers": {
|
||||
"Host": "net.tutsplus.com",
|
||||
"User-Agent": "Mozilla\/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko\/20091102 Firefox\/3.5.5 (.NET CLR 3.5.30729)",
|
||||
"Accept": "text\/html,application\/xhtml+xml,application\/xml;q=0.9,*\/*;q=0.8",
|
||||
"Accept-Language": "en-us,en;q=0.5",
|
||||
"Accept-Encoding": "gzip,deflate",
|
||||
"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7",
|
||||
"Keep-Alive": "300",
|
||||
"Connection": "keep-alive",
|
||||
"Cookie": "PHPSESSID=r2t5uvjq435r4q7ib3vtdjq120",
|
||||
"Pragma": "no-cache",
|
||||
"Cache-Control": "no-cache"
|
||||
},
|
||||
"uri": "GET \/test.pl?param1= test ¶m2=test2",
|
||||
"body": ""
|
||||
},
|
||||
"response": {
|
||||
"headers": {
|
||||
"Content-Type": "text\/xml; charset=utf-8\n\r",
|
||||
"Content-Length": "length\n\r"
|
||||
},
|
||||
"body": [
|
||||
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\r",
|
||||
"<soap:Envelope xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\" xmlns:xsd=\"http:\/\/www.w3.org\/2001\/XMLSchema\" xmlns:soap=\"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/\">\n\r",
|
||||
" <soap:Body>\n\r",
|
||||
" <EnlightenResponse xmlns=\"http:\/\/clearforest.com\/\">\n\r",
|
||||
" <EnlightenResult>string<\/EnlightenResult>\n\r",
|
||||
" <\/EnlightenResponse>\n\r",
|
||||
" <\/soap:Body>\n\r",
|
||||
"<\/soap:Envelope>\n\r"
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"audit_log": "",
|
||||
"debug_log": "\\[9\\] T \\(0\\) trim: \"test2\"",
|
||||
"error_log": ""
|
||||
},
|
||||
"rules": [
|
||||
"SecRuleEngine On",
|
||||
"SecDebugLog \/tmp\/modsec_debug.log",
|
||||
"SecDebugLogLevel 9",
|
||||
"SecRule ARGS \"@contains test \" \"pass,t:trim\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled": 1,
|
||||
"version_min": 300000,
|
||||
"version_max": 0,
|
||||
"title": "Testing transformations :: pass,t:trim,t:lowercase",
|
||||
"request": {
|
||||
"ip": "200.249.12.31",
|
||||
"headers": {
|
||||
"Host": "net.tutsplus.com",
|
||||
"User-Agent": "Mozilla\/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko\/20091102 Firefox\/3.5.5 (.NET CLR 3.5.30729)",
|
||||
"Accept": "text\/html,application\/xhtml+xml,application\/xml;q=0.9,*\/*;q=0.8",
|
||||
"Accept-Language": "en-us,en;q=0.5",
|
||||
"Accept-Encoding": "gzip,deflate",
|
||||
"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7",
|
||||
"Keep-Alive": "300",
|
||||
"Connection": "keep-alive",
|
||||
"Cookie": "PHPSESSID=r2t5uvjq435r4q7ib3vtdjq120",
|
||||
"Pragma": "no-cache",
|
||||
"Cache-Control": "no-cache"
|
||||
},
|
||||
"uri": "GET \/test.pl?param1= WHEE ¶m2=test2",
|
||||
"body": ""
|
||||
},
|
||||
"response": {
|
||||
"headers": {
|
||||
"Content-Type": "text\/xml; charset=utf-8\n\r",
|
||||
"Content-Length": "length\n\r"
|
||||
},
|
||||
"body": [
|
||||
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\r",
|
||||
"<soap:Envelope xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\" xmlns:xsd=\"http:\/\/www.w3.org\/2001\/XMLSchema\" xmlns:soap=\"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/\">\n\r",
|
||||
" <soap:Body>\n\r",
|
||||
" <EnlightenResponse xmlns=\"http:\/\/clearforest.com\/\">\n\r",
|
||||
" <EnlightenResult>string<\/EnlightenResult>\n\r",
|
||||
" <\/EnlightenResponse>\n\r",
|
||||
" <\/soap:Body>\n\r",
|
||||
"<\/soap:Envelope>\n\r"
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"audit_log": "",
|
||||
"debug_log": "\\[9\\] T \\(1\\) lowercase: \"test2\"",
|
||||
"error_log": ""
|
||||
},
|
||||
"rules": [
|
||||
"SecRuleEngine On",
|
||||
"SecDebugLog \/tmp\/modsec_debug.log",
|
||||
"SecDebugLogLevel 9",
|
||||
"SecRule ARGS \"@contains test \" \"pass,t:trim,t:lowercase\""
|
||||
]
|
||||
}
|
||||
]
|
1
test/test-cases/secrules-language-tests
Submodule
1
test/test-cases/secrules-language-tests
Submodule
Submodule test/test-cases/secrules-language-tests added at c5c17dfc71
116
test/unit/unit.cc
Normal file
116
test/unit/unit.cc
Normal file
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* ModSecurity, http://www.modsecurity.org/
|
||||
* Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
||||
*
|
||||
* You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* If any of the files related to licensing are missing or if you have any
|
||||
* other questions related to licensing please contact Trustwave Holdings, Inc.
|
||||
* directly using the email address security@modsecurity.org.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include "modsecurity/modsecurity.h"
|
||||
#include "modsecurity/rules.h"
|
||||
#include "operators/operator.h"
|
||||
|
||||
#include "common/modsecurity_test.h"
|
||||
#include "common/modsecurity_test_results.h"
|
||||
#include "common/colors.h"
|
||||
#include "unit/unit_test.h"
|
||||
|
||||
|
||||
using modsecurity_test::UnitTest;
|
||||
using modsecurity_test::ModSecurityTest;
|
||||
using modsecurity_test::ModSecurityTestResults;
|
||||
|
||||
std::string default_test_path = "test-cases/secrules-language-tests/operators";
|
||||
|
||||
void print_help() {
|
||||
#ifdef HAS_GETOPT
|
||||
std::cout << "Use ./unit [--no-color] -t /path/to/test/files ";
|
||||
std::cout << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << " -h\t\tThis help message" << std::endl;
|
||||
std::cout << " -v\t\tVerbose" << std::endl;
|
||||
std::cout << " -c\t\tNo color" << std::endl;
|
||||
std::cout << " -t\t\tPath to test cases" << std::endl;
|
||||
#else
|
||||
std::cout << "Use ./unit /path/to/file" << std::endl;
|
||||
#endif
|
||||
std::cout << std::endl;
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
|
||||
void perform_unit_test(UnitTest *t, ModSecurityTestResults<UnitTest>* res) {
|
||||
ModSecurity::operators::Operator *op =
|
||||
ModSecurity::operators::Operator::instantiate("\"@" + t->name + \
|
||||
" " + t->param + "\"");
|
||||
|
||||
int ret = op->evaluate(NULL, t->input);
|
||||
if (ret != t->ret) {
|
||||
t->obtained = ret;
|
||||
res->push_back(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int total = 0;
|
||||
ModSecurityTest<UnitTest> test;
|
||||
ModSecurityTestResults<UnitTest> results;
|
||||
|
||||
test.cmd_options(argc, argv);
|
||||
std::cout << test.header();
|
||||
|
||||
test.load_tests();
|
||||
|
||||
for (std::pair<std::string, std::vector<UnitTest *> *> a : test) {
|
||||
std::vector<UnitTest *> *tests = a.second;
|
||||
|
||||
total += tests->size();
|
||||
for (UnitTest *t : *tests) {
|
||||
ModSecurityTestResults<UnitTest> r;
|
||||
|
||||
std::cout << " " << a.first << "...\t";
|
||||
|
||||
perform_unit_test(t, &r);
|
||||
|
||||
if (r.size() == 0) {
|
||||
std::cout << KGRN << r.size() << " tests failed.";
|
||||
} else {
|
||||
std::cout << KRED << r.size() << " tests failed.";
|
||||
}
|
||||
std::cout << RESET << std::endl;
|
||||
|
||||
results.insert(results.end(), r.begin(), r.end());
|
||||
}
|
||||
}
|
||||
std::cout << "Total >> " << total << std::endl;
|
||||
|
||||
for (UnitTest *t : results) {
|
||||
std::cout << t->print() << std::endl;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
std::cout << "Ran a total of: " << total << " unit tests - ";
|
||||
if (results.size() == 0) {
|
||||
std::cout << KGRN << "All tests passed" << RESET << std::endl;
|
||||
} else {
|
||||
std::cout << KRED << results.size() << " failed." << RESET << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
71
test/unit/unit_test.cc
Normal file
71
test/unit/unit_test.cc
Normal file
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* ModSecurity, http://www.modsecurity.org/
|
||||
* Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
||||
*
|
||||
* You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* If any of the files related to licensing are missing or if you have any
|
||||
* other questions related to licensing please contact Trustwave Holdings, Inc.
|
||||
* directly using the email address security@modsecurity.org.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "unit/unit_test.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "common/colors.h"
|
||||
|
||||
namespace modsecurity_test {
|
||||
|
||||
std::string UnitTest::print() {
|
||||
std::stringstream i;
|
||||
|
||||
i << KRED << "Test failed." << RESET;
|
||||
i << " From: " << this->filename << std::endl;
|
||||
i << "{" << std::endl;
|
||||
i << " \"ret\": \"" << this->ret << "\"" << std::endl;
|
||||
i << " \"type\": \"" << this->type << "\"" << std::endl;
|
||||
i << " \"name\": \"" << this->name << "\"" << std::endl;
|
||||
i << " \"input\": \"" << this->input << "\"" << std::endl;
|
||||
i << " \"param\": \"" << this->param << "\"" << std::endl;
|
||||
i << "}" << std::endl;
|
||||
i << "Expecting: " << this->ret << " - operator returned: ";
|
||||
i << this->obtained << std::endl;
|
||||
|
||||
return i.str();
|
||||
}
|
||||
|
||||
|
||||
UnitTest *UnitTest::from_yajl_node(yajl_val &node) {
|
||||
size_t num_tests = node->u.object.len;
|
||||
UnitTest *u = new UnitTest();
|
||||
|
||||
for (int i = 0; i < num_tests; i++) {
|
||||
const char *key = node->u.object.keys[ i ];
|
||||
yajl_val val = node->u.object.values[ i ];
|
||||
|
||||
|
||||
if (strcmp(key, "param") == 0) {
|
||||
u->param = YAJL_GET_STRING(val);
|
||||
} else if (strcmp(key, "input") == 0) {
|
||||
u->input = YAJL_GET_STRING(val);
|
||||
} else if (strcmp(key, "name") == 0) {
|
||||
u->name = YAJL_GET_STRING(val);
|
||||
} else if (strcmp(key, "type") == 0) {
|
||||
u->type = YAJL_GET_STRING(val);
|
||||
} else if (strcmp(key, "ret") == 0) {
|
||||
u->ret = YAJL_GET_INTEGER(val);
|
||||
}
|
||||
}
|
||||
|
||||
return u;
|
||||
}
|
||||
|
||||
} // namespace modsecurity_test
|
45
test/unit/unit_test.h
Normal file
45
test/unit/unit_test.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* ModSecurity, http://www.modsecurity.org/
|
||||
* Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
||||
*
|
||||
* You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* If any of the files related to licensing are missing or if you have any
|
||||
* other questions related to licensing please contact Trustwave Holdings, Inc.
|
||||
* directly using the email address security@modsecurity.org.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <yajl/yajl_tree.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#ifndef TEST_UNIT_UNIT_TEST_H_
|
||||
#define TEST_UNIT_UNIT_TEST_H_
|
||||
|
||||
namespace modsecurity_test {
|
||||
|
||||
class UnitTest {
|
||||
public:
|
||||
static UnitTest *from_yajl_node(yajl_val &);
|
||||
|
||||
std::string print();
|
||||
|
||||
std::string param;
|
||||
std::string input;
|
||||
std::string name;
|
||||
std::string type;
|
||||
std::string filename;
|
||||
int ret;
|
||||
int obtained;
|
||||
};
|
||||
|
||||
} // namespace modsecurity_test
|
||||
|
||||
#endif // TEST_UNIT_UNIT_TEST_H_
|
Reference in New Issue
Block a user