mirror of
https://github.com/openappsec/openappsec.git
synced 2025-09-29 19:24:26 +03:00
First release of open-appsec source code
This commit is contained in:
8
attachments/nginx/nginx_attachment_util/CMakeLists.txt
Normal file
8
attachments/nginx/nginx_attachment_util/CMakeLists.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
add_definitions(-DUSERSPACE)
|
||||
|
||||
add_library(nginx_attachment_util SHARED nginx_attachment_util.cc)
|
||||
|
||||
add_subdirectory(nginx_attachment_util_ut)
|
||||
|
||||
install(TARGETS nginx_attachment_util DESTINATION lib)
|
||||
install(TARGETS nginx_attachment_util DESTINATION http_transaction_handler_service/lib)
|
251
attachments/nginx/nginx_attachment_util/nginx_attachment_util.cc
Normal file
251
attachments/nginx/nginx_attachment_util/nginx_attachment_util.cc
Normal file
@@ -0,0 +1,251 @@
|
||||
// Copyright (C) 2022 Check Point Software Technologies Ltd. All rights reserved.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// 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
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "nginx_attachment_util.h"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "http_configuration.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
static HttpAttachmentConfiguration conf_data;
|
||||
|
||||
int
|
||||
initAttachmentConfig(c_str conf_file)
|
||||
{
|
||||
return conf_data.init(conf_file);
|
||||
}
|
||||
|
||||
ngx_http_inspection_mode_e
|
||||
getInspectionMode()
|
||||
{
|
||||
return static_cast<ngx_http_inspection_mode_e>(conf_data.getNumericalValue("nginx_inspection_mode"));
|
||||
}
|
||||
|
||||
unsigned int
|
||||
getNumOfNginxIpcElements()
|
||||
{
|
||||
return conf_data.getNumericalValue("num_of_nginx_ipc_elements");
|
||||
}
|
||||
|
||||
unsigned int
|
||||
getKeepAliveIntervalMsec()
|
||||
{
|
||||
return conf_data.getNumericalValue("keep_alive_interval_msec");
|
||||
}
|
||||
|
||||
unsigned int
|
||||
getDbgLevel()
|
||||
{
|
||||
return conf_data.getNumericalValue("dbg_level");
|
||||
}
|
||||
|
||||
int
|
||||
isDebugContext(c_str client, c_str server, unsigned int port, c_str method, c_str host , c_str uri)
|
||||
{
|
||||
auto &ctx = conf_data.getDebugContext();
|
||||
return
|
||||
(ctx.client == "" || ctx.client == client) &&
|
||||
(ctx.server == "" || ctx.server == server) &&
|
||||
(ctx.port == 0 || ctx.port == port) &&
|
||||
(ctx.method == "" || ctx.method == method) &&
|
||||
(ctx.host == "" || ctx.host == host) &&
|
||||
(ctx.uri == "" || ctx.uri == uri);
|
||||
}
|
||||
|
||||
c_str
|
||||
getStaticResourcesPath()
|
||||
{
|
||||
return conf_data.getStringValue("static_resources_path").c_str();
|
||||
}
|
||||
|
||||
int
|
||||
isFailOpenMode()
|
||||
{
|
||||
return conf_data.getNumericalValue("is_fail_open_mode_enabled");
|
||||
}
|
||||
|
||||
unsigned int
|
||||
getFailOpenTimeout()
|
||||
{
|
||||
return conf_data.getNumericalValue("fail_open_timeout");
|
||||
}
|
||||
|
||||
int
|
||||
isFailOpenHoldMode()
|
||||
{
|
||||
return conf_data.getNumericalValue("is_fail_open_mode_hold_enabled");
|
||||
}
|
||||
|
||||
unsigned int
|
||||
getFailOpenHoldTimeout()
|
||||
{
|
||||
return conf_data.getNumericalValue("fail_open_hold_timeout");
|
||||
}
|
||||
|
||||
unsigned int
|
||||
getMaxSessionsPerMinute()
|
||||
{
|
||||
return conf_data.getNumericalValue("max_sessions_per_minute");
|
||||
}
|
||||
|
||||
int
|
||||
isFailOpenOnSessionLimit()
|
||||
{
|
||||
return conf_data.getStringValue("sessions_per_minute_limit_verdict") == "Accept";
|
||||
}
|
||||
|
||||
unsigned int
|
||||
getRegistrationThreadTimeout()
|
||||
{
|
||||
return conf_data.getNumericalValue("registration_thread_timeout_msec");
|
||||
}
|
||||
|
||||
unsigned int
|
||||
getReqProccessingTimeout()
|
||||
{
|
||||
return conf_data.getNumericalValue("req_proccessing_timeout_msec");
|
||||
}
|
||||
|
||||
unsigned int
|
||||
getReqHeaderThreadTimeout()
|
||||
{
|
||||
return conf_data.getNumericalValue("req_header_thread_timeout_msec");
|
||||
}
|
||||
|
||||
unsigned int
|
||||
getReqBodyThreadTimeout()
|
||||
{
|
||||
return conf_data.getNumericalValue("req_body_thread_timeout_msec");
|
||||
}
|
||||
|
||||
unsigned int
|
||||
getResProccessingTimeout()
|
||||
{
|
||||
return conf_data.getNumericalValue("res_proccessing_timeout_msec");
|
||||
}
|
||||
|
||||
unsigned int
|
||||
getResHeaderThreadTimeout()
|
||||
{
|
||||
return conf_data.getNumericalValue("res_header_thread_timeout_msec");
|
||||
}
|
||||
|
||||
unsigned int
|
||||
getResBodyThreadTimeout()
|
||||
{
|
||||
return conf_data.getNumericalValue("res_body_thread_timeout_msec");
|
||||
}
|
||||
|
||||
unsigned int
|
||||
getWaitingForVerdictThreadTimeout()
|
||||
{
|
||||
return conf_data.getNumericalValue("waiting_for_verdict_thread_timeout_msec");
|
||||
}
|
||||
|
||||
int
|
||||
isIPAddress(c_str ip_str)
|
||||
{
|
||||
int address_family = AF_INET;
|
||||
for (int i = 0; ip_str[i]; ++i) {
|
||||
if (ip_str[i] == ':') address_family = AF_INET6;
|
||||
}
|
||||
|
||||
char placeholder[16];
|
||||
return inet_pton(address_family, ip_str, placeholder);
|
||||
}
|
||||
|
||||
struct IpAddress
|
||||
{
|
||||
union {
|
||||
struct in_addr ipv4;
|
||||
struct in6_addr ipv6;
|
||||
} ip;
|
||||
bool is_ipv4;
|
||||
|
||||
bool
|
||||
operator<(const IpAddress &other) const
|
||||
{
|
||||
if (is_ipv4 != other.is_ipv4) return is_ipv4 < other.is_ipv4;
|
||||
if (is_ipv4) return memcmp(&ip.ipv4, &other.ip.ipv4, sizeof(struct in_addr)) < 0;
|
||||
return memcmp(&ip.ipv6, &other.ip.ipv6, sizeof(struct in6_addr)) < 0;
|
||||
}
|
||||
|
||||
bool
|
||||
operator<=(const IpAddress &other) const
|
||||
{
|
||||
return !(other < *this);
|
||||
}
|
||||
};
|
||||
|
||||
static IpAddress
|
||||
createIPAddress(c_str ip_str)
|
||||
{
|
||||
IpAddress res;
|
||||
|
||||
for (int i = 0; ip_str[i]; ++i) {
|
||||
if (ip_str[i] == ':') {
|
||||
res.is_ipv4 = false;
|
||||
inet_pton(AF_INET6, ip_str, &res.ip.ipv6);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
res.is_ipv4 = true;
|
||||
inet_pton(AF_INET, ip_str, &res.ip.ipv4);
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool
|
||||
isIPInRange(const IpAddress &ip, const IpAddress &start, const IpAddress &end)
|
||||
{
|
||||
if (ip.is_ipv4 != start.is_ipv4 || ip.is_ipv4 != end.is_ipv4) return false;
|
||||
return start <= ip && ip <= end;
|
||||
}
|
||||
|
||||
static bool
|
||||
isIPInRange(const IpAddress &ip, const string &range)
|
||||
{
|
||||
auto delimiter = range.find('-');
|
||||
|
||||
if (delimiter == string::npos) {
|
||||
if (!isIPAddress(range.c_str())) return false;
|
||||
auto address = createIPAddress(range.c_str());
|
||||
return isIPInRange(ip, address, address);
|
||||
}
|
||||
|
||||
auto start_str = range.substr(0, delimiter);
|
||||
if (!isIPAddress(start_str.c_str())) return false;
|
||||
auto start_addr = createIPAddress(start_str.c_str());
|
||||
|
||||
auto end_str = range.substr(delimiter + 1);
|
||||
if (!isIPAddress(end_str.c_str())) return false;
|
||||
auto end_addr = createIPAddress(end_str.c_str());
|
||||
|
||||
return isIPInRange(ip, start_addr, end_addr);
|
||||
}
|
||||
|
||||
int
|
||||
isSkipSource(c_str ip_str)
|
||||
{
|
||||
if (!isIPAddress(ip_str)) return 0;
|
||||
auto ip = createIPAddress(ip_str);
|
||||
|
||||
for (auto &range : conf_data.getExcludeSources()) {
|
||||
if (isIPInRange(ip, range)) return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
include_directories(${Boost_INCLUDE_DIRS})
|
||||
include_directories(${CMAKE_SOURCE_DIR}/components/include)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/attachments/nginx/nginx_attachment_util)
|
||||
|
||||
add_unit_test(
|
||||
nginx_attachment_util_ut
|
||||
"nginx_attachment_util_ut.cc"
|
||||
"nginx_attachment_util;http_configuration"
|
||||
)
|
@@ -0,0 +1,125 @@
|
||||
#include <fstream>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <stdlib.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "nginx_attachment_util.h"
|
||||
#include "cptest.h"
|
||||
#include "c_common/ip_common.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace testing;
|
||||
|
||||
class HttpAttachmentUtilTest : public Test
|
||||
{
|
||||
public:
|
||||
string
|
||||
createIPRangesString(const vector<string> &ip_ranges)
|
||||
{
|
||||
stringstream ip_ranges_string_stream;
|
||||
ip_ranges_string_stream << "[";
|
||||
for (auto iterator = ip_ranges.begin(); iterator < ip_ranges.end() - 1; iterator++) {
|
||||
ip_ranges_string_stream << "\"" << *iterator << "\"" << ", ";
|
||||
}
|
||||
ip_ranges_string_stream << "\"" << ip_ranges.back() << "\"]";
|
||||
|
||||
return ip_ranges_string_stream.str();
|
||||
}
|
||||
|
||||
const string attachment_configuration_file_name = "cp_nano_http_attachment_conf";
|
||||
const vector<string> ip_ranges = { "8.8.8.8", "9.9.9.9-10.10.10.10", "0:0:0:0:0:0:0:2-0:0:0:0:0:0:0:5"};
|
||||
const string static_resources_path = "/dev/shm/static_resources/";
|
||||
};
|
||||
|
||||
TEST_F(HttpAttachmentUtilTest, GetValidAttachmentConfiguration)
|
||||
{
|
||||
string valid_configuration =
|
||||
"{\n"
|
||||
"\"context_values\": {"
|
||||
"\"clientIp\": \"1.2.3.4\","
|
||||
"\"listeningIp\": \"5.6.7.8\","
|
||||
"\"uriPrefix\": \"/abc\","
|
||||
"\"hostName\": \"test\","
|
||||
"\"httpMethod\": \"GET\","
|
||||
"\"listeningPort\": 80"
|
||||
"},"
|
||||
"\"is_fail_open_mode_enabled\": 0,\n"
|
||||
"\"fail_open_timeout\": 1234,\n"
|
||||
"\"is_fail_open_mode_hold_enabled\": 1,\n"
|
||||
"\"fail_open_hold_timeout\": 4321,\n"
|
||||
"\"sessions_per_minute_limit_verdict\": \"Accept\",\n"
|
||||
"\"max_sessions_per_minute\": 0,\n"
|
||||
"\"num_of_nginx_ipc_elements\": 200,\n"
|
||||
"\"keep_alive_interval_msec\": 10000,\n"
|
||||
"\"dbg_level\": 2,\n"
|
||||
"\"nginx_inspection_mode\": 1,\n"
|
||||
"\"operation_mode\": 0,\n"
|
||||
"\"req_body_thread_timeout_msec\": 155,\n"
|
||||
"\"req_proccessing_timeout_msec\": 42,\n"
|
||||
"\"registration_thread_timeout_msec\": 101,\n"
|
||||
"\"res_proccessing_timeout_msec\": 420,\n"
|
||||
"\"res_header_thread_timeout_msec\": 1,\n"
|
||||
"\"res_body_thread_timeout_msec\": 0,\n"
|
||||
"\"waiting_for_verdict_thread_timeout_msec\": 75,\n"
|
||||
"\"req_header_thread_timeout_msec\": 10,\n"
|
||||
"\"ip_ranges\": " + createIPRangesString(ip_ranges) + ",\n"
|
||||
"\"static_resources_path\": \"" + static_resources_path + "\""
|
||||
"}\n";
|
||||
ofstream valid_configuration_file(attachment_configuration_file_name);
|
||||
valid_configuration_file << valid_configuration;
|
||||
valid_configuration_file.close();
|
||||
|
||||
EXPECT_EQ(initAttachmentConfig(attachment_configuration_file_name.c_str()), 1);
|
||||
EXPECT_EQ(getDbgLevel(), 2);
|
||||
EXPECT_EQ(getStaticResourcesPath(), static_resources_path);
|
||||
EXPECT_EQ(isFailOpenMode(), 0);
|
||||
EXPECT_EQ(getFailOpenTimeout(), 1234);
|
||||
EXPECT_EQ(isFailOpenHoldMode(), 1);
|
||||
EXPECT_EQ(getFailOpenHoldTimeout(), 4321);
|
||||
EXPECT_EQ(isFailOpenOnSessionLimit(), 1);
|
||||
EXPECT_EQ(getMaxSessionsPerMinute(), 0);
|
||||
EXPECT_EQ(getNumOfNginxIpcElements(), 200);
|
||||
EXPECT_EQ(getKeepAliveIntervalMsec(), 10000);
|
||||
EXPECT_EQ(getResProccessingTimeout(), 420);
|
||||
EXPECT_EQ(getReqProccessingTimeout(), 42);
|
||||
EXPECT_EQ(getRegistrationThreadTimeout(), 101);
|
||||
EXPECT_EQ(getReqHeaderThreadTimeout(), 10);
|
||||
EXPECT_EQ(getReqBodyThreadTimeout(), 155);
|
||||
EXPECT_EQ(getResHeaderThreadTimeout(), 1);
|
||||
EXPECT_EQ(getResBodyThreadTimeout(), 0);
|
||||
EXPECT_EQ(getWaitingForVerdictThreadTimeout(), 75);
|
||||
EXPECT_EQ(getInspectionMode(), ngx_http_inspection_mode::BLOCKING_THREAD);
|
||||
|
||||
EXPECT_EQ(isDebugContext("1.2.3.4", "5.6.7.8", 80, "GET", "test", "/abc"), 1);
|
||||
EXPECT_EQ(isDebugContext("1.2.3.9", "5.6.7.8", 80, "GET", "test", "/abc"), 0);
|
||||
EXPECT_EQ(isDebugContext("1.2.3.4", "5.6.7.9", 80, "GET", "test", "/abc"), 0);
|
||||
EXPECT_EQ(isDebugContext("1.2.3.4", "5.6.7.8", 88, "GET", "test", "/abc"), 0);
|
||||
EXPECT_EQ(isDebugContext("1.2.3.4", "5.6.7.8", 80, "POST", "test", "/abc"), 0);
|
||||
EXPECT_EQ(isDebugContext("1.2.3.4", "5.6.7.8", 80, "GET", "est", "/abc"), 0);
|
||||
EXPECT_EQ(isDebugContext("1.2.3.4", "5.6.7.8", 80, "GET", "test", "/ab"), 0);
|
||||
|
||||
EXPECT_EQ(isSkipSource("8.8.8.8"), 1);
|
||||
EXPECT_EQ(isSkipSource("8.8.8.9"), 0);
|
||||
EXPECT_EQ(isSkipSource("8.8.8.10"), 0);
|
||||
|
||||
EXPECT_EQ(isSkipSource("9.9.9.8"), 0);
|
||||
EXPECT_EQ(isSkipSource("9.9.9.9"), 1);
|
||||
EXPECT_EQ(isSkipSource("9.255.0.0"), 1);
|
||||
EXPECT_EQ(isSkipSource("10.10.10.10"), 1);
|
||||
EXPECT_EQ(isSkipSource("10.10.10.11"), 0);
|
||||
|
||||
EXPECT_EQ(isSkipSource("0:0:0:0:0:0:0:1"), 0);
|
||||
EXPECT_EQ(isSkipSource("0:0:0:0:0:0:0:2"), 1);
|
||||
EXPECT_EQ(isSkipSource("0:0:0:0:0:0:0:4"), 1);
|
||||
EXPECT_EQ(isSkipSource("0:0:0:0:0:0:0:5"), 1);
|
||||
EXPECT_EQ(isSkipSource("0:0:0:0:0:0:0:6"), 0);
|
||||
}
|
||||
|
||||
TEST_F(HttpAttachmentUtilTest, CheckIPAddrValidity)
|
||||
{
|
||||
EXPECT_EQ(isIPAddress("10.0.0.1"), 1);
|
||||
EXPECT_EQ(isIPAddress("2001:0db8:85a3:0000:0000:8a2e:0370:7334"), 1);
|
||||
|
||||
EXPECT_EQ(isIPAddress("333.0.0.1"), 0);
|
||||
EXPECT_EQ(isIPAddress("2001:0gb8:85a3:0000:0000:8a2e:0370:7334"), 0);
|
||||
}
|
Reference in New Issue
Block a user