};
#endif
+
+static const Parameter extend_to_service[] =
+{
+ { "extend_to_service", Parameter::PT_STRING, nullptr, nullptr,
+ "service to extend to" },
+
+ { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+static const Parameter service_extension[] =
+{
+ { "service", Parameter::PT_STRING, nullptr, nullptr,
+ "service to perform extension for" },
+
+ { "extend_to", Parameter::PT_LIST, extend_to_service, nullptr,
+ "comma separated list of services to extend to"},
+
+ { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
static const Parameter detection_params[] =
{
{ "allow_missing_so_rules", Parameter::PT_BOOL, nullptr, "false",
{ "max_continuations_per_flow", Parameter::PT_INT, "0:65535", "1024",
"maximum number of continuations stored simultaneously on the flow" },
+ { "service_extension", Parameter::PT_LIST, service_extension, nullptr,
+ "List of maps outlining single service extension to multiple services "
+ "(defaults to http:http2,http3; netbios-ssn:dcerpc)" },
+
{ nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
};
/* *INDENT-ON* */
#endif
}
-bool DetectionModule::end(const char*, int, SnortConfig* sc)
+bool DetectionModule::begin(const char* fqn, int idx, SnortConfig* sc)
{
+ if ( !strcmp(fqn, "detection.service_extension") and ( idx == 0 ) )
+ sc->service_extension.clear();
+
+ return true;
+}
+
+bool DetectionModule::add_service_extension(SnortConfig* sc)
+{
+ const bool ok = (sc->service_extension.insert({service, extend_to})).second;
+ if (!ok)
+ ParseWarning(WARN_CONF,"Duplicate service entry %s in service extension\n", service.c_str());
+ service.clear();
+ extend_to.clear();
+ return true;
+}
+
+bool DetectionModule::end(const char* fqn, int idx, SnortConfig* sc)
+{
+ if ( !strcmp(fqn, "detection.service_extension") )
+ {
+ if ( idx == 0 and service.empty() and extend_to.empty() )
+ return true;
+
+ if ( service.empty() )
+ {
+ ParseError("An entry in detection.service_extension missing a service name");
+ extend_to.clear();
+ return true;
+ }
+
+ if ( extend_to.empty() )
+ {
+ ParseError("Service %s in detection.service_extension missing extend_to", service.c_str());
+ service.clear();
+ return true;
+ }
+
+ return add_service_extension(sc);
+ }
+
if ( sc->offload_threads and ThreadConfig::get_instance_max() != 1 )
ParseError("You can not enable experimental offload with more than one packet thread.");
else if ( v.is("max_continuations_per_flow") )
sc->max_continuations = v.get_uint16();
+ else if ( v.is("service") )
+ service = v.get_string();
+
+ else if ( v.is("extend_to_service") )
+ extend_to.emplace_back(v.get_string());
+
return true;
}
public:
DetectionModule();
+ bool begin(const char*, int, snort::SnortConfig*) override;
bool set(const char*, Value&, SnortConfig*) override;
bool end(const char*, int, SnortConfig*) override;
void set_trace(const Trace*) const override;
const TraceOption* get_trace_options() const override;
+
+private:
+ bool add_service_extension(snort::SnortConfig*);
+
+ std::string service;
+ std::vector<std::string> extend_to;
};
}
return;
}
- // FIXIT-M update NHI and H2I api.buffers and remove the hard-coded foo below
for ( int i = 0; bufs[i]; ++i )
- {
buffer_map[bufs[i]].push_back(svc);
- if ( !strcmp(svc, "http") )
- {
- buffer_map[bufs[i]].push_back("http2");
- buffer_map[bufs[i]].push_back("http3");
- }
- }
if ( !strcmp(svc, "http") )
- {
buffer_map["file_data"].push_back("http");
- buffer_map["file_data"].push_back("http2");
- buffer_map["file_data"].push_back("http3");
- }
}
void add_default_services(SnortConfig* sc, const std::string& buf, OptTreeNode* otn)
continue;
CursorActionType cat = ofl->ips_opt->get_cursor_type();
- const char* s = ofl->ips_opt->get_name();
+ const char* opt = ofl->ips_opt->get_name();
if ( cat <= CAT_ADJUST )
{
if ( !guess )
- guess = guess_service(s);
+ guess = guess_service(opt);
continue;
}
- unsigned n = get_num_services(s);
+ unsigned n = get_num_services(opt);
if ( !n )
continue;
if ( n > 1 )
{
- multi_svc_buf = s;
+ multi_svc_buf = opt;
continue;
}
- s = get_service(s);
+ const char* opt_svc = get_service(opt);
+ const auto& search = sc->service_extension.find(opt_svc);
+ if (search != sc->service_extension.end())
+ {
+ multi_svc_buf = opt;
+ continue;
+ }
- if ( !svc.empty() and svc != s )
+ if ( !svc.empty() and svc != opt_svc )
{
ParseWarning(WARN_RULES, "%u:%u:%u has mixed service buffers (%s and %s)",
- otn->sigInfo.gid, otn->sigInfo.sid, otn->sigInfo.rev, svc.c_str(), s);
+ otn->sigInfo.gid, otn->sigInfo.sid, otn->sigInfo.rev, svc.c_str(), opt_svc);
}
- svc = s;
+ svc = opt_svc;
}
if ( !svc.empty() or !multi_svc_buf.empty() or guess )
otn->sigInfo.gid, otn->sigInfo.sid, otn->sigInfo.rev, guess);
add_service_to_otn(sc, otn, guess);
-
- if ( !strcmp(guess, "netbios-ssn") ) // :(
- add_service_to_otn(sc, otn, "dcerpc");
}
}
const SdPatternOption& rhs = static_cast<const SdPatternOption&>(ips);
- if ( config == rhs.config ) // FIXIT-H seems incorrect
+ if ( config == rhs.config )
return true;
return false;
bool enable_strict_reduction = false;
uint16_t max_continuations = 1024;
+ std::unordered_map<std::string, std::vector<std::string>> service_extension =
+ {
+ { "http", {"http2", "http3"} },
+ { "netbios-ssn", {"dcerpc"} },
+ };
+
//------------------------------------------------------
// process stuff
}
}
+static void add_service_to_otn_helper(SnortConfig* sc, OptTreeNode* otn, const char* svc_name)
+{
+ SnortProtocolId svc_id = sc->proto_ref->add(svc_name);
+
+ for ( const auto& si : otn->sigInfo.services )
+ if ( si.snort_protocol_id == svc_id )
+ return; // already added
+
+ SignatureServiceInfo si(svc_name, svc_id);
+ otn->sigInfo.services.emplace_back(si);
+}
+
void add_service_to_otn(SnortConfig* sc, OptTreeNode* otn, const char* svc_name)
{
if ( !strcmp(svc_name, "file") and otn->sigInfo.services.empty() )
return;
}
- if ( !strcmp(svc_name, "http") )
+ add_service_to_otn_helper(sc, otn, svc_name);
+ const auto& search = sc->service_extension.find(svc_name);
+ if ( search != sc->service_extension.end() )
{
- add_service_to_otn(sc, otn, "http2");
- add_service_to_otn(sc, otn, "http3");
+ for ( const auto& svc : search->second)
+ add_service_to_otn_helper(sc, otn, svc.c_str());
}
-
- SnortProtocolId svc_id = sc->proto_ref->add(svc_name);
-
- for ( const auto& si : otn->sigInfo.services )
- if ( si.snort_protocol_id == svc_id )
- return; // already added
-
- SignatureServiceInfo si(svc_name, svc_id);
- otn->sigInfo.services.emplace_back(si);
}
ListHead* get_rule_list(SnortConfig* sc, const char* s)