mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-09-30 03:34:29 +03:00
Very first commit: libmodsecurity
Check the README.md file for further information about the libmodsecurity.
This commit is contained in:
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_
|
Reference in New Issue
Block a user