From: Serhii. Vlasiuk -X (svlasiuk - SOFTSERVE INC at Cisco) Date: Wed, 24 Jan 2024 19:55:50 +0000 (+0000) Subject: Pull request #4170: packet_tracer: add tenants to filters X-Git-Tag: 3.1.79.0~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=00556c7089983d86d2b2ce930233db6eaa9d3433;p=thirdparty%2Fsnort3.git Pull request #4170: packet_tracer: add tenants to filters Merge in SNORT/snort3 from ~SVLASIUK/snort3:pt_tenants_filter to master Squashed commit of the following: commit 93fc7a347f3e3792f2a896b234c3f9004b1a8092 Author: Serhii Vlasiuk Date: Fri Jan 19 15:59:54 2024 +0200 packet_tracer: add tenants to filters --- diff --git a/src/framework/packet_constraints.cc b/src/framework/packet_constraints.cc index 4b96cb5c4..939a287d1 100644 --- a/src/framework/packet_constraints.cc +++ b/src/framework/packet_constraints.cc @@ -31,20 +31,54 @@ namespace { inline bool match_constraints(const snort::PacketConstraints& cs, const snort::SfIp& sip, const snort::SfIp& dip, uint16_t sport, - uint16_t dport) + uint16_t dport, uint32_t tenant_id) { using SetBits = snort::PacketConstraints::SetBits; - return (!(cs.set_bits & SetBits::SRC_PORT) or (sport == cs.src_port)) and + bool res = (!(cs.set_bits & SetBits::SRC_PORT) or (sport == cs.src_port)) and (!(cs.set_bits & SetBits::DST_PORT) or (dport == cs.dst_port)) and (!(cs.set_bits & SetBits::SRC_IP) or (sip == cs.src_ip)) and (!(cs.set_bits & SetBits::DST_IP) or (dip == cs.dst_ip)); + + if (res && tenant_id && !cs.tenants.empty()) + { + auto it = std::find_if(cs.tenants.cbegin(), cs.tenants.cend(), + [tenant_id](uint32_t t){ return t == tenant_id; }); + + if (it == cs.tenants.cend()) + return false; + } + + return res; } } // namespace using namespace snort; +PacketConstraints::PacketConstraints(const PacketConstraints& other) : + ip_proto(other.ip_proto), src_port(other.src_port), dst_port(other.dst_port), + src_ip(other.src_ip), dst_ip(other.dst_ip), set_bits(other.set_bits), + match(other.match), tenants(other.tenants) +{} + +PacketConstraints& PacketConstraints::operator=(const PacketConstraints& other) +{ + if (this == &other) + return *this; + + ip_proto = other.ip_proto; + src_port = other.src_port; + dst_port = other.dst_port; + src_ip = other.src_ip; + dst_ip = other.dst_ip; + set_bits = other.set_bits; + match = other.match; + tenants = other.tenants; + + return *this; +} + bool PacketConstraints::operator==(const PacketConstraints& other) const { return set_bits == other.set_bits @@ -52,7 +86,8 @@ bool PacketConstraints::operator==(const PacketConstraints& other) const and ( !(set_bits & SRC_PORT) or src_port == other.src_port ) and ( !(set_bits & DST_PORT) or dst_port == other.dst_port ) and ( !(set_bits & SRC_IP) or src_ip == other.src_ip ) - and ( !(set_bits & DST_IP) or dst_ip == other.dst_ip ); + and ( !(set_bits & DST_IP) or dst_ip == other.dst_ip ) + and ( tenants == other.tenants ); } bool PacketConstraints::packet_match(const Packet& p) const @@ -76,8 +111,8 @@ bool PacketConstraints::packet_match(const Packet& p) const const auto sp = p.ptrs.sp; const auto dp = p.ptrs.dp; - return match_constraints(*this, sip, dip, sp, dp) or - match_constraints(*this, dip, sip, dp, sp); + return match_constraints(*this, sip, dip, sp, dp, p.pkth->tenant_id) or + match_constraints(*this, dip, sip, dp, sp, p.pkth->tenant_id); } bool PacketConstraints::flow_match(const Flow& f) const @@ -90,7 +125,7 @@ bool PacketConstraints::flow_match(const Flow& f) const return false; return match_constraints(*this, f.client_ip, f.server_ip, f.client_port, - f.server_port); + f.server_port, f.tenant); } #ifdef UNIT_TEST @@ -101,10 +136,10 @@ TEST_CASE("Packet constraints comparison", "[framework]") { SECTION("all unset") { - const PacketConstraints exp = { IpProtocol::TCP, 10, 20, - SfIp(), SfIp(), 0 }; - const PacketConstraints act = { IpProtocol::UDP, 30, 40, - SfIp(), SfIp(), 0 }; + const PacketConstraints exp = PacketConstraints(IpProtocol::TCP, 10, 20, + SfIp(), SfIp(), 0, true); + const PacketConstraints act = PacketConstraints(IpProtocol::UDP, 30, 40, + SfIp(), SfIp(), 0, true); CHECK( exp == act ); } @@ -112,12 +147,12 @@ TEST_CASE("Packet constraints comparison", "[framework]") { const uint32_t ip1 = 0x01010101; const uint32_t ip2 = 0x02020202; - const PacketConstraints exp = { IpProtocol::PROTO_NOT_SET, 10, 20, + const PacketConstraints exp = PacketConstraints(IpProtocol::PROTO_NOT_SET, 10, 20, SfIp(&ip1, AF_INET), SfIp(&ip2, AF_INET), - (uint8_t)~PacketConstraints::SetBits::DST_IP }; - const PacketConstraints act = { IpProtocol::PROTO_NOT_SET, 10, 20, + (uint8_t)~PacketConstraints::SetBits::DST_IP, true); + const PacketConstraints act = PacketConstraints(IpProtocol::PROTO_NOT_SET, 10, 20, SfIp(&ip1, AF_INET), SfIp(), - (uint8_t)~PacketConstraints::SetBits::DST_IP }; + (uint8_t)~PacketConstraints::SetBits::DST_IP, true); CHECK( exp == act ); } @@ -126,21 +161,31 @@ TEST_CASE("Packet constraints comparison", "[framework]") const uint32_t ip1 = 0x01010101; const uint32_t ip2 = 0x02020202; const uint32_t ip3 = 0x03030303; - const PacketConstraints exp = { IpProtocol::PROTO_NOT_SET, 0, 0, - SfIp(&ip1, AF_INET), SfIp(&ip2, AF_INET), (uint8_t)-1 }; - const PacketConstraints act = { IpProtocol::PROTO_NOT_SET, 0, 0, - SfIp(&ip3, AF_INET), SfIp(&ip2, AF_INET), (uint8_t)-1}; + const PacketConstraints exp = PacketConstraints(IpProtocol::PROTO_NOT_SET, 0, 0, + SfIp(&ip1, AF_INET), SfIp(&ip2, AF_INET), (uint8_t)-1, true); + const PacketConstraints act = PacketConstraints(IpProtocol::PROTO_NOT_SET, 0, 0, + SfIp(&ip3, AF_INET), SfIp(&ip2, AF_INET), (uint8_t)-1, true); CHECK( !(exp == act) ); } SECTION("equal") { + std::vector tenants1; + tenants1.push_back(100); + tenants1.push_back(200); + + std::vector tenants2; + tenants2.push_back(100); + tenants2.push_back(200); + const uint32_t ip1 = 0x01010101; const uint32_t ip2 = 0x02020202; - const PacketConstraints exp = { IpProtocol::PROTO_NOT_SET, 0, 0, - SfIp(&ip1, AF_INET), SfIp(&ip2, AF_INET), (uint8_t)-1 }; - const PacketConstraints act = { IpProtocol::PROTO_NOT_SET, 0, 0, - SfIp(&ip1, AF_INET), SfIp(&ip2, AF_INET), (uint8_t)-1 }; + PacketConstraints exp = PacketConstraints(IpProtocol::PROTO_NOT_SET, 0, 0, + SfIp(&ip1, AF_INET), SfIp(&ip2, AF_INET), (uint8_t)-1, true); + exp.tenants = tenants1; + PacketConstraints act = PacketConstraints(IpProtocol::PROTO_NOT_SET, 0, 0, + SfIp(&ip1, AF_INET), SfIp(&ip2, AF_INET), (uint8_t)-1, true); + act.tenants = tenants2; CHECK( exp == act ); } } @@ -171,7 +216,12 @@ TEST_CASE("Packet constraints matching", "[framework]") cs.src_ip = sip; cs.dst_ip = dip; - CHECK( true == match_constraints(cs, sip, dip, sport, dport) ); + std::vector tenants; + tenants.push_back(100); + tenants.push_back(200); + cs.tenants = tenants; + + CHECK( true == match_constraints(cs, sip, dip, sport, dport, 100) ); } SECTION("backwards") @@ -188,7 +238,7 @@ TEST_CASE("Packet constraints matching", "[framework]") cs.src_ip = sip; cs.dst_ip = dip; - CHECK( false == match_constraints(cs, dip, sip, dport, sport) ); + CHECK( false == match_constraints(cs, dip, sip, dport, sport, 0) ); } SECTION("any ip") @@ -201,7 +251,7 @@ TEST_CASE("Packet constraints matching", "[framework]") cs.src_port = sport; cs.dst_port = dport; - CHECK( true == match_constraints(cs, sip, dip, sport, dport) ); + CHECK( true == match_constraints(cs, sip, dip, sport, dport, 0) ); } SECTION("any port") @@ -214,7 +264,7 @@ TEST_CASE("Packet constraints matching", "[framework]") cs.src_ip = sip; cs.dst_ip = dip; - CHECK( true == match_constraints(cs, sip, dip, sport, dport) ); + CHECK( true == match_constraints(cs, sip, dip, sport, dport, 0) ); } SECTION("any src") @@ -227,7 +277,7 @@ TEST_CASE("Packet constraints matching", "[framework]") cs.dst_port = dport; cs.dst_ip = dip; - CHECK( true == match_constraints(cs, sip, dip, sport, dport) ); + CHECK( true == match_constraints(cs, sip, dip, sport, dport, 0) ); } } diff --git a/src/framework/packet_constraints.h b/src/framework/packet_constraints.h index 73e113359..ffe6c03bc 100644 --- a/src/framework/packet_constraints.h +++ b/src/framework/packet_constraints.h @@ -20,6 +20,8 @@ #ifndef PACKET_CONSTRAINTS_H #define PACKET_CONSTRAINTS_H +#include + #include "protocols/protocol_ids.h" #include "sfip/sf_ip.h" @@ -39,6 +41,15 @@ struct PacketConstraints DST_PORT = 1 << 4, }; + PacketConstraints() = default; + PacketConstraints(IpProtocol ip_proto, uint16_t src_port, uint16_t dst_port, + const snort::SfIp& src_ip, const snort::SfIp& dst_ip, uint8_t set_bits, bool match) : + ip_proto(ip_proto), src_port(src_port), dst_port(dst_port), + src_ip(src_ip), dst_ip(dst_ip), set_bits(set_bits), match(match) + {} + PacketConstraints(const PacketConstraints&); + PacketConstraints& operator=(const PacketConstraints& other); + bool operator==(const PacketConstraints& other) const; bool packet_match(const Packet& p) const; @@ -53,6 +64,8 @@ struct PacketConstraints uint8_t set_bits = 0; bool match = true; + + std::vector tenants; }; } // namespace snort diff --git a/src/network_inspectors/packet_tracer/packet_tracer.cc b/src/network_inspectors/packet_tracer/packet_tracer.cc index 5b52ecb58..108e75fac 100644 --- a/src/network_inspectors/packet_tracer/packet_tracer.cc +++ b/src/network_inspectors/packet_tracer/packet_tracer.cc @@ -464,9 +464,23 @@ void PacketTracer::update_constraints(const PacketConstraints* cs) constraints = *cs; constraints.src_ip.ntop(sipstr, sizeof(sipstr)); constraints.dst_ip.ntop(dipstr, sizeof(dipstr)); - LogMessage("Debugging packet tracer with %s-%hu and %s-%hu %hhu\n", + + std::string tenants = "none"; + if (constraints.tenants.size()) + { + std::ostringstream oss; + for (size_t i = 0; i < constraints.tenants.size(); ++i) + { + oss << constraints.tenants[i]; + if (i < constraints.tenants.size() - 1) + oss << ","; + } + tenants = oss.str(); + } + + LogMessage("Debugging packet tracer with %s-%hu and %s-%hu %hhu and tenants:%s\n", sipstr, constraints.src_port, dipstr, constraints.dst_port, - static_cast(constraints.ip_proto)); + static_cast(constraints.ip_proto), tenants.c_str()); shell_enabled = true; diff --git a/src/network_inspectors/packet_tracer/packet_tracer_module.cc b/src/network_inspectors/packet_tracer/packet_tracer_module.cc index 56c2e57d0..841b6c2b8 100644 --- a/src/network_inspectors/packet_tracer/packet_tracer_module.cc +++ b/src/network_inspectors/packet_tracer/packet_tracer_module.cc @@ -37,6 +37,20 @@ using namespace snort; +static void StrToVector(const std::string& s, + char delim, + std::vector& elems) +{ + std::istringstream ss(s); + std::string item; + while (std::getline(ss, item, delim)) + { + size_t pos; + uint32_t i = std::stoul(item, &pos); + elems.push_back(i); + } +} + static int enable(lua_State*); static int disable(lua_State*); @@ -58,6 +72,7 @@ static const Parameter enable_packet_tracer_params[] = {"src_port", Parameter::PT_INT, "0:65535", nullptr, "source port filter"}, {"dst_ip", Parameter::PT_STRING, nullptr, nullptr, "destination IP address filter"}, {"dst_port", Parameter::PT_INT, "0:65535", nullptr, "destination port filter"}, + {"tenants", Parameter::PT_STRING, nullptr, nullptr, "tenants filter"}, {nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr} }; @@ -71,7 +86,7 @@ static const Command packet_tracer_cmds[] = class PacketTracerDebug : public AnalyzerCommand { public: - PacketTracerDebug(PacketConstraints* cs); + PacketTracerDebug(const PacketConstraints* cs); bool execute(Analyzer&, void**) override; const char *stringify() override { return "PACKET_TRACER_DEBUG"; } @@ -80,11 +95,11 @@ class PacketTracerDebug : public AnalyzerCommand bool enable = false; }; -PacketTracerDebug::PacketTracerDebug(PacketConstraints* cs) +PacketTracerDebug::PacketTracerDebug(const PacketConstraints* cs) { if (cs) { - memcpy(&constraints, cs, sizeof(constraints)); + constraints = *cs; enable = true; } } @@ -107,6 +122,8 @@ static int enable(lua_State* L) const char *dipstr = luaL_optstring(L, 4, nullptr); int dport = luaL_optint(L, 5, 0); + const char *tenantsstr = luaL_optstring(L, 6, nullptr); + SfIp sip, dip; sip.clear(); dip.clear(); @@ -125,6 +142,9 @@ static int enable(lua_State* L) PacketConstraints constraints = {}; + if (tenantsstr) + StrToVector(tenantsstr, ',', constraints.tenants); + if (proto and (IpProtocol)proto < IpProtocol::PROTO_NOT_SET) { constraints.ip_proto = (IpProtocol)proto; diff --git a/src/trace/trace_parser.cc b/src/trace/trace_parser.cc index b10640fc9..5b132cfe4 100644 --- a/src/trace/trace_parser.cc +++ b/src/trace/trace_parser.cc @@ -358,8 +358,8 @@ TEST_CASE("packet constraints", "[TraceParser]") SECTION("ip_proto") { PROTO_OPTION(ip_proto, 6); - const PacketConstraints exp = { IpProtocol::TCP, 0, 0, - SfIp(), SfIp(), PacketConstraints::IP_PROTO }; + const PacketConstraints exp = PacketConstraints(IpProtocol::TCP, 0, 0, + SfIp(), SfIp(), PacketConstraints::IP_PROTO, true); CHECK(true == tp.set_constraints(ip_proto)); tp.finalize_constraints(); @@ -374,8 +374,8 @@ TEST_CASE("packet constraints", "[TraceParser]") { ADDR_OPTION(src_ip, "10.1.2.3"); const uint32_t exp_ip = 0x0302010a; - const PacketConstraints exp = { IpProtocol::PROTO_NOT_SET, 0, 0, - SfIp(&exp_ip, AF_INET), SfIp(), PacketConstraints::SRC_IP }; + const PacketConstraints exp = PacketConstraints(IpProtocol::PROTO_NOT_SET, 0, 0, + SfIp(&exp_ip, AF_INET), SfIp(), PacketConstraints::SRC_IP, true); CHECK(true == tp.set_constraints(src_ip)); tp.finalize_constraints(); @@ -394,8 +394,8 @@ TEST_CASE("packet constraints", "[TraceParser]") SECTION("src_port") { - const PacketConstraints exp = { IpProtocol::PROTO_NOT_SET, 100, 0, - SfIp(), SfIp(), PacketConstraints::SRC_PORT }; + const PacketConstraints exp = PacketConstraints(IpProtocol::PROTO_NOT_SET, 100, 0, + SfIp(), SfIp(), PacketConstraints::SRC_PORT, true); PORT_OPTION(src_port, 100); CHECK(true == tp.set_constraints(src_port)); @@ -411,8 +411,8 @@ TEST_CASE("packet constraints", "[TraceParser]") { ADDR_OPTION(dst_ip, "10.3.2.1"); const uint32_t exp_ip = 0x0102030a; - const PacketConstraints exp = { IpProtocol::PROTO_NOT_SET, 0, 0, - SfIp(), SfIp(&exp_ip, AF_INET), PacketConstraints::DST_IP }; + const PacketConstraints exp = PacketConstraints(IpProtocol::PROTO_NOT_SET, 0, 0, + SfIp(), SfIp(&exp_ip, AF_INET), PacketConstraints::DST_IP, true); CHECK(true == tp.set_constraints(dst_ip)); tp.finalize_constraints(); @@ -432,8 +432,8 @@ TEST_CASE("packet constraints", "[TraceParser]") SECTION("dst_port") { PORT_OPTION(dst_port, 200); - const PacketConstraints exp = { IpProtocol::PROTO_NOT_SET, 0, 200, - SfIp(), SfIp(), PacketConstraints::DST_PORT }; + const PacketConstraints exp = PacketConstraints(IpProtocol::PROTO_NOT_SET, 0, 200, + SfIp(), SfIp(), PacketConstraints::DST_PORT, true); CHECK(true == tp.set_constraints(dst_port)); tp.finalize_constraints();