00001 //--------------------------------------------------------------------------
00002 // Copyright (C) 2014-2017 Cisco and/or its affiliates. All rights reserved.
00003 //
00004 // This program is free software; you can redistribute it and/or modify it
00005 // under the terms of the GNU General Public License Version 2 as published
00006 // by the Free Software Foundation. You may not use, modify or distribute
00007 // this program under any other version of the GNU General Public License.
00008 //
00009 // This program is distributed in the hope that it will be useful, but
00010 // WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00012 // General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License along
00015 // with this program; if not, write to the Free Software Foundation, Inc.,
00016 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017 //--------------------------------------------------------------------------
00018
00019 // modules.cc author Russ Combs <rucombs@cisco.com>
00020
00021 #ifdef HAVE_CONFIG_H
00022 #include "config.h"
00023 #endif
00024
00025 #include "modules.h"
00026
00027 #include "codecs/codec_module.h"
00028 #include "detection/fp_config.h"
00029 #include "filters/detection_filter.h"
00030 #include "filters/rate_filter.h"
00031 #include "filters/sfrf.h"
00032 #include "filters/sfthd.h"
00033 #include "filters/sfthreshold.h"
00034 #include "flow/ha_module.h"
00035 #include "framework/module.h"
00036 #include "host_tracker/host_tracker_module.h"
00037 #include "host_tracker/host_cache_module.h"
00038 #include "latency/latency_module.h"
00039 #include "log/messages.h"
00040 #include "log/packet_tracer.h"
00041 #include "managers/module_manager.h"
00042 #include "managers/plugin_manager.h"
00043 #include "memory/memory_module.h"
00044 #include "packet_io/sfdaq_module.h"
00045 #include "parser/config_file.h"
00046 #include "parser/parse_conf.h"
00047 #include "parser/parse_ip.h"
00048 #include "parser/parser.h"
00049 #include "profiler/profiler_defs.h"
00050 #include "search_engines/pat_stats.h"
00051 #include "side_channel/side_channel_module.h"
00052 #include "sfip/sf_ipvar.h"
00053 #include "stream/stream.h"
00054 #include "target_based/sftarget_data.h"
00055 #include "target_based/snort_protocols.h"
00056
00057 #include "snort_config.h"
00058 #include "snort_module.h"
00059 #include "thread_config.h"
00060
00061 using namespace std;
00062
00063 //-------------------------------------------------------------------------
00064 // detection module
00065 //-------------------------------------------------------------------------
00066
00067 /* *INDENT-OFF* */ // Uncrustify handles this section incorrectly.
00068 static const Parameter detection_params[] =
00069 {
00070 { "asn1", Parameter::PT_INT, "1:", "256",
00071 "maximum decode nodes" },
00072
00073 { "offload_limit", Parameter::PT_INT, "0:", "99999",
00074 "minimum sizeof PDU to offload fast pattern search (defaults to disabled)" },
00075
00076 { "offload_threads", Parameter::PT_INT, "0:", "0",
00077 "maximum number of simultaneous offloads (defaults to disabled)" },
00078
00079 { "pcre_enable", Parameter::PT_BOOL, nullptr, "true",
00080 "disable pcre pattern matching" },
00081
00082 { "pcre_match_limit", Parameter::PT_INT, "-1:1000000", "1500",
00083 "limit pcre backtracking, -1 = max, 0 = off" },
00084
00085 { "pcre_match_limit_recursion", Parameter::PT_INT, "-1:10000", "1500",
00086 "limit pcre stack consumption, -1 = max, 0 = off" },
00087
00088 { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
00089 };
00090 /* *INDENT-ON* */
00091
00092 #define detection_help \
00093 "configure general IPS rule processing parameters"
00094
00095 class DetectionModule : public Module
00096 {
00097 public:
00098 DetectionModule() :
00099 Module("detection", detection_help, detection_params, false, &TRACE_NAME(detection)) {}
00100 bool set(const char*, Value&, SnortConfig*) override;
00101
00102 const PegInfo* get_pegs() const override
00103 { return pc_names; }
00104
00105 PegCount* get_counts() const override
00106 { return (PegCount*) &pc; }
00107
00108 Usage get_usage() const override
00109 { return GLOBAL; }
00110 };
00111
00112 bool DetectionModule::set(const char* fqn, Value& v, SnortConfig* sc)
00113 {
00114 if ( v.is("asn1") )
00115 sc->asn1_mem = v.get_long();
00116
00117 else if ( v.is("offload_limit") )
00118 sc->offload_limit = v.get_long();
00119
00120 else if ( v.is("offload_threads") )
00121 sc->offload_threads = v.get_long();
00122
00123 else if ( v.is("pcre_enable") )
00124 v.update_mask(sc->run_flags, RUN_FLAG__NO_PCRE, true);
00125
00126 else if ( v.is("pcre_match_limit") )
00127 sc->pcre_match_limit = v.get_long();
00128
00129 else if ( v.is("pcre_match_limit_recursion") )
00130 sc->pcre_match_limit_recursion = v.get_long();
00131
00132 else
00133 return Module::set(fqn, v, sc);
00134
00135 return true;
00136 }
00137
00138 //-------------------------------------------------------------------------
00139 // event queue module
00140 //-------------------------------------------------------------------------
00141
00142 static const Parameter event_queue_params[] =
00143 {
00144 { "max_queue", Parameter::PT_INT, "1:", "8",
00145 "maximum events to queue" },
00146
00147 { "log", Parameter::PT_INT, "1:", "3",
00148 "maximum events to log" },
00149
00150 { "order_events", Parameter::PT_ENUM,
00151 "priority|content_length", "content_length",
00152 "criteria for ordering incoming events" },
00153
00154 { "process_all_events", Parameter::PT_BOOL, nullptr, "false",
00155 "process just first action group or all action groups" },
00156
00157 { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
00158 };
00159
00160 #define event_queue_help \
00161 "configure event queue parameters"
00162
00163 class EventQueueModule : public Module
00164 {
00165 public:
00166 EventQueueModule() : Module("event_queue", event_queue_help, event_queue_params) { }
00167 bool set(const char*, Value&, SnortConfig*) override;
00168
00169 Usage get_usage() const override
00170 { return CONTEXT; }
00171 };
00172
00173 bool EventQueueModule::set(const char*, Value& v, SnortConfig* sc)
00174 {
00175 EventQueueConfig* eq = sc->event_queue_config;
00176
00177 if ( v.is("max_queue") )
00178 eq->max_events = v.get_long();
00179
00180 else if ( v.is("log") )
00181 eq->log_events = v.get_long();
00182
00183 else if ( v.is("order_events") )
00184 {
00185 if ( v.get_long() )
00186 eq->order = SNORT_EVENTQ_CONTENT_LEN;
00187 else
00188 eq->order = SNORT_EVENTQ_PRIORITY;
00189 }
00190 else if ( v.is("process_all_events") )
00191 eq->process_all_events = v.get_bool();
00192
00193 else
00194 return false;
00195
00196 if ( eq->max_events < eq->log_events )
00197 eq->max_events = eq->log_events;
00198
00199 return true;
00200 }
00201
00202 //-------------------------------------------------------------------------
00203 // search engine module
00204 //-------------------------------------------------------------------------
00205
00206 function<const char*()> get_search_methods = []()
00207 { return PluginManager::get_available_plugins(PT_SEARCH_ENGINE); };
00208
00209 static const Parameter search_engine_params[] =
00210 {
00211 { "bleedover_port_limit", Parameter::PT_INT, "1:", "1024",
00212 "maximum ports in rule before demotion to any-any port group" },
00213
00214 { "bleedover_warnings_enabled", Parameter::PT_BOOL, nullptr, "false",
00215 "print warning if a rule is demoted to any-any port group" },
00216
00217 { "enable_single_rule_group", Parameter::PT_BOOL, nullptr, "false",
00218 "put all rules into one group" },
00219
00220 { "debug", Parameter::PT_BOOL, nullptr, "false",
00221 "print verbose fast pattern info" },
00222
00223 { "debug_print_nocontent_rule_tests", Parameter::PT_BOOL, nullptr, "false",
00224 "print rule group info during packet evaluation" },
00225
00226 { "debug_print_rule_group_build_details", Parameter::PT_BOOL, nullptr, "false",
00227 "print rule group info during compilation" },
00228
00229 { "debug_print_rule_groups_uncompiled", Parameter::PT_BOOL, nullptr, "false",
00230 "prints uncompiled rule group information" },
00231
00232 { "debug_print_rule_groups_compiled", Parameter::PT_BOOL, nullptr, "false",
00233 "prints compiled rule group information" },
00234
00235 { "max_pattern_len", Parameter::PT_INT, "0:", "0",
00236 "truncate patterns when compiling into state machine (0 means no maximum)" },
00237
00238 { "max_queue_events", Parameter::PT_INT, "2:100", "5", // upper bound is MAX_EVENT_MATCH
00239 "maximum number of matching fast pattern states to queue per packet" },
00240
00241 { "inspect_stream_inserts", Parameter::PT_BOOL, nullptr, "false",
00242 "inspect reassembled payload - disabling is good for performance, bad for detection" },
00243
00244 { "search_method", Parameter::PT_DYNAMIC, (void*)&get_search_methods, "ac_bnfa",
00245 "set fast pattern algorithm - choose available search engine" },
00246
00247 { "search_optimize", Parameter::PT_BOOL, nullptr, "true",
00248 "tweak state machine construction for better performance" },
00249
00250 { "show_fast_patterns", Parameter::PT_BOOL, nullptr, "false",
00251 "print fast pattern info for each rule" },
00252
00253 { "split_any_any", Parameter::PT_BOOL, nullptr, "true",
00254 "evaluate any-any rules separately to save memory" },
00255
00256 { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
00257 };
00258
00259 #define search_engine_help \
00260 "configure fast pattern matcher"
00261
00262 THREAD_LOCAL PatMatQStat pmqs;
00263
00264 const PegInfo mpse_pegs[] =
00265 {
00266 { CountType::SUM, "max_queued", "maximum fast pattern matches queued for further evaluation" },
00267 { CountType::SUM, "total_flushed", "fast pattern matches discarded due to overflow" },
00268 { CountType::SUM, "total_inserts", "total fast pattern hits" },
00269 { CountType::SUM, "total_unique", "total unique fast pattern hits" },
00270 { CountType::SUM, "non_qualified_events", "total non-qualified events" },
00271 { CountType::SUM, "qualified_events", "total qualified events" },
00272 { CountType::SUM, "searched_bytes", "total bytes searched" },
00273 { CountType::END, nullptr, nullptr }
00274 };
00275
00276 class SearchEngineModule : public Module
00277 {
00278 public:
00279 SearchEngineModule() : Module("search_engine", search_engine_help, search_engine_params) { }
00280 bool set(const char*, Value&, SnortConfig*) override;
00281
00282 const PegInfo* get_pegs() const override
00283 { return mpse_pegs; }
00284
00285 PegCount* get_counts() const override
00286 { return (PegCount*)&pmqs; }
00287
00288 Usage get_usage() const override
00289 { return GLOBAL; }
00290 };
00291
00292 bool SearchEngineModule::set(const char*, Value& v, SnortConfig* sc)
00293 {
00294 FastPatternConfig* fp = sc->fast_pattern_config;
00295
00296 if ( v.is("bleedover_port_limit") )
00297 fp->set_bleed_over_port_limit(v.get_long());
00298
00299 else if ( v.is("bleedover_warnings_enabled") )
00300 {
00301 if ( v.get_bool() )
00302 fp->set_bleed_over_warnings(); // FIXIT-L these should take arg
00303 }
00304 else if ( v.is("enable_single_rule_group") )
00305 {
00306 if ( v.get_bool() )
00307 fp->set_single_rule_group();
00308 }
00309 else if ( v.is("debug") )
00310 {
00311 if ( v.get_bool() )
00312 fp->set_debug_mode();
00313 }
00314 else if ( v.is("debug_print_nocontent_rule_tests") )
00315 {
00316 if ( v.get_bool() )
00317 fp->set_debug_print_nc_rules();
00318 }
00319 else if ( v.is("debug_print_rule_group_build_details") )
00320 {
00321 if ( v.get_bool() )
00322 fp->set_debug_print_rule_group_build_details();
00323 }
00324 else if ( v.is("debug_print_rule_groups_uncompiled") )
00325 {
00326 if ( v.get_bool() )
00327 fp->set_debug_print_rule_groups_uncompiled();
00328 }
00329 else if ( v.is("debug_print_rule_groups_compiled") )
00330 {
00331 if ( v.get_bool() )
00332 fp->set_debug_print_rule_groups_compiled();
00333 }
00334 else if ( v.is("max_pattern_len") )
00335 fp->set_max_pattern_len(v.get_long());
00336
00337 else if ( v.is("max_queue_events") )
00338 fp->set_max_queue_events(v.get_long());
00339
00340 else if ( v.is("inspect_stream_inserts") )
00341 fp->set_stream_insert(v.get_bool());
00342
00343 else if ( v.is("search_method") )
00344 {
00345 if ( !fp->set_search_method(v.get_string()) )
00346 return false;
00347 }
00348 else if ( v.is("search_optimize") )
00349 fp->set_search_opt(v.get_long());
00350
00351 else if ( v.is("show_fast_patterns") )
00352 fp->set_debug_print_fast_patterns(v.get_bool());
00353
00354 else if ( v.is("split_any_any") )
00355 fp->set_split_any_any(v.get_long());
00356
00357 else
00358 return false;
00359
00360 return true;
00361 }
00362
00363 // -----------------------------------------------------------------------------
00364 // profiler module
00365 // -----------------------------------------------------------------------------
00366
00367 static const Parameter profiler_time_params[] =
00368 {
00369 { "show", Parameter::PT_BOOL, nullptr, "true",
00370 "show module time profile stats" },
00371
00372 { "count", Parameter::PT_INT, "0:", "0",
00373 "limit results to count items per level (0 = no limit)" },
00374
00375 { "sort", Parameter::PT_ENUM,
00376 "none | checks | avg_check | total_time ",
00377 "total_time", "sort by given field" },
00378
00379 { "max_depth", Parameter::PT_INT, "-1:", "-1",
00380 "limit depth to max_depth (-1 = no limit)" },
00381
00382 { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
00383 };
00384
00385 static const Parameter profiler_memory_params[] =
00386 {
00387 { "show", Parameter::PT_BOOL, nullptr, "true",
00388 "show module memory profile stats" },
00389
00390 { "count", Parameter::PT_INT, "0:", "0",
00391 "limit results to count items per level (0 = no limit)" },
00392
00393 { "sort", Parameter::PT_ENUM,
00394 "none | allocations | total_used | avg_allocation ",
00395 "total_used", "sort by given field" },
00396
00397 { "max_depth", Parameter::PT_INT, "-1:", "-1",
00398 "limit depth to max_depth (-1 = no limit)" },
00399
00400 { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
00401 };
00402
00403 static const Parameter profiler_rule_params[] =
00404 {
00405 { "show", Parameter::PT_BOOL, nullptr, "true",
00406 "show rule time profile stats" },
00407
00408 { "count", Parameter::PT_INT, "0:", "0",
00409 "print results to given level (0 = all)" },
00410
00411 { "sort", Parameter::PT_ENUM,
00412 "none | checks | avg_check | total_time | matches | no_matches | "
00413 "avg_match | avg_no_match",
00414 "total_time", "sort by given field" },
00415
00416 { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
00417 };
00418
00419 static const Parameter profiler_params[] = // FIXIT-L add help
00420 {
00421 { "modules", Parameter::PT_TABLE, profiler_time_params, nullptr,
00422 "module time profiling" },
00423
00424 { "memory", Parameter::PT_TABLE, profiler_memory_params, nullptr,
00425 "module memory profiling" },
00426
00427 { "rules", Parameter::PT_TABLE, profiler_rule_params, nullptr,
00428 "rule time profiling" },
00429
00430 { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
00431 };
00432
00433 #define profiler_help \
00434 "configure profiling of rules and/or modules"
00435
00436 template<typename T>
00437 static bool s_profiler_module_set_max_depth(T& config, Value& v)
00438 { config.max_depth = v.get_long(); return true; }
00439
00440 static bool s_profiler_module_set_max_depth(RuleProfilerConfig&, Value&)
00441 { return false; }
00442
00443 template<typename T>
00444 static bool s_profiler_module_set(T& config, Value& v)
00445 {
00446 if ( v.is("count") )
00447 config.count = v.get_long();
00448
00449 else if ( v.is("show") )
00450 config.show = v.get_bool();
00451
00452 else if ( v.is("sort") )
00453 config.sort = static_cast<typename T::Sort>(v.get_long());
00454
00455 else if ( v.is("max_depth") )
00456 return s_profiler_module_set_max_depth(config, v);
00457
00458 else
00459 return false;
00460
00461 return true;
00462 }
00463
00464 class ProfilerModule : public Module
00465 {
00466 public:
00467 ProfilerModule() : Module("profiler", profiler_help, profiler_params) { }
00468 bool set(const char*, Value&, SnortConfig*) override;
00469
00470 Usage get_usage() const override
00471 { return GLOBAL; }
00472 };
00473
00474 bool ProfilerModule::set(const char* fqn, Value& v, SnortConfig* sc)
00475 {
00476 const char* spt = "profiler.modules";
00477 const char* spm = "profiler.memory";
00478 const char* spr = "profiler.rules";
00479
00480 if ( !strncmp(fqn, spt, strlen(spt)) )
00481 return s_profiler_module_set(sc->profiler->time, v);
00482
00483 else if ( !strncmp(fqn, spm, strlen(spm)) )
00484 return s_profiler_module_set(sc->profiler->memory, v);
00485
00486 else if ( !strncmp(fqn, spr, strlen(spr)) )
00487 return s_profiler_module_set(sc->profiler->rule, v);
00488
00489 return false;
00490 }
00491
00492 //-------------------------------------------------------------------------
00493 // classification module
00494 //-------------------------------------------------------------------------
00495 // FIXIT-L signature.{h,cc} has type and name confused
00496 // the keys here make more sense
00497
00498 #define classifications_help \
00499 "define rule categories with priority"
00500
00501 static const Parameter classification_params[] =
00502 {
00503 { "name", Parameter::PT_STRING, nullptr, nullptr,
00504 "name used with classtype rule option" },
00505
00506 { "priority", Parameter::PT_INT, "0:", "1",
00507 "default priority for class" },
00508
00509 { "text", Parameter::PT_STRING, nullptr, nullptr,
00510 "description of class" },
00511
00512 { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
00513 };
00514
00515 class ClassificationsModule : public Module
00516 {
00517 public:
00518 ClassificationsModule() :
00519 Module("classifications", classifications_help, classification_params, true) { }
00520
00521 bool set(const char*, Value&, SnortConfig*) override;
00522 bool begin(const char*, int, SnortConfig*) override;
00523 bool end(const char*, int, SnortConfig*) override;
00524
00525 Usage get_usage() const override
00526 { return GLOBAL; }
00527
00528 private:
00529 string name;
00530 string text;
00531 int priority;
00532 };
00533
00534 bool ClassificationsModule::begin(const char*, int, SnortConfig*)
00535 {
00536 name.erase();
00537 text.erase();
00538 priority = 1;
00539 return true;
00540 }
00541
00542 bool ClassificationsModule::end(const char*, int idx, SnortConfig* sc)
00543 {
00544 if ( idx )
00545 AddClassification(sc, name.c_str(), text.c_str(), priority);
00546 return true;
00547 }
00548
00549 bool ClassificationsModule::set(const char*, Value& v, SnortConfig*)
00550 {
00551 if ( v.is("name") )
00552 name = v.get_string();
00553
00554 else if ( v.is("priority") )
00555 priority = v.get_long();
00556
00557 else if ( v.is("text") )
00558 text = v.get_string();
00559
00560 else
00561 return false;
00562
00563 return true;
00564 }
00565
00566 //-------------------------------------------------------------------------
00567 // reference module
00568 //-------------------------------------------------------------------------
00569
00570 #define reference_help \
00571 "define reference systems used in rules"
00572
00573 static const Parameter reference_params[] =
00574 {
00575 { "name", Parameter::PT_STRING, nullptr, nullptr,
00576 "name used with reference rule option" },
00577
00578 { "url", Parameter::PT_STRING, nullptr, nullptr,
00579 "where this reference is defined" },
00580
00581 { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
00582 };
00583
00584 class ReferencesModule : public Module
00585 {
00586 public:
00587 ReferencesModule() :
00588 Module("references", reference_help, reference_params, true) { }
00589
00590 bool set(const char*, Value&, SnortConfig*) override;
00591 bool begin(const char*, int, SnortConfig*) override;
00592 bool end(const char*, int, SnortConfig*) override;
00593
00594 Usage get_usage() const override
00595 { return GLOBAL; }
00596
00597 private:
00598 string name;
00599 string url;
00600 };
00601
00602 bool ReferencesModule::begin(const char*, int, SnortConfig*)
00603 {
00604 name.erase();
00605 url.erase();
00606 return true;
00607 }
00608
00609 bool ReferencesModule::end(const char*, int idx, SnortConfig* sc)
00610 {
00611 if ( idx )
00612 ReferenceSystemAdd(sc, name.c_str(), url.c_str());
00613 return true;
00614 }
00615
00616 bool ReferencesModule::set(const char*, Value& v, SnortConfig*)
00617 {
00618 if ( v.is("name") )
00619 name = v.get_string();
00620
00621 else if ( v.is("url") )
00622 url = v.get_string();
00623
00624 else
00625 return false;
00626
00627 return true;
00628 }
00629
00630 //-------------------------------------------------------------------------
00631 // alerts module
00632 //-------------------------------------------------------------------------
00633
00634 static const Parameter alerts_params[] =
00635 {
00636 { "alert_with_interface_name", Parameter::PT_BOOL, nullptr, "false",
00637 "include interface in alert info (fast, full, or syslog only)" },
00638
00639 { "default_rule_state", Parameter::PT_BOOL, nullptr, "true",
00640 "enable or disable ips rules" },
00641
00642 { "detection_filter_memcap", Parameter::PT_INT, "0:", "1048576",
00643 "set available bytes of memory for detection_filters" },
00644
00645 { "event_filter_memcap", Parameter::PT_INT, "0:", "1048576",
00646 "set available bytes of memory for event_filters" },
00647
00648 { "log_references", Parameter::PT_BOOL, nullptr, "false",
00649 "include rule references in alert info (full only)" },
00650
00651 { "order", Parameter::PT_STRING, nullptr, "pass drop alert log",
00652 "change the order of rule action application" },
00653
00654 { "rate_filter_memcap", Parameter::PT_INT, "0:", "1048576",
00655 "set available bytes of memory for rate_filters" },
00656
00657 { "reference_net", Parameter::PT_STRING, nullptr, nullptr,
00658 "set the CIDR for homenet "
00659 "(for use with -l or -B, does NOT change $HOME_NET in IDS mode)" },
00660
00661 { "stateful", Parameter::PT_BOOL, nullptr, "false",
00662 "don't alert w/o established session (note: rule action still taken)" },
00663
00664 { "tunnel_verdicts", Parameter::PT_STRING, nullptr, nullptr,
00665 "let DAQ handle non-allow verdicts for gtp|teredo|6in4|4in6|4in4|6in6|gre|mpls traffic" },
00666
00667 { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
00668 };
00669
00670 #define alerts_help \
00671 "configure alerts"
00672
00673 class AlertsModule : public Module
00674 {
00675 public:
00676 AlertsModule() : Module("alerts", alerts_help, alerts_params) { }
00677 bool set(const char*, Value&, SnortConfig*) override;
00678
00679 Usage get_usage() const override
00680 { return GLOBAL; }
00681 };
00682
00683 bool AlertsModule::set(const char*, Value& v, SnortConfig* sc)
00684 {
00685 if ( v.is("alert_with_interface_name") )
00686 v.update_mask(sc->output_flags, OUTPUT_FLAG__ALERT_IFACE);
00687
00688 else if ( v.is("default_rule_state") )
00689 sc->default_rule_state = v.get_bool();
00690
00691 else if ( v.is("detection_filter_memcap") )
00692 sc->detection_filter_config->memcap = v.get_long();
00693
00694 else if ( v.is("event_filter_memcap") )
00695 sc->threshold_config->memcap = v.get_long();
00696
00697 else if ( v.is("log_references") )
00698 v.update_mask(sc->output_flags, OUTPUT_FLAG__ALERT_REFS);
00699
00700 else if ( v.is("order") )
00701 OrderRuleLists(sc, v.get_string());
00702
00703 else if ( v.is("rate_filter_memcap") )
00704 sc->rate_filter_config->memcap = v.get_long();
00705
00706 else if ( v.is("reference_net") )
00707 return ( sc->homenet.set(v.get_string()) == SFIP_SUCCESS );
00708
00709 else if ( v.is("stateful") )
00710 v.update_mask(sc->run_flags, RUN_FLAG__ASSURE_EST);
00711
00712 else if ( v.is("tunnel_verdicts") )
00713 sc->set_tunnel_verdicts(v.get_string());
00714
00715 else
00716 return false;
00717
00718 return true;
00719 }
00720
00721 //-------------------------------------------------------------------------
00722 // output module
00723 //-------------------------------------------------------------------------
00724
00725 static const Parameter output_event_trace_params[] =
00726 {
00727 { "max_data", Parameter::PT_INT, "0:65535", "0",
00728 "maximum amount of packet data to capture" },
00729
00730 { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
00731 };
00732
00733 static const Parameter output_params[] =
00734 {
00735 { "dump_chars_only", Parameter::PT_BOOL, nullptr, "false",
00736 "turns on character dumps (same as -C)" },
00737
00738 { "dump_payload", Parameter::PT_BOOL, nullptr, "false",
00739 "dumps application layer (same as -d)" },
00740
00741 { "dump_payload_verbose", Parameter::PT_BOOL, nullptr, "false",
00742 "dumps raw packet starting at link layer (same as -X)" },
00743
00744 { "event_trace", Parameter::PT_TABLE, output_event_trace_params, nullptr,
00745 "" },
00746
00747 { "quiet", Parameter::PT_BOOL, nullptr, "false",
00748 "suppress non-fatal information (still show alerts, same as -q)" },
00749
00750 { "logdir", Parameter::PT_STRING, nullptr, ".",
00751 "where to put log files (same as -l)" },
00752
00753 { "obfuscate", Parameter::PT_BOOL, nullptr, "false",
00754 "obfuscate the logged IP addresses (same as -O)" },
00755
00756 { "obfuscate_pii", Parameter::PT_BOOL, nullptr, "false",
00757 "mask all but the last 4 characters of credit card and social security numbers" },
00758
00759 { "show_year", Parameter::PT_BOOL, nullptr, "false",
00760 "include year in timestamp in the alert and log files (same as -y)" },
00761
00762 { "tagged_packet_limit", Parameter::PT_INT, "0:", "256",
00763 "maximum number of packets tagged for non-packet metrics" },
00764
00765 { "verbose", Parameter::PT_BOOL, nullptr, "false",
00766 "be verbose (same as -v)" },
00767
00768 #ifdef REG_TEST
00769 { "wide_hex_dump", Parameter::PT_BOOL, nullptr, "true",
00770 #else
00771 { "wide_hex_dump", Parameter::PT_BOOL, nullptr, "false",
00772 #endif
00773 "output 20 bytes per lines instead of 16 when dumping buffers" },
00774
00775 { "enable_packet_trace", Parameter::PT_BOOL, nullptr, "false",
00776 "enable summary output of state that determined packet verdict" },
00777
00778 { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
00779 };
00780
00781 #define output_help \
00782 "configure general output parameters"
00783
00784 class OutputModule : public Module
00785 {
00786 public:
00787 OutputModule() : Module("output", output_help, output_params) { }
00788 bool set(const char*, Value&, SnortConfig*) override;
00789
00790 Usage get_usage() const override
00791 { return GLOBAL; }
00792 };
00793
00794 bool OutputModule::set(const char*, Value& v, SnortConfig* sc)
00795 {
00796 if ( v.is("dump_chars_only") )
00797 v.update_mask(sc->output_flags, OUTPUT_FLAG__CHAR_DATA);
00798
00799 else if ( v.is("dump_payload") )
00800 v.update_mask(sc->output_flags, OUTPUT_FLAG__APP_DATA);
00801
00802 else if ( v.is("dump_payload_verbose") )
00803 v.update_mask(sc->output_flags, OUTPUT_FLAG__VERBOSE_DUMP);
00804
00805 else if ( v.is("enable_packet_trace") )
00806 sc->enable_packet_trace = v.get_bool();
00807
00808 else if ( v.is("quiet") )
00809 v.update_mask(sc->logging_flags, LOGGING_FLAG__QUIET);
00810
00811 else if ( v.is("logdir") )
00812 sc->log_dir = v.get_string();
00813
00814 else if ( v.is("max_data") )
00815 sc->event_trace_max = v.get_long();
00816
00817 else if ( v.is("obfuscate") )
00818 v.update_mask(sc->output_flags, OUTPUT_FLAG__OBFUSCATE);
00819
00820 else if ( v.is("obfuscate_pii") )
00821 sc->obfuscate_pii = v.get_bool();
00822
00823 else if ( v.is("show_year") )
00824 v.update_mask(sc->output_flags, OUTPUT_FLAG__INCLUDE_YEAR);
00825
00826 else if ( v.is("tagged_packet_limit") )
00827 sc->tagged_packet_limit = v.get_long();
00828
00829 else if ( v.is("verbose") )
00830 v.update_mask(sc->logging_flags, LOGGING_FLAG__VERBOSE);
00831
00832 else if ( v.is("wide_hex_dump") )
00833 v.update_mask(sc->output_flags, OUTPUT_FLAG__WIDE_HEX);
00834
00835 else
00836 return false;
00837
00838 return true;
00839 }
00840
00841 //-------------------------------------------------------------------------
00842 // active module
00843 //-------------------------------------------------------------------------
00844
00845 static const Parameter active_params[] =
00846 {
00847 { "attempts", Parameter::PT_INT, "0:20", "0",
00848 "number of TCP packets sent per response (with varying sequence numbers)" },
00849
00850 { "device", Parameter::PT_STRING, nullptr, nullptr,
00851 "use 'ip' for network layer responses or 'eth0' etc for link layer" },
00852
00853 { "dst_mac", Parameter::PT_STRING, nullptr, nullptr,
00854 "use format '01:23:45:67:89:ab'" },
00855
00856 { "max_responses", Parameter::PT_INT, "0:", "0",
00857 "maximum number of responses" },
00858
00859 { "min_interval", Parameter::PT_INT, "1:", "255",
00860 "minimum number of seconds between responses" },
00861
00862 { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
00863 };
00864
00865 #define active_help \
00866 "configure responses"
00867
00868 class ActiveModule : public Module
00869 {
00870 public:
00871 ActiveModule() : Module("active", active_help, active_params) { }
00872 bool set(const char*, Value&, SnortConfig*) override;
00873
00874 Usage get_usage() const override
00875 { return GLOBAL; }
00876 };
00877
00878 bool ActiveModule::set(const char*, Value& v, SnortConfig* sc)
00879 {
00880 if ( v.is("attempts") )
00881 sc->respond_attempts = v.get_long();
00882
00883 else if ( v.is("device") )
00884 sc->respond_device = v.get_string();
00885
00886 else if ( v.is("dst_mac") )
00887 sc->set_dst_mac(v.get_string());
00888
00889 else if ( v.is("max_responses") )
00890 sc->max_responses = v.get_long();
00891
00892 else if ( v.is("min_interval") )
00893 sc->min_interval = v.get_long();
00894
00895 else
00896 return false;
00897
00898 return true;
00899 }
00900
00901 //-------------------------------------------------------------------------
00902 // packets module
00903 //-------------------------------------------------------------------------
00904
00905 static const Parameter packets_params[] =
00906 {
00907 { "address_space_agnostic", Parameter::PT_BOOL, nullptr, "false",
00908 "determines whether DAQ address space info is used to track fragments and connections" },
00909
00910 { "bpf_file", Parameter::PT_STRING, nullptr, nullptr,
00911 "file with BPF to select traffic for Snort" },
00912
00913 { "limit", Parameter::PT_INT, "0:", "0",
00914 "maximum number of packets to process before stopping (0 is unlimited)" },
00915
00916 { "skip", Parameter::PT_INT, "0:", "0",
00917 "number of packets to skip before before processing" },
00918
00919 { "vlan_agnostic", Parameter::PT_BOOL, nullptr, "false",
00920 "determines whether VLAN info is used to track fragments and connections" },
00921
00922 { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
00923 };
00924
00925 #define packets_help \
00926 "configure basic packet handling"
00927
00928 class PacketsModule : public Module
00929 {
00930 public:
00931 PacketsModule() : Module("packets", packets_help, packets_params) { }
00932 bool set(const char*, Value&, SnortConfig*) override;
00933
00934 Usage get_usage() const override
00935 { return GLOBAL; }
00936 };
00937
00938 bool PacketsModule::set(const char*, Value& v, SnortConfig* sc)
00939 {
00940 if ( v.is("address_space_agnostic") )
00941 sc->addressspace_agnostic = v.get_long();
00942
00943 else if ( v.is("bpf_file") )
00944 sc->bpf_file = v.get_string();
00945
00946 else if ( v.is("limit") )
00947 sc->pkt_cnt = v.get_long();
00948
00949 else if ( v.is("skip") )
00950 sc->pkt_skip = v.get_long();
00951
00952 else if ( v.is("vlan_agnostic") )
00953 sc->vlan_agnostic = v.get_long();
00954
00955 else
00956 return false;
00957
00958 return true;
00959 }
00960
00961
00962 //-------------------------------------------------------------------------
00963 // attribute_table module
00964 //-------------------------------------------------------------------------
00965
00966 static const Parameter attribute_table_params[] =
00967 {
00968 { "max_hosts", Parameter::PT_INT, "32:207551", "1024",
00969 "maximum number of hosts in attribute table" },
00970
00971 { "max_services_per_host", Parameter::PT_INT, "1:65535", "8",
00972 "maximum number of services per host entry in attribute table" },
00973
00974 { "max_metadata_services", Parameter::PT_INT, "1:256", "8",
00975 "maximum number of services in rule metadata" },
00976
00977 { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
00978 };
00979
00980 const char* attribute_table_help =
00981 "configure hosts loading";
00982
00983 class AttributeTableModule : public Module
00984 {
00985 public:
00986 AttributeTableModule() :
00987 Module("attribute_table", attribute_table_help, attribute_table_params) { }
00988 bool set(const char*, Value&, SnortConfig*) override;
00989
00990 Usage get_usage() const override
00991 { return GLOBAL; }
00992 };
00993
00994 bool AttributeTableModule::set(const char*, Value& v, SnortConfig* sc)
00995 {
00996 if ( v.is("max_hosts") )
00997 sc->max_attribute_hosts = v.get_long();
00998
00999 else if ( v.is("max_services_per_host") )
01000 sc->max_attribute_services_per_host = v.get_long();
01001
01002 else if ( v.is("max_metadata_services") )
01003 sc->max_metadata_services = v.get_long();
01004
01005 else
01006 return false;
01007
01008 return true;
01009 }
01010
01011 //-------------------------------------------------------------------------
01012 // network module
01013 //-------------------------------------------------------------------------
01014
01015 static const Parameter network_params[] =
01016 {
01017 { "checksum_drop", Parameter::PT_MULTI,
01018 "all | ip | noip | tcp | notcp | udp | noudp | icmp | noicmp | none", "none",
01019 "drop if checksum is bad" },
01020
01021 { "checksum_eval", Parameter::PT_MULTI,
01022 "all | ip | noip | tcp | notcp | udp | noudp | icmp | noicmp | none", "none",
01023 "checksums to verify" },
01024
01025 { "decode_drops", Parameter::PT_BOOL, nullptr, "false",
01026 "enable dropping of packets by the decoder" },
01027
01028 { "id", Parameter::PT_INT, "0:65535", "0",
01029 "correlate unified2 events with configuration" },
01030
01031 { "min_ttl", Parameter::PT_INT, "1:255", "1",
01032 "alert / normalize packets with lower ttl / hop limit "
01033 "(you must enable rules and / or normalization also)" },
01034
01035 { "new_ttl", Parameter::PT_INT, "1:255", "1",
01036 "use this value for responses and when normalizing" },
01037
01038 { "layers", Parameter::PT_INT, "3:255", "40",
01039 "the maximum number of protocols that Snort can correctly decode" },
01040
01041 { "max_ip6_extensions", Parameter::PT_INT, "0:255", "0",
01042 "the maximum number of IP6 options Snort will process for a given IPv6 layer "
01043 "before raising 116:456 (0 = unlimited)" },
01044
01045 { "max_ip_layers", Parameter::PT_INT, "0:255", "0",
01046 "the maximum number of IP layers Snort will process for a given packet "
01047 "before raising 116:293 (0 = unlimited)" },
01048
01049 { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
01050 };
01051
01052 #define network_help \
01053 "configure basic network parameters"
01054
01055 class NetworkModule : public Module
01056 {
01057 public:
01058 NetworkModule() : Module("network", network_help, network_params) { }
01059 bool set(const char*, Value&, SnortConfig*) override;
01060
01061 Usage get_usage() const override
01062 { return CONTEXT; }
01063 };
01064
01065 bool NetworkModule::set(const char*, Value& v, SnortConfig* sc)
01066 {
01067 NetworkPolicy* p = get_network_policy();
01068
01069 if ( v.is("checksum_drop") )
01070 ConfigChecksumDrop(v.get_string());
01071
01072 else if ( v.is("checksum_eval") )
01073 ConfigChecksumMode(v.get_string());
01074
01075 else if ( v.is("decode_drops") )
01076 p->decoder_drop = v.get_bool();
01077
01078 else if ( v.is("id") )
01079 p->user_policy_id = v.get_long();
01080
01081 else if ( v.is("min_ttl") )
01082 p->min_ttl = (uint8_t)v.get_long();
01083
01084 else if ( v.is("new_ttl") )
01085 p->new_ttl = (uint8_t)v.get_long();
01086
01087 else if (v.is("layers"))
01088 sc->num_layers = (uint8_t)v.get_long();
01089
01090 else if (v.is("max_ip6_extensions"))
01091 sc->max_ip6_extensions = (uint8_t)v.get_long();
01092
01093 else if (v.is("max_ip_layers"))
01094 sc->max_ip_layers = (uint8_t)v.get_long();
01095
01096 else
01097 return false;
01098
01099 return true;
01100 }
01101
01102 //-------------------------------------------------------------------------
01103 // detection policy module
01104 //-------------------------------------------------------------------------
01105
01106 static const Parameter ips_params[] =
01107 {
01108 { "enable_builtin_rules", Parameter::PT_BOOL, nullptr, "false",
01109 "enable events from builtin rules w/o stubs" },
01110
01111 { "id", Parameter::PT_INT, "0:65535", "0",
01112 "correlate unified2 events with configuration" },
01113
01114 { "include", Parameter::PT_STRING, nullptr, nullptr,
01115 "legacy snort rules and includes" },
01116
01117 // FIXIT-L no default; it breaks initialization by -Q
01118 { "mode", Parameter::PT_ENUM, "tap | inline | inline-test", nullptr,
01119 "set policy mode" },
01120
01121 { "rules", Parameter::PT_STRING, nullptr, nullptr,
01122 "snort rules and includes" },
01123
01124 { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
01125 };
01126
01127 #define ips_help \
01128 "configure IPS rule processing"
01129
01130 THREAD_LOCAL IpsModuleStats ips_module_stats;
01131
01132 const PegInfo ips_module_pegs[] =
01133 {
01134 { CountType::SUM, "invalid_policy_ids", "Number of times an invalid policy ID was provided" },
01135 { CountType::END, nullptr, nullptr }
01136 };
01137
01138 class IpsModule : public Module
01139 {
01140 public:
01141 IpsModule() : Module("ips", ips_help, ips_params) { }
01142 bool set(const char*, Value&, SnortConfig*) override;
01143
01144 const PegInfo* get_pegs() const override
01145 { return ips_module_pegs; }
01146
01147 PegCount* get_counts() const override
01148 { return (PegCount*) &ips_module_stats; }
01149
01150 Usage get_usage() const override
01151 { return DETECT; }
01152 };
01153
01154 bool IpsModule::set(const char*, Value& v, SnortConfig* sc)
01155 {
01156 IpsPolicy* p = get_ips_policy();
01157
01158 if ( v.is("enable_builtin_rules") )
01159 p->enable_builtin_rules = v.get_bool();
01160
01161 else if ( v.is("id") )
01162 {
01163 p->user_policy_id = v.get_long();
01164 sc->policy_map->set_user_ips(p);
01165 }
01166
01167 else if ( v.is("include") )
01168 p->include = v.get_string();
01169
01170 else if ( v.is("mode") )
01171 p->policy_mode = (PolicyMode)v.get_long();
01172
01173 else if ( v.is("rules") )
01174 p->rules = v.get_string();
01175
01176 else
01177 return false;
01178
01179 return true;
01180 }
01181
01182 //-------------------------------------------------------------------------
01183 // process module
01184 //-------------------------------------------------------------------------
01185
01186 static const Parameter thread_pinning_params[] =
01187 {
01188 { "cpuset", Parameter::PT_STRING, nullptr, nullptr,
01189 "pin the associated thread to this cpuset" },
01190
01191 { "thread", Parameter::PT_INT, "0:", "0",
01192 "set cpu affinity for the <cur_thread_num> thread that runs" },
01193
01194 { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
01195 };
01196
01197 static const Parameter process_params[] =
01198 {
01199 { "chroot", Parameter::PT_STRING, nullptr, nullptr,
01200 "set chroot directory (same as -t)" },
01201
01202 { "threads", Parameter::PT_LIST, thread_pinning_params, nullptr,
01203 "thread pinning parameters" },
01204
01205 { "daemon", Parameter::PT_BOOL, nullptr, "false",
01206 "fork as a daemon (same as -D)" },
01207
01208 { "dirty_pig", Parameter::PT_BOOL, nullptr, "false",
01209 "shutdown without internal cleanup" },
01210
01211 { "set_gid", Parameter::PT_STRING, nullptr, nullptr,
01212 "set group ID (same as -g)" },
01213
01214 { "set_uid", Parameter::PT_STRING, nullptr, nullptr,
01215 "set user ID (same as -u)" },
01216
01217 { "umask", Parameter::PT_STRING, nullptr, nullptr,
01218 "set process umask (same as -m)" },
01219
01220 { "utc", Parameter::PT_BOOL, nullptr, "false",
01221 "use UTC instead of local time for timestamps" },
01222
01223 { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
01224 };
01225
01226 #define process_help \
01227 "configure basic process setup"
01228
01229 class ProcessModule : public Module
01230 {
01231 public:
01232 ProcessModule() : Module("process", process_help, process_params) { }
01233 bool set(const char*, Value&, SnortConfig*) override;
01234 bool begin(const char*, int, SnortConfig*) override;
01235 bool end(const char*, int, SnortConfig*) override;
01236
01237 Usage get_usage() const override
01238 { return GLOBAL; }
01239
01240 private:
01241 int thread;
01242 CpuSet* cpuset;
01243 };
01244
01245 bool ProcessModule::set(const char*, Value& v, SnortConfig* sc)
01246 {
01247 if ( v.is("daemon") )
01248 sc->set_daemon(v.get_bool());
01249
01250 else if ( v.is("chroot") )
01251 sc->set_chroot_dir(v.get_string());
01252
01253 else if ( v.is("dirty_pig") )
01254 sc->set_dirty_pig(v.get_bool());
01255
01256 else if ( v.is("set_gid") )
01257 sc->set_gid(v.get_string());
01258
01259 else if ( v.is("set_uid") )
01260 sc->set_uid(v.get_string());
01261
01262 else if ( v.is("umask") )
01263 sc->set_umask(v.get_string());
01264
01265 else if ( v.is("utc") )
01266 sc->set_utc(v.get_bool());
01267
01268 else if (v.is("cpuset"))
01269 {
01270 if (!(cpuset = ThreadConfig::validate_cpuset_string(v.get_string())))
01271 return false;
01272 }
01273 else if (v.is("thread"))
01274 thread = v.get_long();
01275
01276 else
01277 return false;
01278
01279 return true;
01280 }
01281
01282 bool ProcessModule::begin(const char*, int, SnortConfig*)
01283 {
01284 thread = -1;
01285 cpuset = nullptr;
01286 return true;
01287 }
01288
01289 bool ProcessModule::end(const char* fqn, int idx, SnortConfig* sc)
01290 {
01291 if ( !idx )
01292 return true;
01293
01294 if (!strcmp(fqn, "process.threads"))
01295 {
01296 if (thread == -1)
01297 {
01298 ParseError("%s - no thread ID specified", fqn);
01299 if (cpuset)
01300 ThreadConfig::destroy_cpuset(cpuset);
01301 return false;
01302 }
01303 if (!cpuset)
01304 {
01305 ParseError("%s - no cpuset specified for thread %d", fqn, thread);
01306 return false;
01307 }
01308 sc->thread_config->set_thread_affinity(STHREAD_TYPE_PACKET, thread, cpuset);
01309 }
01310
01311 return true;
01312 }
01313
01314 //-------------------------------------------------------------------------
01315 // suppress module
01316 //-------------------------------------------------------------------------
01317
01318 static const Parameter suppress_params[] =
01319 {
01320 { "gid", Parameter::PT_INT, "0:", "0",
01321 "rule generator ID" },
01322
01323 { "sid", Parameter::PT_INT, "0:", "0",
01324 "rule signature ID" },
01325
01326 { "track", Parameter::PT_ENUM, "by_src | by_dst", nullptr,
01327 "suppress only matching source or destination addresses" },
01328
01329 { "ip", Parameter::PT_STRING, nullptr, nullptr,
01330 "restrict suppression to these addresses according to track" },
01331
01332 { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
01333 };
01334
01335 #define suppress_help \
01336 "configure event suppressions"
01337
01338 class SuppressModule : public Module
01339 {
01340 public:
01341 SuppressModule() : Module("suppress", suppress_help, suppress_params, true) { }
01342 bool set(const char*, Value&, SnortConfig*) override;
01343 bool begin(const char*, int, SnortConfig*) override;
01344 bool end(const char*, int, SnortConfig*) override;
01345
01346 Usage get_usage() const override
01347 { return DETECT; }
01348
01349 private:
01350 THDX_STRUCT thdx;
01351 };
01352
01353 bool SuppressModule::set(const char*, Value& v, SnortConfig*)
01354 {
01355 if ( v.is("gid") )
01356 thdx.gen_id = v.get_long();
01357
01358 else if ( v.is("sid") )
01359 thdx.sig_id = v.get_long();
01360
01361 else if ( v.is("track") )
01362 thdx.tracking = v.get_long() + 1;
01363
01364 else if ( v.is("ip") )
01365 thdx.ip_address = sfip_var_from_string(v.get_string());
01366
01367 else
01368 return false;
01369
01370 return true;
01371 }
01372
01373 bool SuppressModule::begin(const char*, int, SnortConfig*)
01374 {
01375 memset(&thdx, 0, sizeof(thdx));
01376 thdx.type = THD_TYPE_SUPPRESS;
01377 thdx.priority = THD_PRIORITY_SUPPRESS;
01378 thdx.tracking = THD_TRK_NONE;
01379 return true;
01380 }
01381
01382 bool SuppressModule::end(const char*, int idx, SnortConfig* sc)
01383 {
01384 if ( idx && sfthreshold_create(sc, sc->threshold_config, &thdx) )
01385 {
01386 ParseError("bad suppress configuration [%d]", idx);
01387 return false;
01388 }
01389 return true;
01390 }
01391
01392 //-------------------------------------------------------------------------
01393 // event_filter module
01394 //-------------------------------------------------------------------------
01395
01396 static const Parameter event_filter_params[] =
01397 {
01398 { "gid", Parameter::PT_INT, "0:", "1",
01399 "rule generator ID" },
01400
01401 { "sid", Parameter::PT_INT, "0:", "1",
01402 "rule signature ID" },
01403
01404 { "type", Parameter::PT_ENUM, "limit | threshold | both", nullptr,
01405 "1st count events | every count events | once after count events" },
01406
01407 { "track", Parameter::PT_ENUM, "by_src | by_dst", nullptr,
01408 "filter only matching source or destination addresses" },
01409
01410 { "count", Parameter::PT_INT, "-1:", "0",
01411 "number of events in interval before tripping; -1 to disable" },
01412
01413 { "seconds", Parameter::PT_INT, "0:", "0",
01414 "count interval" },
01415
01416 { "ip", Parameter::PT_STRING, nullptr, nullptr,
01417 "restrict filter to these addresses according to track" },
01418
01419 { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
01420 };
01421
01422 #define event_filter_help \
01423 "configure thresholding of events"
01424
01425 class EventFilterModule : public Module
01426 {
01427 public:
01428 EventFilterModule() :
01429 Module("event_filter", event_filter_help, event_filter_params, true) { }
01430 bool set(const char*, Value&, SnortConfig*) override;
01431 bool begin(const char*, int, SnortConfig*) override;
01432 bool end(const char*, int, SnortConfig*) override;
01433
01434 Usage get_usage() const override
01435 { return CONTEXT; }
01436
01437 private:
01438 THDX_STRUCT thdx;
01439 };
01440
01441 bool EventFilterModule::set(const char*, Value& v, SnortConfig*)
01442 {
01443 if ( v.is("gid") )
01444 thdx.gen_id = v.get_long();
01445
01446 else if ( v.is("sid") )
01447 thdx.sig_id = v.get_long();
01448
01449 else if ( v.is("track") )
01450 thdx.tracking = v.get_long() + 1;
01451
01452 else if ( v.is("ip") )
01453 thdx.ip_address = sfip_var_from_string(v.get_string());
01454
01455 else if ( v.is("count") )
01456 thdx.count = v.get_long();
01457
01458 else if ( v.is("seconds") )
01459 thdx.seconds = v.get_long();
01460
01461 else if ( v.is("type") )
01462 thdx.type = v.get_long();
01463
01464 else
01465 return false;
01466
01467 return true;
01468 }
01469
01470 bool EventFilterModule::begin(const char*, int, SnortConfig*)
01471 {
01472 memset(&thdx, 0, sizeof(thdx));
01473 thdx.priority = THD_PRIORITY_SUPPRESS;
01474 thdx.tracking = THD_TRK_NONE;
01475 return true;
01476 }
01477
01478 bool EventFilterModule::end(const char*, int idx, SnortConfig* sc)
01479 {
01480 if ( idx && sfthreshold_create(sc, sc->threshold_config, &thdx) )
01481 {
01482 ParseError("bad event_filter configuration [%d]", idx);
01483 return false;
01484 }
01485 return true;
01486 }
01487
01488 //-------------------------------------------------------------------------
01489 // rate_filter module
01490 //-------------------------------------------------------------------------
01491
01492 static const Parameter rate_filter_params[] =
01493 {
01494 { "gid", Parameter::PT_INT, "0:", "1",
01495 "rule generator ID" },
01496
01497 { "sid", Parameter::PT_INT, "0:", "1",
01498 "rule signature ID" },
01499
01500 { "track", Parameter::PT_ENUM, "by_src | by_dst | by_rule", "by_src",
01501 "filter only matching source or destination addresses" },
01502
01503 { "count", Parameter::PT_INT, "0:", "1",
01504 "number of events in interval before tripping" },
01505
01506 { "seconds", Parameter::PT_INT, "0:", "1",
01507 "count interval" },
01508
01509 { "new_action", Parameter::PT_ENUM,
01510 // FIXIT-L new_action options must match RuleType and
01511 // should include pluggable actions as well
01512 "log | pass | alert | drop | block | reset", "alert",
01513 "take this action on future hits until timeout" },
01514
01515 { "timeout", Parameter::PT_INT, "0:", "1",
01516 "count interval" },
01517
01518 { "apply_to", Parameter::PT_STRING, nullptr, nullptr,
01519 "restrict filter to these addresses according to track" },
01520
01521 { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
01522 };
01523
01524 #define rate_filter_help \
01525 "configure rate filters (which change rule actions)"
01526
01527 class RateFilterModule : public Module
01528 {
01529 public:
01530 RateFilterModule() : Module("rate_filter", rate_filter_help, rate_filter_params, true)
01531 { thdx.applyTo = nullptr; }
01532 ~RateFilterModule() override;
01533 bool set(const char*, Value&, SnortConfig*) override;
01534 bool begin(const char*, int, SnortConfig*) override;
01535 bool end(const char*, int, SnortConfig*) override;
01536
01537 Usage get_usage() const override
01538 { return DETECT; }
01539
01540 private:
01541 tSFRFConfigNode thdx;
01542 };
01543
01544 RateFilterModule::~RateFilterModule()
01545 {
01546 if ( thdx.applyTo )
01547 sfvar_free(thdx.applyTo);
01548 }
01549
01550 bool RateFilterModule::set(const char*, Value& v, SnortConfig*)
01551 {
01552 if ( v.is("gid") )
01553 thdx.gid = v.get_long();
01554
01555 else if ( v.is("sid") )
01556 thdx.sid = v.get_long();
01557
01558 else if ( v.is("track") )
01559 thdx.tracking = (SFRF_TRACK)(v.get_long() + 1);
01560
01561 else if ( v.is("count") )
01562 thdx.count = v.get_long();
01563
01564 else if ( v.is("seconds") )
01565 thdx.seconds = v.get_long();
01566
01567 else if ( v.is("timeout") )
01568 thdx.timeout = v.get_long();
01569
01570 else if ( v.is("apply_to") )
01571 thdx.applyTo = sfip_var_from_string(v.get_string());
01572
01573 else if ( v.is("new_action") )
01574 thdx.newAction = (RuleType)(v.get_long() + 1);
01575
01576 else
01577 return false;
01578
01579 return true;
01580 }
01581
01582 bool RateFilterModule::begin(const char*, int, SnortConfig*)
01583 {
01584 memset(&thdx, 0, sizeof(thdx));
01585 return true;
01586 }
01587
01588 bool RateFilterModule::end(const char*, int idx, SnortConfig* sc)
01589 {
01590 if ( idx && RateFilter_Create(sc, sc->rate_filter_config, &thdx) )
01591 ParseError("bad rate_filter configuration [%d]", idx);
01592
01593 thdx.applyTo = nullptr;
01594 return true;
01595 }
01596
01597 //-------------------------------------------------------------------------
01598 // rule_state module
01599 //-------------------------------------------------------------------------
01600
01601 static const Parameter rule_state_params[] =
01602 {
01603 { "gid", Parameter::PT_INT, "0:", "0",
01604 "rule generator ID" },
01605
01606 { "sid", Parameter::PT_INT, "0:", "0",
01607 "rule signature ID" },
01608
01609 { "enable", Parameter::PT_BOOL, nullptr, "true",
01610 "enable or disable rule in all policies" },
01611
01612 { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
01613 };
01614
01615 #define rule_state_help \
01616 "enable/disable specific IPS rules"
01617
01618 class RuleStateModule : public Module
01619 {
01620 public:
01621 RuleStateModule() : Module("rule_state", rule_state_help, rule_state_params) { }
01622 bool set(const char*, Value&, SnortConfig*) override;
01623 bool begin(const char*, int, SnortConfig*) override;
01624 bool end(const char*, int, SnortConfig*) override;
01625
01626 Usage get_usage() const override
01627 { return DETECT; }
01628
01629 private:
01630 RuleState state;
01631 };
01632
01633 bool RuleStateModule::set(const char*, Value& v, SnortConfig*)
01634 {
01635 if ( v.is("gid") )
01636 state.gid = v.get_long();
01637
01638 else if ( v.is("sid") )
01639 state.sid = v.get_long();
01640
01641 else if ( v.is("enable") )
01642 state.state = v.get_bool();
01643
01644 else
01645 return false;
01646
01647 return true;
01648 }
01649
01650 bool RuleStateModule::begin(const char*, int, SnortConfig*)
01651 {
01652 memset(&state, 0, sizeof(state));
01653 return true;
01654 }
01655
01656 bool RuleStateModule::end(const char*, int idx, SnortConfig* sc)
01657 {
01658 if ( idx )
01659 AddRuleState(sc, state);
01660 return true;
01661 }
01662
01663 //-------------------------------------------------------------------------
01664 // hosts module
01665 //-------------------------------------------------------------------------
01666
01667 static const Parameter service_params[] =
01668 {
01669 { "name", Parameter::PT_STRING, nullptr, nullptr,
01670 "service identifier" },
01671
01672 { "proto", Parameter::PT_ENUM, "tcp | udp", "tcp",
01673 "ip protocol" },
01674
01675 { "port", Parameter::PT_PORT, nullptr, nullptr,
01676 "port number" },
01677
01678 { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
01679 };
01680
01681 static const Parameter hosts_params[] =
01682 {
01683 { "ip", Parameter::PT_ADDR, nullptr, "0.0.0.0/32",
01684 "hosts address / cidr" },
01685
01686 { "frag_policy", Parameter::PT_ENUM, IP_POLICIES, nullptr,
01687 "defragmentation policy" },
01688
01689 { "tcp_policy", Parameter::PT_ENUM, TCP_POLICIES, nullptr,
01690 "tcp reassembly policy" },
01691
01692 { "services", Parameter::PT_LIST, service_params, nullptr,
01693 "list of service parameters" },
01694
01695 { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
01696 };
01697
01698 #define hosts_help \
01699 "configure hosts"
01700
01701 class HostsModule : public Module
01702 {
01703 public:
01704 HostsModule() : Module("hosts", hosts_help, hosts_params, true)
01705 { app = nullptr; host = nullptr; }
01706 ~HostsModule() override { assert(!host && !app); }
01707
01708 bool set(const char*, Value&, SnortConfig*) override;
01709 bool begin(const char*, int, SnortConfig*) override;
01710 bool end(const char*, int, SnortConfig*) override;
01711
01712 Usage get_usage() const override
01713 { return GLOBAL; }
01714
01715 private:
01716 ApplicationEntry* app;
01717 HostAttributeEntry* host;
01718 };
01719
01720 bool HostsModule::set(const char*, Value& v, SnortConfig* sc)
01721 {
01722 if ( host and v.is("ip") )
01723 v.get_addr(host->ipAddr);
01724
01725 else if ( host and v.is("frag_policy") )
01726 host->hostInfo.fragPolicy = v.get_long() + 1;
01727
01728 else if ( host and v.is("tcp_policy") )
01729 host->hostInfo.streamPolicy = v.get_long() + 1;
01730
01731 else if ( app and v.is("name") )
01732 app->protocol = sc->proto_ref->add(v.get_string());
01733
01734 else if ( app and v.is("proto") )
01735 app->ipproto = sc->proto_ref->add(v.get_string());
01736
01737 else if ( app and v.is("port") )
01738 app->port = v.get_long();
01739
01740 else
01741 return false;
01742
01743 return true;
01744 }
01745
01746 bool HostsModule::begin(const char* fqn, int idx, SnortConfig*)
01747 {
01748 if ( idx && !strcmp(fqn, "hosts.services") )
01749 app = SFAT_CreateApplicationEntry();
01750
01751 else if ( idx && !strcmp(fqn, "hosts") )
01752 host = SFAT_CreateHostEntry();
01753
01754 return true;
01755 }
01756
01757 bool HostsModule::end(const char* fqn, int idx, SnortConfig*)
01758 {
01759 if ( idx && !strcmp(fqn, "hosts.services") )
01760 {
01761 SFAT_AddService(host, app);
01762 app = nullptr;
01763 }
01764 else if ( idx && !strcmp(fqn, "hosts") )
01765 {
01766 SFAT_AddHost(host);
01767 host = nullptr;
01768 }
01769
01770 return true;
01771 }
01772
01773 //-------------------------------------------------------------------------
01774 // module manager stuff - move to framework/module_manager.cc
01775 //-------------------------------------------------------------------------
01776
01777 void module_init()
01778 {
01779 // parameters must be settable regardless of sequence
01780 // since Lua calls this by table hash key traversal
01781 // (which is effectively random)
01782 // so module interdependencies must come after this phase
01783 ModuleManager::add_module(get_snort_module());
01784
01785 // these modules are not policy specific
01786 ModuleManager::add_module(new ClassificationsModule);
01787 ModuleManager::add_module(new CodecModule);
01788 ModuleManager::add_module(new DetectionModule);
01789 ModuleManager::add_module(new MemoryModule);
01790 ModuleManager::add_module(new PacketsModule);
01791 ModuleManager::add_module(new ProcessModule);
01792 ModuleManager::add_module(new ProfilerModule);
01793 ModuleManager::add_module(new ReferencesModule);
01794 ModuleManager::add_module(new RuleStateModule);
01795 ModuleManager::add_module(new SearchEngineModule);
01796 ModuleManager::add_module(new SFDAQModule);
01797
01798 // these could but prolly shouldn't be policy specific
01799 // or should be broken into policy and non-policy parts
01800 ModuleManager::add_module(new AlertsModule);
01801 ModuleManager::add_module(new EventQueueModule);
01802 ModuleManager::add_module(new OutputModule);
01803
01804 // these modules could be in traffic policy
01805 ModuleManager::add_module(new ActiveModule);
01806
01807 ModuleManager::add_module(new LatencyModule);
01808
01809 ModuleManager::add_module(new SideChannelModule);
01810 ModuleManager::add_module(new HighAvailabilityModule);
01811
01812 // these modules should be in ips policy
01813 ModuleManager::add_module(new EventFilterModule);
01814 ModuleManager::add_module(new RateFilterModule);
01815 ModuleManager::add_module(new SuppressModule);
01816
01817 // these are preliminary policies
01818 ModuleManager::add_module(new NetworkModule);
01819 ModuleManager::add_module(new IpsModule);
01820
01821 // these modules replace config and hosts.xml
01822 ModuleManager::add_module(new AttributeTableModule);
01823 ModuleManager::add_module(new HostsModule);
01824 ModuleManager::add_module(new HostTrackerModule);
01825 ModuleManager::add_module(new HostCacheModule);
01826 }
01827
END OF CODE