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:
1
core/connkey/CMakeLists.txt
Normal file
1
core/connkey/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
||||
add_library(connkey connkey.cc connkey_eval.cc)
|
241
core/connkey/connkey.cc
Executable file
241
core/connkey/connkey.cc
Executable file
@@ -0,0 +1,241 @@
|
||||
// Copyright (C) 2022 Check Point Software Technologies Ltd. All rights reserved.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (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 <stdio.h>
|
||||
#include <string.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "connkey.h"
|
||||
#include "debug.h"
|
||||
#include "config.h"
|
||||
#include "hash_combine.h"
|
||||
#include "enum_range.h"
|
||||
#include "cereal/types/memory.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
CEREAL_CLASS_VERSION(IPAddr, 0);
|
||||
CEREAL_CLASS_VERSION(ConnKey, 0);
|
||||
|
||||
USE_DEBUG_FLAG(D_CONFIG);
|
||||
|
||||
static bool
|
||||
protoHasPorts(IPProto proto)
|
||||
{
|
||||
return (proto==IPPROTO_TCP) || (proto==IPPROTO_UDP);
|
||||
}
|
||||
|
||||
ostream &
|
||||
operator<<(ostream &os, const IPType &t)
|
||||
{
|
||||
switch (t) {
|
||||
case IPType::V4: {
|
||||
return os << "IPv4";
|
||||
}
|
||||
case IPType::V6: {
|
||||
return os << "IPv6";
|
||||
}
|
||||
case IPType::UNINITIALIZED: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return os << "Invalid(" << static_cast<uint>(t) << ")";
|
||||
}
|
||||
|
||||
// Format an IP address. Use a pair, becuase it depends on the type (v4/v6)
|
||||
ostream &
|
||||
IPAddr::print(ostream &os) const
|
||||
{
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
const char *formatted_addr;
|
||||
|
||||
switch (type) {
|
||||
case IPType::V4: {
|
||||
formatted_addr = inet_ntop(AF_INET, &v4, buf, sizeof(buf));
|
||||
dbgAssert(formatted_addr == buf) << "Failed to convert an IPv4 address";
|
||||
break;
|
||||
}
|
||||
case IPType::V6: {
|
||||
formatted_addr = inet_ntop(AF_INET6, &v6, buf, sizeof(buf));
|
||||
dbgAssert(formatted_addr == buf) << "Failed to convert an IPv6 address";
|
||||
break;
|
||||
}
|
||||
case IPType::UNINITIALIZED: {
|
||||
formatted_addr = "Uninitialized IP address";
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
formatted_addr = "?";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return os << formatted_addr;
|
||||
}
|
||||
|
||||
// Format a port numbers. Use a pair, becuase it depends on the protocl (only TCP/UDP have ports).
|
||||
static ostream &
|
||||
operator<<(ostream &os, pair<IPProto, PortNumber> pp)
|
||||
{
|
||||
if (protoHasPorts(get<0>(pp))) {
|
||||
os << "|" << get<1>(pp);
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
ostream &
|
||||
ConnKey::print(ostream &os) const
|
||||
{
|
||||
if (src.type == IPType::UNINITIALIZED) return os << "<Uninitialized connection>";
|
||||
|
||||
return os << "<" <<
|
||||
src << make_pair(src.proto, src.port) <<
|
||||
" -> " <<
|
||||
dst << make_pair(dst.proto, dst.port) <<
|
||||
" " << static_cast<uint>(src.proto) << ">"; // Cast needed to print as a number.
|
||||
}
|
||||
|
||||
void
|
||||
ConnKey::reverse()
|
||||
{
|
||||
swap(src, dst);
|
||||
}
|
||||
|
||||
size_t
|
||||
ConnKey::hash() const
|
||||
{
|
||||
dbgAssert(src.type != IPType::UNINITIALIZED) << "ConnKey::hash was called on an uninitialized object";
|
||||
size_t seed = 0; // XXX: random seed for security?
|
||||
hashCombine(seed, static_cast<u_char>(src.type));
|
||||
hashCombine(seed, src.proto);
|
||||
hashCombine(seed, src);
|
||||
hashCombine(seed, dst);
|
||||
hashCombine(seed, src.port);
|
||||
hashCombine(seed, dst.port);
|
||||
return seed;
|
||||
}
|
||||
|
||||
size_t
|
||||
IPAddr::hash() const
|
||||
{
|
||||
size_t seed = 0;
|
||||
hashCombine(seed, v6.s6_addr32[0]);
|
||||
hashCombine(seed, v6.s6_addr32[1]);
|
||||
hashCombine(seed, v6.s6_addr32[2]);
|
||||
hashCombine(seed, v6.s6_addr32[3]);
|
||||
return seed;
|
||||
}
|
||||
|
||||
bool
|
||||
IPAddr::isInRange(const IPAddr &left, const IPAddr &right) const
|
||||
{
|
||||
return (*this >= left) && (*this <= right);
|
||||
}
|
||||
|
||||
Maybe<IPAddr>
|
||||
IPAddr::createIPAddr(const string &ip_text)
|
||||
{
|
||||
if (ip_text.find(':') == string::npos) {
|
||||
struct in_addr v4;
|
||||
if(inet_pton(AF_INET, ip_text.c_str(), &v4)!=0){
|
||||
return IPAddr(v4);
|
||||
}
|
||||
} else { // Found ':' - it's IPv6
|
||||
struct in6_addr v6;
|
||||
if(inet_pton(AF_INET6, ip_text.c_str(), &v6)!=0){
|
||||
return IPAddr(v6);
|
||||
}
|
||||
}
|
||||
return genError("String \'"+ ip_text +"\' is not a valid IPv4/IPv6 address");
|
||||
}
|
||||
|
||||
bool IPAddr::isValidIPAddr(const string &ip_text) { return createIPAddr(ip_text).ok(); }
|
||||
|
||||
IPAddressConfig::IPAddressConfig(const string &ip_string)
|
||||
{
|
||||
auto maybe_address = IPAddr::createIPAddr(ip_string);
|
||||
if (maybe_address.ok()) address = maybe_address.unpack();
|
||||
}
|
||||
|
||||
void
|
||||
IPAddressConfig::load(cereal::JSONInputArchive &ar)
|
||||
{
|
||||
string ip_string;
|
||||
ar(cereal::make_nvp("IPAddress", ip_string));
|
||||
auto ip_address = IPAddr::createIPAddr(ip_string);
|
||||
if (!ip_address.ok()) {
|
||||
throw Config::ConfigException(
|
||||
"Failed to create an IP address from " + ip_string + ": " + ip_address.getErr()
|
||||
);
|
||||
}
|
||||
address = ip_address.unpack();
|
||||
}
|
||||
|
||||
const string ConnKey::network_key = "NetworkKey";
|
||||
|
||||
template<typename Num>
|
||||
Maybe<Num>
|
||||
fromStringToNumeric(const string &value_str, const string &name, const int max_val)
|
||||
{
|
||||
if (value_str.find_first_not_of("0123456789") != string::npos) {
|
||||
dbgError(D_CONFIG) << name << " contains non digit chars. Value: " << value_str;
|
||||
return genError(name + " contains non digit chars. Value: " + value_str);
|
||||
}
|
||||
try {
|
||||
int value;
|
||||
value = stoi(value_str);
|
||||
if (value > max_val) {
|
||||
dbgError(D_CONFIG) << "Invalid " << name << ". Value: " << value_str;
|
||||
return genError("Invalid " + name + ". Value: " + value_str);
|
||||
}
|
||||
return static_cast<Num>(value);
|
||||
} catch (const invalid_argument &e) {
|
||||
dbgError(D_CONFIG) << name << " resived is invalid. Error: " << e.what();
|
||||
return genError(name + " recived is invalid. Error: " + e.what());
|
||||
}
|
||||
return genError("Error in creating numeric value of " + name);
|
||||
}
|
||||
|
||||
bool
|
||||
ConnKeyUtil::fromString(const string &proto_str, IPProto &proto)
|
||||
{
|
||||
Maybe<IPProto> ip_protocol = fromStringToNumeric<IPProto>(proto_str, "Ip protocol", 255);
|
||||
if (ip_protocol.ok()) {
|
||||
proto = ip_protocol.unpack();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ConnKeyUtil::fromString(const string &port_str, PortNumber &port)
|
||||
{
|
||||
Maybe<PortNumber> port_num = fromStringToNumeric<PortNumber>(port_str, "Port", 65535);
|
||||
if (port_num.ok()) {
|
||||
port = port_num.unpack();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ConnKeyUtil::fromString(const string &ip_str, IPAddr &ip_address)
|
||||
{
|
||||
Maybe<IPAddr> ip_addr = IPAddr::createIPAddr(ip_str);
|
||||
if (!ip_addr.ok()) {
|
||||
dbgError(D_CONFIG) << "Ip address resived is invalid: " << ip_addr.getErr();
|
||||
return false;
|
||||
}
|
||||
ip_address = ip_addr.unpack();
|
||||
return true;
|
||||
}
|
167
core/connkey/connkey_eval.cc
Normal file
167
core/connkey/connkey_eval.cc
Normal file
@@ -0,0 +1,167 @@
|
||||
// Copyright (C) 2022 Check Point Software Technologies Ltd. All rights reserved.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (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 "connkey.h"
|
||||
#include "environment/evaluator_templates.h"
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace EnvironmentHelper;
|
||||
|
||||
class ConstantPort : public Constant<uint16_t>
|
||||
{
|
||||
public:
|
||||
ConstantPort(const vector<string> ¶ms)
|
||||
:
|
||||
Constant<uint16_t>(
|
||||
[] (const string & str) {
|
||||
uint16_t value = 0;
|
||||
try {
|
||||
value = boost::lexical_cast<uint16_t>(str);
|
||||
} catch (boost::bad_lexical_cast const&) {
|
||||
reportWrongParamType(getName(), str, "Not a port number");
|
||||
}
|
||||
return value;
|
||||
},
|
||||
params
|
||||
) {}
|
||||
|
||||
static string getName() { return Constant<uint16_t>::getName() + "Port"; }
|
||||
};
|
||||
|
||||
class ConstantIP : public Constant<IPAddr>
|
||||
{
|
||||
public:
|
||||
ConstantIP(const vector<string> ¶ms)
|
||||
:
|
||||
Constant<IPAddr>(
|
||||
[] (const string & str) {
|
||||
auto addr = IPAddr::createIPAddr(str);
|
||||
if (!addr.ok()) reportWrongParamType(getName(), str, "Not an IP address");
|
||||
return *addr;
|
||||
},
|
||||
params
|
||||
) {}
|
||||
|
||||
static string getName() { return Constant<IPAddr>::getName() + "IP"; }
|
||||
};
|
||||
|
||||
class ConstantProtocol : public Constant<IPProto>
|
||||
{
|
||||
public:
|
||||
ConstantProtocol(const vector<string> ¶ms)
|
||||
:
|
||||
Constant<IPProto>(
|
||||
[] (const string &str) {
|
||||
uint16_t value = 0;
|
||||
for (auto &ch : str) {
|
||||
if (ch < '0' || ch > '9') reportWrongParamType(getName(), str, "Not a protocol ID character");
|
||||
value = value * 10 + (ch - '0');
|
||||
if (256 <= value) reportWrongParamType(getName(), str, "Not a protocol ID number");
|
||||
}
|
||||
return static_cast<IPProto>(value);
|
||||
},
|
||||
params
|
||||
) {}
|
||||
|
||||
static string getName() { return Constant<IPProto>::getName() + "Protocol"; }
|
||||
};
|
||||
|
||||
class EqualPort : public Equal<uint16_t>
|
||||
{
|
||||
public:
|
||||
EqualPort(const vector<string> ¶ms) : Equal<uint16_t>(params) {}
|
||||
static string getName() { return Equal<uint16_t>::getName() + "Port"; }
|
||||
};
|
||||
|
||||
class EqualIP : public Equal<IPAddr>
|
||||
{
|
||||
public:
|
||||
EqualIP(const vector<string> ¶ms) : Equal<IPAddr>(params) {}
|
||||
static string getName() { return Equal<IPAddr>::getName() + "IP"; }
|
||||
};
|
||||
|
||||
class EqualProtocol : public Equal<IPProto>
|
||||
{
|
||||
public:
|
||||
EqualProtocol(const vector<string> ¶ms) : Equal<IPProto>(params) {}
|
||||
static string getName() { return Equal<IPProto>::getName() + "Protocol"; }
|
||||
};
|
||||
|
||||
class DPort : public Invoker<uint16_t, ConnKey>
|
||||
{
|
||||
public:
|
||||
DPort(const vector<string> ¶ms)
|
||||
:
|
||||
Invoker<uint16_t, ConnKey>([] (const ConnKey &key) { return key.getDPort(); }, params) {}
|
||||
static string getName() { return Invoker<uint16_t, ConnKey>::getName() + "DPort"; }
|
||||
};
|
||||
|
||||
class SPort : public Invoker<uint16_t, ConnKey>
|
||||
{
|
||||
public:
|
||||
SPort(const vector<string> ¶ms)
|
||||
:
|
||||
Invoker<uint16_t, ConnKey>([] (const ConnKey &key) { return key.getSPort(); }, params) {}
|
||||
|
||||
static string getName() { return Invoker<uint16_t, ConnKey>::getName() + "SPort"; }
|
||||
};
|
||||
|
||||
class Dst : public Invoker<IPAddr, ConnKey>
|
||||
{
|
||||
public:
|
||||
Dst(const vector<string> ¶ms)
|
||||
:
|
||||
Invoker<IPAddr, ConnKey>([] (const ConnKey &key) { return key.getDst(); }, params) {}
|
||||
|
||||
static string getName() { return Invoker<IPAddr, ConnKey>::getName() + "Dst"; }
|
||||
};
|
||||
|
||||
class Src : public Invoker<IPAddr, ConnKey>
|
||||
{
|
||||
public:
|
||||
Src(const vector<string> ¶ms)
|
||||
:
|
||||
Invoker<IPAddr, ConnKey>([] (const ConnKey &key) { return key.getSrc(); }, params) {}
|
||||
|
||||
static string getName() { return Invoker<IPAddr, ConnKey>::getName() + "Src"; }
|
||||
};
|
||||
|
||||
class Protocol : public Invoker<IPProto, ConnKey>
|
||||
{
|
||||
public:
|
||||
Protocol(const vector<string> ¶ms)
|
||||
:
|
||||
Invoker<IPProto, ConnKey>([] (const ConnKey &key) { return key.getProto(); }, params) {}
|
||||
|
||||
static string getName() { return Invoker<IPProto, ConnKey>::getName() + "Protocol"; }
|
||||
};
|
||||
|
||||
void
|
||||
ConnKey::preload()
|
||||
{
|
||||
addMatcher<ConstantPort>();
|
||||
addMatcher<ConstantIP>();
|
||||
addMatcher<ConstantProtocol>();
|
||||
|
||||
addMatcher<EqualPort>();
|
||||
addMatcher<EqualIP>();
|
||||
addMatcher<EqualProtocol>();
|
||||
|
||||
addMatcher<DPort>();
|
||||
addMatcher<SPort>();
|
||||
addMatcher<Dst>();
|
||||
addMatcher<Src>();
|
||||
addMatcher<Protocol>();
|
||||
}
|
Reference in New Issue
Block a user