1 //--------------------------------------------------------------------------
2 // Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
3 //
4 // This program is free software; you can redistribute it and/or modify it
5 // under the terms of the GNU General Public License Version 2 as published
6 // by the Free Software Foundation. You may not use, modify or distribute
7 // this program under any other version of the GNU General Public License.
8 //
9 // This program is distributed in the hope that it will be useful, but
10 // WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License along
15 // with this program; if not, write to the Free Software Foundation, Inc.,
16 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 //--------------------------------------------------------------------------
18
19 // snort_module.cc author Russ Combs <rucombs@cisco.com>
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include "snort_module.h"
26
27 #include <string>
28
29 #include "detection/detect.h"
30 #include "detection/fp_detect.h"
31 #include "framework/module.h"
32 #include "framework/parameter.h"
33 #include "log/messages.h"
34 #include "main.h"
35 #include "main/snort_debug.h"
36 #include "managers/codec_manager.h"
37 #include "packet_io/sfdaq_config.h"
38 #include "packet_io/trough.h"
39 #include "parser/config_file.h"
40 #include "parser/parser.h"
41 #include "parser/parse_utils.h"
42 #include "parser/vars.h"
43 #include "trace/trace_config.h"
44
45 #if defined(UNIT_TEST) || defined(BENCHMARK_TEST)
46 #include "catch/unit_test.h"
47 #endif
48
49 #include "analyzer.h"
50 #include "help.h"
51 #include "shell.h"
52 #include "snort_config.h"
53 #include "thread_config.h"
54
55 using namespace snort;
56 using namespace std;
57
58 //-------------------------------------------------------------------------
59 // commands
60 //-------------------------------------------------------------------------
61
62 #ifdef SHELL
63 static const Parameter s_reload[] =
64 {
65 { "filename", Parameter::PT_STRING, nullptr, nullptr,
66 "name of file to load" },
67
68 { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
69 };
70
71 static const Parameter s_reload_w_path[] =
72 {
73 { "filename", Parameter::PT_STRING, "(optional)", nullptr,
74 "[<plugin path>] name of file to load" },
75
76 { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
77 };
78
79 static const Parameter s_delete[] =
80 {
81 { "inspector", Parameter::PT_STRING, nullptr, nullptr,
82 "name of inspector to delete" },
83
84 { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
85 };
86
87 static const Parameter s_module[] =
88 {
89 { "module", Parameter::PT_STRING, nullptr, nullptr,
90 "name of the module to reload" },
91
92 { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
93 };
94
95 static const Parameter s_pktnum[] =
96 {
97 { "pkt_num", Parameter::PT_INT, "1:max53", nullptr,
98 "resume and pause after pkt_num packets" },
99
100 { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
101 };
102
103 static const Command snort_cmds[] =
104 {
105 { "show_plugins", main_dump_plugins, nullptr, "show available plugins" },
106
107 { "delete_inspector", main_delete_inspector, s_delete,
108 "delete an inspector from the default policy" },
109
110 { "dump_stats", main_dump_stats, nullptr, "show summary statistics" },
111 { "reset_stats", main_reset_stats, nullptr, "clear summary statistics" },
112 { "rotate_stats", main_rotate_stats, nullptr, "roll perfmonitor log files" },
113 { "reload_config", main_reload_config, s_reload_w_path, "load new configuration" },
114 { "reload_policy", main_reload_policy, s_reload, "reload part or all of the default policy" },
115 { "reload_module", main_reload_module, s_module, "reload module" },
116 { "reload_daq", main_reload_daq, nullptr, "reload daq module" },
117 { "reload_hosts", main_reload_hosts, s_reload, "load a new hosts table" },
118
119 // FIXIT-M rewrite trough to permit updates on the fly
120 //{ "process", main_process, nullptr, "process given pcap" },
121
122 { "pause", main_pause, nullptr, "suspend packet processing" },
123
124 { "resume", main_resume, s_pktnum, "continue packet processing. "
125 "If number of packets is specified, will resume for n packets and pause" },
126
127 { "detach", main_detach, nullptr, "detach from control shell (without shutting down)" },
128 { "quit", main_quit, nullptr, "shutdown and dump-stats" },
129 { "help", main_help, nullptr, "this output" },
130
131 { nullptr, nullptr, nullptr, nullptr }
132 };
133 #endif
134
135 //-------------------------------------------------------------------------
136 // hex conversion helper funcs
137 //-------------------------------------------------------------------------
138
c2x(const char * s)139 [[noreturn]] static void c2x(const char* s)
140 {
141 printf("'%c' = 0x%2.2X (%d)\n", s[0], s[0], s[0]);
142 exit(0);
143 }
144
x2c(uint8_t x)145 [[noreturn]] static void x2c(uint8_t x)
146 {
147 printf("0x%2.2X (%u) = '%c'\n", x, x, static_cast<char>(x));
148 exit(0);
149 }
150
x2s(const char * s)151 [[noreturn]] static void x2s(const char* s)
152 {
153 bool inv;
154 string out, in = "\"";
155 in += s;
156 in += "\"";
157
158 if ( parse_byte_code(in.c_str(), inv, out) )
159 printf("%s = '%s'\n", s, out.c_str());
160
161 else
162 printf("%s = '%s'\n", s, "error");
163
164 exit(0);
165 }
166
167 //-------------------------------------------------------------------------
168 // parameters
169 //
170 // users aren't used to seeing the standard help format for command line
171 // args so the few cases where there is a default, we include it in the
172 // help as well.
173 //
174 // command line options can be specified in Lua instead by doing e.g.
175 //
176 // snort = { }; snort["-z"] = 2
177 //
178 // so a default value can't be provided for args that kick off optional
179 // run modes such as --rule-to-text because the program will do strange
180 // things like waiting on stdin for input that won't be coming. in these
181 // cases the default must only be indicated in the help.
182 //-------------------------------------------------------------------------
183
184 static const TraceOption snort_trace_options[] =
185 {
186 { "inspector_manager", TRACE_INSPECTOR_MANAGER, "enable inspector manager trace logging" },
187 #ifdef DEBUG_MSGS
188 { "main", TRACE_MAIN, "enable main trace logging" },
189 #endif
190
191 { nullptr, 0, nullptr }
192 };
193
194 static const Parameter s_params[] =
195 {
196 { "-?", Parameter::PT_STRING, "(optional)", nullptr,
197 "<option prefix> output matching command line option quick help (same as --help-options)" },
198
199 // FIXIT-M should use PluginManager::get_available_plugins(PT_LOGGER)
200 // but plugins not yet loaded upon set
201 { "-A", Parameter::PT_STRING, nullptr, nullptr,
202 "<mode> set alert mode: none, cmg, or alert_*" },
203
204 { "-B", Parameter::PT_ADDR, nullptr, "255.255.255.255/32",
205 "<mask> obfuscated IP addresses in alerts and packet dumps using CIDR mask" },
206
207 { "-C", Parameter::PT_IMPLIED, nullptr, nullptr,
208 "print out payloads with character data only (no hex)" },
209
210 { "-c", Parameter::PT_STRING, nullptr, nullptr,
211 "<conf> use this configuration" },
212
213 { "-D", Parameter::PT_IMPLIED, nullptr, nullptr,
214 "run Snort in background (daemon) mode" },
215
216 { "-d", Parameter::PT_IMPLIED, nullptr, nullptr,
217 "dump the Application Layer" },
218
219 { "-e", Parameter::PT_IMPLIED, nullptr, nullptr,
220 "display the second layer header info" },
221
222 { "-f", Parameter::PT_IMPLIED, nullptr, nullptr,
223 "turn off fflush() calls after binary log writes" },
224
225 { "-G", Parameter::PT_INT, "0:65535", nullptr,
226 "<0xid> (same as --logid)" },
227
228 { "-g", Parameter::PT_STRING, nullptr, nullptr,
229 "<gname> run snort gid as <gname> group (or gid) after initialization" },
230
231 { "-H", Parameter::PT_IMPLIED, nullptr, nullptr,
232 "make hash tables deterministic" },
233
234 { "-h", Parameter::PT_IMPLIED, nullptr, nullptr,
235 "show help overview (same as --help)" },
236
237 { "-i", Parameter::PT_STRING, nullptr, nullptr,
238 "<iface>... list of interfaces" },
239
240 #ifdef SHELL
241 { "-j", Parameter::PT_PORT, nullptr, nullptr,
242 "<port> to listen for Telnet connections" },
243 #endif
244
245 { "-k", Parameter::PT_ENUM, "all|noip|notcp|noudp|noicmp|none", "all",
246 "<mode> checksum mode; default is all" },
247
248 { "-L", Parameter::PT_STRING, nullptr, nullptr,
249 "<mode> logging mode (none, dump, pcap, or log_*)" },
250
251 { "-l", Parameter::PT_STRING, nullptr, nullptr,
252 "<logdir> log to this directory instead of current directory" },
253
254 { "-M", Parameter::PT_IMPLIED, nullptr, nullptr,
255 "log messages to syslog (not alerts)" },
256
257 { "-m", Parameter::PT_INT, "0x000:0x1FF", nullptr,
258 "<umask> set the process file mode creation mask" },
259
260 { "-n", Parameter::PT_INT, "0:max53", nullptr,
261 "<count> stop after count packets" },
262
263 { "-O", Parameter::PT_IMPLIED, nullptr, nullptr,
264 "obfuscate the logged IP addresses" },
265
266 { "-Q", Parameter::PT_IMPLIED, nullptr, nullptr,
267 "enable inline mode operation" },
268
269 { "-q", Parameter::PT_IMPLIED, nullptr, nullptr,
270 "quiet mode - suppress normal logging on stdout" },
271
272 { "-R", Parameter::PT_STRING, nullptr, nullptr,
273 "<rules> include this rules file in the default policy" },
274
275 { "-r", Parameter::PT_STRING, nullptr, nullptr,
276 "<pcap>... (same as --pcap-list)" },
277
278 { "-s", Parameter::PT_INT, "68:65535", "1518",
279 "<snap> (same as --snaplen); default is 1518" },
280
281 { "-T", Parameter::PT_IMPLIED, nullptr, nullptr,
282 "test and report on the current Snort configuration" },
283
284 { "-t", Parameter::PT_STRING, nullptr, nullptr,
285 "<dir> chroots process to <dir> after initialization" },
286
287 { "-U", Parameter::PT_IMPLIED, nullptr, nullptr,
288 "use UTC for timestamps" },
289
290 { "-u", Parameter::PT_STRING, nullptr, nullptr,
291 "<uname> run snort as <uname> or <uid> after initialization" },
292
293 { "-V", Parameter::PT_IMPLIED, nullptr, nullptr,
294 "(same as --version)" },
295
296 { "-v", Parameter::PT_IMPLIED, nullptr, nullptr,
297 "be verbose" },
298
299 { "-X", Parameter::PT_IMPLIED, nullptr, nullptr,
300 "dump the raw packet data starting at the link layer" },
301
302 { "-x", Parameter::PT_IMPLIED, nullptr, nullptr,
303 "same as --pedantic" },
304
305 { "-y", Parameter::PT_IMPLIED, nullptr, nullptr,
306 "include year in timestamp in the alert and log files" },
307
308 // do not provide parameter default as it will cause the value to change
309 // after allocations in SnortConfig if snort = { } is set in Lua
310 { "-z", Parameter::PT_INT, "0:max32", nullptr,
311 "<count> maximum number of packet threads (same as --max-packet-threads); "
312 "0 gets the number of CPU cores reported by the system; default is 1" },
313
314 { "--alert-before-pass", Parameter::PT_IMPLIED, nullptr, nullptr,
315 "evaluate alert rules before pass rules; default is pass rules first" },
316
317 { "--bpf", Parameter::PT_STRING, nullptr, nullptr,
318 "<filter options> are standard BPF options, as seen in TCPDump" },
319
320 { "--c2x", Parameter::PT_STRING, nullptr, nullptr,
321 "output hex for given char (see also --x2c)" },
322
323 #ifdef SHELL
324 { "--control-socket", Parameter::PT_STRING, nullptr, nullptr,
325 "<file> to create unix socket" },
326 #endif
327
328 { "--create-pidfile", Parameter::PT_IMPLIED, nullptr, nullptr,
329 "create PID file, even when not in Daemon mode" },
330
331 { "--daq", Parameter::PT_STRING, nullptr, nullptr,
332 "<type> select packet acquisition module (default is pcap)" },
333
334 { "--daq-batch-size", Parameter::PT_INT, "1:", "64",
335 "<size> set the DAQ receive batch size", },
336
337 { "--daq-dir", Parameter::PT_STRING, nullptr, nullptr,
338 "<dir> tell snort where to find desired DAQ" },
339
340 { "--daq-list", Parameter::PT_IMPLIED, nullptr, nullptr,
341 "list packet acquisition modules available in optional dir, default is static modules only" },
342
343 { "--daq-mode", Parameter::PT_ENUM, "passive | inline | read-file", nullptr,
344 "<mode> select DAQ module operating mode (overrides automatic selection)" },
345
346 { "--daq-var", Parameter::PT_STRING, nullptr, nullptr,
347 "<name=value> specify extra DAQ configuration variable" },
348
349 { "--dirty-pig", Parameter::PT_IMPLIED, nullptr, nullptr,
350 "don't flush packets on shutdown" },
351
352 { "--dump-builtin-options", Parameter::PT_STRING, nullptr, nullptr,
353 "additional options to include with --dump-builtin-rules stubs" },
354
355 { "--dump-builtin-rules", Parameter::PT_STRING, "(optional)", nullptr,
356 "[<module prefix>] output stub rules for selected modules" },
357
358 { "--dump-config", Parameter::PT_SELECT, "all | top", nullptr,
359 "dump config in json format" },
360
361 { "--dump-config-text", Parameter::PT_IMPLIED, nullptr, nullptr,
362 "dump config in text format" },
363
364 // FIXIT-L add --list-dynamic-rules like --list-builtin-rules
365 { "--dump-dynamic-rules", Parameter::PT_IMPLIED, nullptr, nullptr,
366 "output stub rules for all loaded rules libraries" },
367
368 { "--dump-defaults", Parameter::PT_STRING, "(optional)", nullptr,
369 "[<module prefix>] output module defaults in Lua format" },
370
371 { "--dump-rule-databases", Parameter::PT_STRING, nullptr, nullptr,
372 "dump rule databases to given directory (hyperscan only)" },
373
374 { "--dump-rule-deps", Parameter::PT_IMPLIED, nullptr, nullptr,
375 "dump rule dependencies in json format for use by other tools" },
376
377 { "--dump-rule-meta", Parameter::PT_IMPLIED, nullptr, nullptr,
378 "dump configured rule info in json format for use by other tools" },
379
380 { "--dump-rule-state", Parameter::PT_IMPLIED, nullptr, nullptr,
381 "dump configured rule state in json format for use by other tools" },
382
383 { "--dump-version", Parameter::PT_IMPLIED, nullptr, nullptr,
384 "output the version, the whole version, and only the version" },
385
386 { "--enable-inline-test", Parameter::PT_IMPLIED, nullptr, nullptr,
387 "enable Inline-Test Mode Operation" },
388
389 { "--enable-test-features", Parameter::PT_IMPLIED, nullptr, nullptr,
390 "enable features used in testing" },
391
392 { "--gen-msg-map", Parameter::PT_IMPLIED, nullptr, nullptr,
393 "dump configured rules in gen-msg.map format for use by other tools" },
394
395 { "--help", Parameter::PT_IMPLIED, nullptr, nullptr,
396 "show help overview" },
397
398 { "--help-commands", Parameter::PT_STRING, "(optional)", nullptr,
399 "[<module prefix>] output matching commands" },
400
401 { "--help-config", Parameter::PT_STRING, "(optional)", nullptr,
402 "[<module prefix>] output matching config options" },
403
404 { "--help-counts", Parameter::PT_STRING, "(optional)", nullptr,
405 "[<module prefix>] output matching peg counts" },
406
407 { "--help-limits", Parameter::PT_IMPLIED, nullptr, nullptr,
408 "print the int upper bounds denoted by max*" },
409
410 { "--help-module", Parameter::PT_STRING, nullptr, nullptr,
411 "<module> output description of given module" },
412
413 { "--help-modules", Parameter::PT_IMPLIED, nullptr, nullptr,
414 "list all available modules with brief help" },
415
416 { "--help-modules-json", Parameter::PT_IMPLIED, nullptr, nullptr,
417 "dump description of all available modules in JSON format" },
418
419 { "--help-options", Parameter::PT_STRING, "(optional)", nullptr,
420 "[<option prefix>] output matching command line option quick help (same as -?)" },
421
422 { "--help-plugins", Parameter::PT_IMPLIED, nullptr, nullptr,
423 "list all available plugins with brief help" },
424
425 { "--help-signals", Parameter::PT_IMPLIED, nullptr, nullptr,
426 "dump available control signals" },
427
428 { "--id-offset", Parameter::PT_INT, "0:65535", "0",
429 "offset to add to instance IDs when logging to files" },
430
431 { "--id-subdir", Parameter::PT_IMPLIED, nullptr, nullptr,
432 "create/use instance subdirectories in logdir instead of instance filename prefix" },
433
434 { "--id-zero", Parameter::PT_IMPLIED, nullptr, nullptr,
435 "use id prefix / subdirectory even with one packet thread" },
436
437 { "--include-path", Parameter::PT_STRING, nullptr, nullptr,
438 "<path> where to find Lua and rule included files; "
439 "searched before current or config directories" },
440
441 { "--list-buffers", Parameter::PT_IMPLIED, nullptr, nullptr,
442 "output available inspection buffers" },
443
444 { "--list-builtin", Parameter::PT_STRING, "(optional)", nullptr,
445 "[<module prefix>] output matching builtin rules" },
446
447 { "--list-gids", Parameter::PT_STRING, "(optional)", nullptr,
448 "[<module prefix>] output matching generators" },
449
450 { "--list-modules", Parameter::PT_STRING, "(optional)", nullptr,
451 "[<module type>] list all known modules of given type" },
452
453 { "--list-plugins", Parameter::PT_IMPLIED, nullptr, nullptr,
454 "list all known plugins" },
455
456 { "--lua", Parameter::PT_STRING, nullptr, nullptr,
457 "<chunk> extend/override conf with chunk; may be repeated" },
458
459 { "--lua-sandbox", Parameter::PT_STRING, nullptr, nullptr,
460 "<file> file that contains the lua sandbox environment in which config will be loaded" },
461
462 { "--logid", Parameter::PT_INT, "0:65535", nullptr,
463 "<0xid> log Identifier to uniquely id events for multiple snorts (same as -G)" },
464
465 { "--markup", Parameter::PT_IMPLIED, nullptr, nullptr,
466 "output help in asciidoc compatible format" },
467
468 { "--max-packet-threads", Parameter::PT_INT, "0:max32", nullptr,
469 "<count> configure maximum number of packet threads (same as -z)" },
470
471 { "--mem-check", Parameter::PT_IMPLIED, nullptr, nullptr,
472 "like -T but also compile search engines" },
473
474 { "--metadata-filter", Parameter::PT_STRING, nullptr, nullptr,
475 "<filter> load only rules containing filter string in metadata if set" },
476
477 { "--nostamps", Parameter::PT_IMPLIED, nullptr, nullptr,
478 "don't include timestamps in log file names" },
479
480 { "--nolock-pidfile", Parameter::PT_IMPLIED, nullptr, nullptr,
481 "do not try to lock Snort PID file" },
482
483 { "--no-warn-flowbits", Parameter::PT_IMPLIED, nullptr, nullptr,
484 "ignore warnings about flowbits that are checked but not set and vice-versa" },
485
486 { "--no-warn-rules", Parameter::PT_IMPLIED, nullptr, nullptr,
487 "ignore warnings about duplicate rules and rule parsing issues" },
488
489 { "--pause", Parameter::PT_IMPLIED, nullptr, nullptr,
490 "wait for resume/quit command before processing packets/terminating", },
491
492 #ifdef REG_TEST
493 { "--pause-after-n", Parameter::PT_INT, "1:max53", nullptr,
494 "<count> pause after count packets", },
495 #endif
496
497 { "--pcap-file", Parameter::PT_STRING, nullptr, nullptr,
498 "<file> file that contains a list of pcaps to read - read mode is implied" },
499
500 { "--pcap-list", Parameter::PT_STRING, nullptr, nullptr,
501 "<list> a space separated list of pcaps to read - read mode is implied" },
502
503 { "--pcap-dir", Parameter::PT_STRING, nullptr, nullptr,
504 "<dir> a directory to recurse to look for pcaps - read mode is implied" },
505
506 { "--pcap-filter", Parameter::PT_STRING, nullptr, "*.*cap*",
507 "<filter> filter to apply when getting pcaps from file or directory" },
508
509 { "--pcap-loop", Parameter::PT_INT, "0:max32", nullptr,
510 "<count> read all pcaps <count> times; 0 will read until Snort is terminated" },
511
512 { "--pcap-no-filter", Parameter::PT_IMPLIED, nullptr, nullptr,
513 "reset to use no filter when getting pcaps from file or directory" },
514
515 { "--pcap-show", Parameter::PT_IMPLIED, nullptr, nullptr,
516 "print a line saying what pcap is currently being read" },
517
518 { "--pedantic", Parameter::PT_IMPLIED, nullptr, nullptr,
519 "warnings are fatal" },
520
521 #ifdef PIGLET
522 { "--piglet", Parameter::PT_IMPLIED, nullptr, nullptr,
523 "enable piglet test harness mode" },
524 #endif
525
526 { "--plugin-path", Parameter::PT_STRING, nullptr, nullptr,
527 "<path> a colon separated list of directories or plugin libraries" },
528
529 { "--process-all-events", Parameter::PT_IMPLIED, nullptr, nullptr,
530 "process all action groups" },
531
532 { "--rule", Parameter::PT_STRING, nullptr, nullptr,
533 "<rules> to be added to configuration; may be repeated" },
534
535 { "--rule-path", Parameter::PT_STRING, nullptr, nullptr,
536 "<path> where to find rules files" },
537
538 { "--rule-to-hex", Parameter::PT_IMPLIED, nullptr, nullptr,
539 "output so rule header to stdout for text rule on stdin" },
540
541 { "--rule-to-text", Parameter::PT_STRING, "16", nullptr,
542 "output plain so rule header to stdout for text rule on stdin "
543 "(specify delimiter or [Snort_SO_Rule] will be used)" },
544
545 { "--run-prefix", Parameter::PT_STRING, nullptr, nullptr,
546 "<pfx> prepend this to each output file" },
547
548 { "--script-path", Parameter::PT_STRING, nullptr, nullptr,
549 "<path> to a luajit script or directory containing luajit scripts" },
550
551 #ifdef SHELL
552 { "--shell", Parameter::PT_IMPLIED, nullptr, nullptr,
553 "enable the interactive command line", },
554 #endif
555
556 { "--show-file-codes", Parameter::PT_IMPLIED, nullptr, nullptr,
557 "indicate how files are located: A=absolute and W, F, C which are relative "
558 "to the working directory, including file, and config file respectively" },
559
560 { "--show-plugins", Parameter::PT_IMPLIED, nullptr, nullptr,
561 "list module and plugin versions", },
562
563 { "--skip", Parameter::PT_INT, "0:max53", nullptr,
564 "<n> skip 1st n packets", },
565
566 { "--snaplen", Parameter::PT_INT, "68:65535", "1518",
567 "<snap> set snaplen of packet (same as -s)", },
568
569 { "--stdin-rules", Parameter::PT_IMPLIED, nullptr, nullptr,
570 "read rules from stdin until EOF or a line starting with END is read", },
571
572 { "--talos", Parameter::PT_IMPLIED, nullptr, nullptr,
573 "enable Talos tweak (same as --tweaks talos)", },
574
575 { "--tweaks", Parameter::PT_STRING, nullptr, nullptr,
576 "tune configuration" },
577
578 #if defined(UNIT_TEST) || defined(BENCHMARK_TEST)
579 { "--catch-test", Parameter::PT_STRING, nullptr, nullptr,
580 "comma separated list of Catch test tags or 'all'" },
581 #endif
582 { "--version", Parameter::PT_IMPLIED, nullptr, nullptr,
583 "show version number (same as -V)" },
584
585 { "--warn-all", Parameter::PT_IMPLIED, nullptr, nullptr,
586 "enable all warnings" },
587
588 { "--warn-conf", Parameter::PT_IMPLIED, nullptr, nullptr,
589 "warn about configuration issues" },
590
591 { "--warn-conf-strict", Parameter::PT_IMPLIED, nullptr, nullptr,
592 "warn about unrecognized elements in configuration files" },
593
594 { "--warn-daq", Parameter::PT_IMPLIED, nullptr, nullptr,
595 "warn about DAQ issues, usually related to mode" },
596
597 { "--warn-flowbits", Parameter::PT_IMPLIED, nullptr, nullptr,
598 "warn about flowbits that are checked but not set and vice-versa" },
599
600 { "--warn-hosts", Parameter::PT_IMPLIED, nullptr, nullptr,
601 "warn about host table issues" },
602
603 { "--warn-plugins", Parameter::PT_IMPLIED, nullptr, nullptr,
604 "warn about issues that prevent plugins from loading" },
605
606 { "--warn-rules", Parameter::PT_IMPLIED, nullptr, nullptr,
607 "warn about duplicate rules and rule parsing issues" },
608
609 { "--warn-scripts", Parameter::PT_IMPLIED, nullptr, nullptr,
610 "warn about issues discovered while processing Lua scripts" },
611
612 { "--warn-symbols", Parameter::PT_IMPLIED, nullptr, nullptr,
613 "warn about unknown symbols in your Lua config" },
614
615 { "--warn-vars", Parameter::PT_IMPLIED, nullptr, nullptr,
616 "warn about variable definition and usage issues" },
617
618 { "--x2c", Parameter::PT_INT, "0x00:0xFF", nullptr,
619 "output ASCII char for given hex (see also --c2x)" },
620
621 { "--x2s", Parameter::PT_STRING, nullptr, nullptr,
622 "output ASCII string for given byte code (see also --x2c)" },
623
624 { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
625 };
626
627 //-------------------------------------------------------------------------
628 // module
629 //-------------------------------------------------------------------------
630
631 #define s_name "snort"
632
633 #ifdef SHELL
634 #define s_help \
635 "command line configuration and shell commands"
636 #else
637 #define s_help \
638 "command line configuration"
639 #endif
640
641 THREAD_LOCAL const Trace* snort_trace = nullptr;
642
643 class SnortModule : public Module
644 {
645 public:
SnortModule()646 SnortModule() : Module(s_name, s_help, s_params)
647 { }
648
649 #ifdef SHELL
get_commands() const650 const Command* get_commands() const override
651 { return snort_cmds; }
652 #endif
653
654 bool begin(const char*, int, SnortConfig*) override;
655 bool set(const char*, Value&, SnortConfig*) override;
656 bool end(const char*, int, SnortConfig*) override;
657
get_pegs() const658 const PegInfo* get_pegs() const override
659 { return proc_names; }
660
get_counts() const661 PegCount* get_counts() const override
662 { return (PegCount*)&proc_stats; }
663
global_stats() const664 bool global_stats() const override
665 { return true; }
666
sum_stats(bool)667 void sum_stats(bool) override
668 { } // accumulate externally
669
670 ProfileStats* get_profile(unsigned, const char*&, const char*&) const override;
671
get_usage() const672 Usage get_usage() const override
673 { return GLOBAL; }
674
675 void set_trace(const Trace*) const override;
676 const TraceOption* get_trace_options() const override;
677
678 private:
679 SFDAQModuleConfig* module_config;
680 bool no_warn_flowbits = false;
681 bool no_warn_rules = false;
682 std::string stub_opts;
683 };
684
set_trace(const Trace * trace) const685 void SnortModule::set_trace(const Trace* trace) const
686 { snort_trace = trace; }
687
get_trace_options() const688 const TraceOption* SnortModule::get_trace_options() const
689 {
690 return snort_trace_options;
691 }
692
begin(const char * fqn,int,SnortConfig *)693 bool SnortModule::begin(const char* fqn, int, SnortConfig*)
694 {
695 if (!strcmp(fqn, "snort"))
696 module_config = nullptr;
697 return true;
698 }
699
set(const char *,Value & v,SnortConfig * sc)700 bool SnortModule::set(const char*, Value& v, SnortConfig* sc)
701 {
702 if ( v.is("-?") )
703 help_options(sc, v.get_string());
704
705 else if ( v.is("-A") )
706 sc->set_alert_mode(v.get_string());
707
708 else if ( v.is("-B") )
709 sc->set_obfuscation_mask(v.get_string());
710
711 else if ( v.is("-C") )
712 sc->set_dump_chars_only(true);
713
714 else if ( v.is("-c") )
715 config_conf(v.get_string());
716
717 else if ( v.is("-D") )
718 sc->set_daemon(true);
719
720 else if ( v.is("-d") )
721 sc->set_dump_payload(true);
722
723 else if ( v.is("-e") )
724 sc->set_decode_data_link(true);
725
726 else if ( v.is("-f") )
727 sc->output_flags |= OUTPUT_FLAG__LINE_BUFFER;
728
729 else if ( v.is("-G") || v.is("--logid") )
730 sc->event_log_id = v.get_uint16();
731
732 else if ( v.is("-g") )
733 sc->set_gid(v.get_string());
734
735 else if ( v.is("-H") )
736 sc->run_flags |= RUN_FLAG__STATIC_HASH;
737
738 else if ( v.is("-h") )
739 help_basic(sc, v.get_string());
740
741 else if ( v.is("-i") )
742 sc->daq_config->add_input(v.get_string());
743
744 #ifdef SHELL
745 else if ( v.is("-j") )
746 {
747 sc->remote_control_port = v.get_uint16();
748 sc->remote_control_socket.clear();
749 }
750 #endif
751
752 else if ( v.is("-k") )
753 ConfigChecksumMode(v.get_string());
754
755 else if ( v.is("-L") )
756 sc->set_log_mode(v.get_string());
757
758 else if ( v.is("-l") )
759 sc->set_log_dir(v.get_string());
760
761 else if ( v.is("-M") )
762 sc->enable_syslog();
763
764 else if ( v.is("-m") )
765 sc->set_umask(v.get_uint32());
766
767 else if ( v.is("-n") )
768 sc->pkt_cnt = v.get_uint64();
769
770 else if ( v.is("-O") )
771 sc->set_obfuscate(true);
772
773 else if ( v.is("-Q") )
774 sc->run_flags |= RUN_FLAG__INLINE;
775
776 else if ( v.is("-q") )
777 SnortConfig::set_log_quiet(true);
778
779 else if ( v.is("-R") )
780 {
781 string s = "include ";
782 s += v.get_string();
783 parser_append_rules(s.c_str());
784 }
785 else if ( v.is("-r") || v.is("--pcap-list") )
786 {
787 sc->run_flags |= RUN_FLAG__READ;
788 Trough::add_source(Trough::SOURCE_LIST, v.get_string());
789 }
790
791 else if ( v.is("-s") or v.is("--snaplen") )
792 sc->daq_config->set_mru_size(v.get_uint16());
793
794 else if ( v.is("-T") )
795 sc->run_flags |= RUN_FLAG__TEST;
796
797 else if ( v.is("-t") )
798 sc->set_chroot_dir(v.get_string());
799
800 else if ( v.is("-U") )
801 sc->set_utc(true);
802
803 else if ( v.is("-u") )
804 sc->set_uid(v.get_string());
805
806 else if ( v.is("-V") )
807 help_version(sc);
808
809 else if ( v.is("-v") )
810 SnortConfig::enable_log_verbose();
811
812 else if ( v.is("-X") )
813 sc->set_dump_payload_verbose(true);
814
815 else if ( v.is("-x") || v.is("--pedantic") )
816 sc->run_flags |= RUN_FLAG__CONF_ERROR_OUT;
817
818 else if ( v.is("-y") )
819 sc->set_show_year(true);
820
821 else if ( v.is("-z") || v.is("--max-packet-threads") )
822 ThreadConfig::set_instance_max(v.get_uint32());
823
824 else if ( v.is("--alert-before-pass") )
825 sc->set_alert_before_pass(true);
826
827 else if ( v.is("--bpf") )
828 sc->bpf_filter = v.get_string();
829
830 else if ( v.is("--c2x") )
831 c2x(v.get_string());
832
833 #ifdef SHELL
834 else if ( v.is("--control-socket") )
835 {
836 sc->remote_control_socket = v.get_string();
837 sc->remote_control_port = 0;
838 }
839 #endif
840
841 else if ( v.is("--create-pidfile") )
842 sc->set_create_pid_file(true);
843
844 else if ( v.is("--daq") )
845 module_config = sc->daq_config->add_module_config(v.get_string());
846
847 else if ( v.is("--daq-batch-size") )
848 sc->daq_config->set_batch_size(v.get_uint32());
849
850 else if ( v.is("--daq-dir") )
851 {
852 stringstream ss { v.get_string() };
853 string path;
854
855 while ( getline(ss, path, ':') )
856 sc->daq_config->add_module_dir(path.c_str());
857 }
858 else if ( v.is("--daq-mode") )
859 {
860 if (!module_config)
861 return false;
862 switch ( v.get_uint8() )
863 {
864 case 0:
865 module_config->mode = SFDAQModuleConfig::SFDAQ_MODE_PASSIVE;
866 break;
867 case 1:
868 module_config->mode = SFDAQModuleConfig::SFDAQ_MODE_INLINE;
869 break;
870 case 2:
871 module_config->mode = SFDAQModuleConfig::SFDAQ_MODE_READ_FILE;
872 break;
873 }
874 }
875 else if ( v.is("--daq-list") )
876 list_daqs(sc);
877
878 else if ( v.is("--daq-var") )
879 {
880 if (!module_config)
881 return false;
882 module_config->set_variable(v.get_string());
883 }
884 else if ( v.is("--dirty-pig") )
885 sc->set_dirty_pig(true);
886
887 else if ( v.is("--dump-builtin-options") )
888 stub_opts = v.get_string();
889
890 else if ( v.is("--dump-builtin-rules") )
891 dump_builtin_rules(sc, v.get_string(), stub_opts.c_str());
892
893 else if ( v.is("--dump-config") )
894 {
895 SnortConfig::set_log_quiet(true);
896 sc->run_flags |= RUN_FLAG__TEST;
897 if ( v.get_as_string() == "all" )
898 sc->dump_config_type = DUMP_CONFIG_JSON_ALL;
899 else if ( v.get_as_string() == "top" )
900 sc->dump_config_type = DUMP_CONFIG_JSON_TOP;
901 }
902
903 else if ( v.is("--dump-config-text") )
904 {
905 SnortConfig::set_log_quiet(true);
906 sc->run_flags |= RUN_FLAG__TEST;
907 sc->dump_config_type = DUMP_CONFIG_TEXT;
908 }
909
910 else if ( v.is("--dump-dynamic-rules") )
911 dump_dynamic_rules(sc, v.get_string());
912
913 else if ( v.is("--dump-defaults") )
914 dump_defaults(sc, v.get_string());
915
916 else if ( v.is("--dump-rule-databases") )
917 {
918 sc->set_rule_db_dir(v.get_string());
919 sc->run_flags |= (RUN_FLAG__TEST | RUN_FLAG__MEM_CHECK);
920 }
921 else if ( v.is("--dump-rule-deps") )
922 {
923 sc->run_flags |= (RUN_FLAG__DUMP_RULE_DEPS | RUN_FLAG__TEST);
924 SnortConfig::set_log_quiet(true);
925 }
926 else if ( v.is("--dump-rule-meta") )
927 {
928 sc->run_flags |= (RUN_FLAG__DUMP_RULE_META | RUN_FLAG__TEST);
929 sc->output_flags |= OUTPUT_FLAG__ALERT_REFS;
930 SnortConfig::set_log_quiet(true);
931 }
932 else if ( v.is("--dump-rule-state") )
933 {
934 sc->run_flags |= (RUN_FLAG__DUMP_RULE_STATE | RUN_FLAG__TEST);
935 SnortConfig::set_log_quiet(true);
936 }
937 else if ( v.is("--dump-version") )
938 dump_version(sc);
939
940 else if ( v.is("--enable-inline-test") )
941 sc->run_flags |= RUN_FLAG__INLINE_TEST;
942
943 else if ( v.is("--enable-test-features") )
944 {
945 sc->run_flags |= RUN_FLAG__TEST_FEATURES;
946 SfIp::test_features = true;
947 }
948
949 else if ( v.is("--gen-msg-map") )
950 {
951 sc->run_flags |= (RUN_FLAG__DUMP_MSG_MAP | RUN_FLAG__TEST);
952 sc->output_flags |= OUTPUT_FLAG__ALERT_REFS;
953 SnortConfig::set_log_quiet(true);
954 }
955 else if ( v.is("--help") )
956 help_basic(sc, v.get_string());
957
958 else if ( v.is("--help-commands") )
959 help_commands(sc, v.get_string());
960
961 else if ( v.is("--help-config") )
962 help_config(sc, v.get_string());
963
964 else if ( v.is("--help-counts") )
965 help_counts(sc, v.get_string());
966
967 else if ( v.is("--help-limits") )
968 help_limits(sc, v.get_string());
969
970 else if ( v.is("--help-module") )
971 help_module(sc, v.get_string());
972
973 else if ( v.is("--help-modules") )
974 help_modules(sc, v.get_string());
975
976 else if ( v.is("--help-modules-json") )
977 help_modules_json(sc, v.get_string());
978
979 else if ( v.is("--help-options") )
980 help_options(sc, v.get_string());
981
982 else if ( v.is("--help-plugins") )
983 help_plugins(sc, v.get_string());
984
985 else if ( v.is("--help-signals") )
986 help_signals(sc, v.get_string());
987
988 else if ( v.is("--id-offset") )
989 sc->id_offset = v.get_uint16();
990
991 else if ( v.is("--id-subdir") )
992 sc->id_subdir = true;
993
994 else if ( v.is("--id-zero") )
995 sc->id_zero = true;
996
997 else if ( v.is("--include-path") )
998 sc->set_include_path(v.get_string());
999
1000 else if ( v.is("--list-buffers") )
1001 help_buffers(sc, v.get_string());
1002
1003 else if ( v.is("--list-builtin") )
1004 help_builtin(sc, v.get_string());
1005
1006 else if ( v.is("--list-gids") )
1007 help_gids(sc, v.get_string());
1008
1009 else if ( v.is("--list-modules") )
1010 list_modules(sc, v.get_string());
1011
1012 else if ( v.is("--list-plugins") )
1013 list_plugins(sc, v.get_string());
1014
1015 else if ( v.is("--lua") )
1016 sc->policy_map->get_shell()->set_overrides(v.get_string());
1017
1018 else if ( v.is("--lua-sandbox") )
1019 Shell::set_lua_sandbox(v.get_string());
1020
1021 else if ( v.is("--markup") )
1022 config_markup(sc, v.get_string());
1023
1024 else if ( v.is("--mem-check") )
1025 sc->run_flags |= (RUN_FLAG__TEST | RUN_FLAG__MEM_CHECK);
1026
1027 else if ( v.is("--metadata-filter") )
1028 sc->metadata_filter = v.get_string();
1029
1030 else if ( v.is("--nostamps") )
1031 sc->set_no_logging_timestamps(true);
1032
1033 else if ( v.is("--nolock-pidfile") )
1034 sc->run_flags |= RUN_FLAG__NO_LOCK_PID_FILE;
1035
1036 else if ( v.is("--no-warn-flowbits") )
1037 no_warn_flowbits = true;
1038
1039 else if ( v.is("--no-warn-rules") )
1040 no_warn_rules = true;
1041
1042 else if ( v.is("--pause") )
1043 sc->run_flags |= RUN_FLAG__PAUSE;
1044
1045 #ifdef REG_TEST
1046 else if ( v.is("--pause-after-n") )
1047 sc->pkt_pause_cnt = v.get_uint64();
1048 #endif
1049
1050 else if ( v.is("--pcap-file") )
1051 {
1052 sc->run_flags |= RUN_FLAG__READ;
1053 Trough::add_source(Trough::SOURCE_FILE_LIST, v.get_string());
1054 }
1055 else if ( v.is("--pcap-dir") )
1056 {
1057 sc->run_flags |= RUN_FLAG__READ;
1058 Trough::add_source(Trough::SOURCE_DIR, v.get_string());
1059 }
1060 else if ( v.is("--pcap-filter") )
1061 Trough::set_filter(v.get_string());
1062
1063 else if ( v.is("--pcap-loop") )
1064 Trough::set_loop_count(v.get_uint32());
1065
1066 else if ( v.is("--pcap-no-filter") )
1067 Trough::set_filter(nullptr);
1068
1069 else if ( v.is("--pcap-show") )
1070 sc->run_flags |= RUN_FLAG__PCAP_SHOW;
1071
1072 #ifdef PIGLET
1073 else if ( v.is("--piglet") )
1074 sc->run_flags |= RUN_FLAG__PIGLET;
1075 #endif
1076
1077 else if ( v.is("--plugin-path") )
1078 sc->add_plugin_path(v.get_string());
1079
1080 else if ( v.is("--process-all-events") )
1081 sc->set_process_all_events(true);
1082
1083 else if ( v.is("--rule") )
1084 parser_append_rules(v.get_string());
1085
1086 else if ( v.is("--rule-path") )
1087 parser_append_includes(v.get_string());
1088
1089 else if ( v.is("--rule-to-hex") )
1090 dump_rule_hex(sc, v.get_string());
1091
1092 else if ( v.is("--rule-to-text") )
1093 dump_rule_text(sc, v.get_string());
1094
1095 else if ( v.is("--run-prefix") )
1096 sc->run_prefix = v.get_string();
1097
1098 else if ( v.is("--script-path") )
1099 sc->add_script_path(v.get_string());
1100
1101 #ifdef SHELL
1102 else if ( v.is("--shell") )
1103 sc->run_flags |= RUN_FLAG__SHELL;
1104 #endif
1105
1106 else if ( v.is("--show-file-codes") )
1107 sc->run_flags |= RUN_FLAG__SHOW_FILE_CODES;
1108
1109 else if ( v.is("--show-plugins") )
1110 SnortConfig::enable_log_show_plugins();
1111
1112 else if ( v.is("--skip") )
1113 sc->pkt_skip = v.get_uint64();
1114
1115 else if ( v.is("--stdin-rules") )
1116 sc->stdin_rules = true;
1117
1118 else if ( v.is("--talos") )
1119 sc->set_tweaks("talos");
1120
1121 else if ( v.is("--tweaks") )
1122 sc->set_tweaks(v.get_string());
1123
1124 #if defined(UNIT_TEST) || defined(BENCHMARK_TEST)
1125 else if ( v.is("--catch-test") )
1126 catch_set_filter(v.get_string());
1127 #endif
1128 else if ( v.is("--version") )
1129 help_version(sc);
1130
1131 else if ( v.is("--warn-all") )
1132 sc->warning_flags = 0xFFFFFFFF;
1133
1134 else if ( v.is("--warn-conf") )
1135 sc->warning_flags |= (1 << WARN_CONF);
1136
1137 else if ( v.is("--warn-conf-strict") )
1138 sc->warning_flags |= (1 << WARN_CONF_STRICT);
1139
1140 else if ( v.is("--warn-daq") )
1141 sc->warning_flags |= (1 << WARN_DAQ);
1142
1143 else if ( v.is("--warn-flowbits") )
1144 sc->warning_flags |= (1 << WARN_FLOWBITS);
1145
1146 else if ( v.is("--warn-hosts") )
1147 sc->warning_flags |= (1 << WARN_HOSTS);
1148
1149 else if ( v.is("--warn-plugins") )
1150 sc->warning_flags |= (1 << WARN_PLUGINS);
1151
1152 else if ( v.is("--warn-rules") )
1153 sc->warning_flags |= (1 << WARN_RULES);
1154
1155 else if ( v.is("--warn-scripts") )
1156 sc->warning_flags |= (1 << WARN_SCRIPTS);
1157
1158 else if ( v.is("--warn-symbols") )
1159 sc->warning_flags |= (1 << WARN_SYMBOLS);
1160
1161 else if ( v.is("--warn-vars") )
1162 sc->warning_flags |= (1 << WARN_VARS);
1163
1164 else if ( v.is("--x2c") )
1165 x2c(v.get_uint8());
1166
1167 else if ( v.is("--x2s") )
1168 x2s(v.get_string());
1169
1170 return true;
1171 }
1172
end(const char *,int,SnortConfig * sc)1173 bool SnortModule::end(const char*, int, SnortConfig* sc)
1174 {
1175 if ( sc->offload_threads and ThreadConfig::get_instance_max() != 1 )
1176 ParseError("You can not enable experimental offload with more than one packet thread.");
1177
1178 if ( no_warn_flowbits )
1179 {
1180 sc->warning_flags &= ~(1 << WARN_FLOWBITS);
1181 no_warn_flowbits = false;
1182 }
1183
1184 if ( no_warn_rules )
1185 {
1186 sc->warning_flags &= ~(1 << WARN_RULES);
1187 no_warn_rules = false;
1188 }
1189
1190 return true;
1191 }
1192
get_profile(unsigned index,const char * & name,const char * & parent) const1193 ProfileStats* SnortModule::get_profile(
1194 unsigned index, const char*& name, const char*& parent) const
1195 {
1196 switch ( index )
1197 {
1198 case 0:
1199 name = "daq";
1200 parent = nullptr;
1201 return &daqPerfStats;
1202
1203 case 1:
1204 name = "decode";
1205 parent = nullptr;
1206 return &decodePerfStats;
1207
1208 case 2:
1209 name = "mpse";
1210 parent = nullptr;
1211 return &mpsePerfStats;
1212
1213 case 3:
1214 name = "rule_eval";
1215 parent = nullptr;
1216 return &rulePerfStats;
1217
1218 case 4:
1219 name = "eventq";
1220 parent = nullptr;
1221 return &eventqPerfStats;
1222 }
1223 return nullptr;
1224 }
1225
1226 //-------------------------------------------------------------------------
1227 // singleton
1228 //-------------------------------------------------------------------------
1229
1230 static SnortModule* snort_module = nullptr;
1231
get_snort_module()1232 Module* get_snort_module()
1233 {
1234 if ( !snort_module )
1235 snort_module = new SnortModule;
1236
1237 return snort_module;
1238 }
1239
1240