1 //--------------------------------------------------------------------------
2 // Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
3 // Copyright (C) 2013-2013 Sourcefire, Inc.
4 //
5 // This program is free software; you can redistribute it and/or modify it
6 // under the terms of the GNU General Public License Version 2 as published
7 // by the Free Software Foundation.  You may not use, modify or distribute
8 // this program under any other version of the GNU General Public License.
9 //
10 // This program is distributed in the hope that it will be useful, but
11 // WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License along
16 // with this program; if not, write to the Free Software Foundation, Inc.,
17 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18 //--------------------------------------------------------------------------
19 
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23 
24 #include "snort_config.h"
25 
26 #include <grp.h>
27 #include <pwd.h>
28 #include <syslog.h>
29 
30 #include "actions/ips_actions.h"
31 #include "detection/detect.h"
32 #include "detection/detection_engine.h"
33 #include "detection/fp_config.h"
34 #include "detection/fp_create.h"
35 #include "dump_config/json_config_output.h"
36 #include "dump_config/text_config_output.h"
37 #include "file_api/file_service.h"
38 #include "filters/detection_filter.h"
39 #include "filters/rate_filter.h"
40 #include "filters/sfrf.h"
41 #include "filters/sfthreshold.h"
42 #include "flow/ha_module.h"
43 #include "framework/policy_selector.h"
44 #include "hash/xhash.h"
45 #include "helpers/process.h"
46 #include "latency/latency_config.h"
47 #include "log/messages.h"
48 #include "managers/action_manager.h"
49 #include "managers/event_manager.h"
50 #include "managers/inspector_manager.h"
51 #include "managers/ips_manager.h"
52 #include "managers/module_manager.h"
53 #include "managers/mpse_manager.h"
54 #include "managers/plugin_manager.h"
55 #include "managers/so_manager.h"
56 #include "memory/memory_config.h"
57 #include "packet_io/sfdaq.h"
58 #include "packet_io/sfdaq_config.h"
59 #include "parser/parser.h"
60 #include "parser/vars.h"
61 #include "payload_injector/payload_injector_config.h"
62 #include "ports/rule_port_tables.h"
63 #include "profiler/profiler.h"
64 #include "protocols/packet.h"
65 #include "sfip/sf_ip.h"
66 #include "main/snort.h"
67 #include "target_based/host_attributes.h"
68 #include "target_based/snort_protocols.h"
69 #include "trace/trace_config.h"
70 #include "utils/dnet_header.h"
71 #include "utils/util.h"
72 #include "utils/util_cstring.h"
73 
74 #include "analyzer.h"
75 #include "thread_config.h"
76 
77 using namespace snort;
78 
79 #define LOG_NONE    "none"
80 #define LOG_DUMP    "dump"
81 #define LOG_CODECS  "codecs"
82 
83 #define ALERT_NONE  "none"
84 #define ALERT_CMG   "cmg"
85 #define ALERT_JH    "jh"
86 #define ALERT_DJR   "djr"
87 #define ALERT_U2    "u2"
88 #define ALERT_AJK   "ajk"
89 
90 #define OUTPUT_U2   "unified2"
91 #define OUTPUT_FAST "alert_fast"
92 
93 static THREAD_LOCAL const SnortConfig* snort_conf = nullptr;
94 
95 uint32_t SnortConfig::warning_flags = 0;
96 uint32_t SnortConfig::logging_flags = 0;
97 
98 static std::vector<ScratchAllocator*> scratch_handlers;
99 
100 //-------------------------------------------------------------------------
101 // private implementation
102 //-------------------------------------------------------------------------
103 
init_policy_mode(const SnortConfig * sc,PolicyMode mode)104 static PolicyMode init_policy_mode(const SnortConfig* sc, PolicyMode mode)
105 {
106     switch ( mode )
107     {
108     case POLICY_MODE__PASSIVE:
109         if ( sc->adaptor_inline_test_mode() )
110             return POLICY_MODE__INLINE_TEST;
111         break;
112 
113     case POLICY_MODE__INLINE:
114         if ( sc->adaptor_inline_test_mode() )
115             return POLICY_MODE__INLINE_TEST;
116 
117         else if (!sc->adaptor_inline_mode())
118         {
119             ParseWarning(WARN_DAQ, "adapter is in passive mode; switching policy mode to tap.");
120             return POLICY_MODE__PASSIVE;
121         }
122         break;
123 
124     case POLICY_MODE__INLINE_TEST:
125         break;
126 
127     case POLICY_MODE__MAX:
128         if ( sc->adaptor_inline_mode() )
129             return POLICY_MODE__INLINE;
130         else
131             return POLICY_MODE__PASSIVE;
132         break;
133     }
134     return mode;
135 }
136 
init_policies(SnortConfig * sc)137 static void init_policies(SnortConfig* sc)
138 {
139     IpsPolicy* ips_policy = nullptr;
140     InspectionPolicy* inspection_policy = nullptr;
141 
142     for ( unsigned idx = 0; idx <  sc->policy_map->ips_policy_count(); ++idx )
143     {
144         ips_policy = sc->policy_map->get_ips_policy(idx);
145         ips_policy->policy_mode = init_policy_mode(sc, ips_policy->policy_mode);
146     }
147 
148     for ( unsigned idx = 0; idx < sc->policy_map->inspection_policy_count(); ++idx )
149     {
150         inspection_policy = sc->policy_map->get_inspection_policy(idx);
151         inspection_policy->policy_mode = init_policy_mode(sc, inspection_policy->policy_mode);
152     }
153 }
154 
init(const SnortConfig * const other_conf,ProtocolReference * protocol_reference,const char * exclude_name)155 void SnortConfig::init(const SnortConfig* const other_conf, ProtocolReference* protocol_reference,
156     const char* exclude_name)
157 {
158     homenet.clear();
159     obfuscation_net.clear();
160 
161     if ( !other_conf )
162     {
163         num_layers = DEFAULT_LAYERMAX;
164 
165         max_attribute_hosts = DEFAULT_MAX_ATTRIBUTE_HOSTS;
166         max_attribute_services_per_host = DEFAULT_MAX_ATTRIBUTE_SERVICES_PER_HOST;
167 
168         max_metadata_services = DEFAULT_MAX_METADATA_SERVICES;
169 
170         daq_config = new SFDAQConfig();
171         ActionManager::new_config(this);
172         InspectorManager::new_config(this);
173 
174         num_slots = 0;
175         state = nullptr;
176 
177         profiler = new ProfilerConfig;
178         latency = new LatencyConfig();
179         memory = new MemoryConfig();
180         policy_map = new PolicyMap;
181         thread_config = new ThreadConfig();
182 
183         proto_ref = new ProtocolReference(protocol_reference);
184         so_rules = new SoRules;
185         trace_config = new TraceConfig;
186     }
187     else
188     {
189         clone(other_conf);
190         policy_map = new PolicyMap(other_conf->policy_map, exclude_name);
191     }
192 }
193 
194 //-------------------------------------------------------------------------
195 // public methods
196 //-------------------------------------------------------------------------
197 
198 /* A lot of this initialization can be skipped if not running in IDS mode
199  * but the goal is to minimize config checks at run time when running in
200  * IDS mode so we keep things simple and enforce that the only difference
201  * among run_modes is how we handle packets via the log_func. */
SnortConfig(const SnortConfig * const other_conf,const char * exclude_name)202 SnortConfig::SnortConfig(const SnortConfig* const other_conf, const char* exclude_name)
203 {
204     init(other_conf, nullptr, exclude_name);
205 }
206 
207 //  Copy the ProtocolReference data into the new SnortConfig.
SnortConfig(ProtocolReference * protocol_reference)208 SnortConfig::SnortConfig(ProtocolReference* protocol_reference)
209 {
210     init(nullptr, protocol_reference, nullptr);
211 }
212 
~SnortConfig()213 SnortConfig::~SnortConfig()
214 {
215     if ( cloned )
216     {
217         policy_map->set_cloned(true);
218         delete policy_map;
219         return;
220     }
221 
222     for ( auto ct : classifications )
223         delete ct.second;
224 
225     for ( auto rs : references )
226         delete rs.second;
227 
228     for ( auto* s : scratchers )
229         s->cleanup(this);
230 
231     FreeRuleLists(this);
232     PortTablesFree(port_tables);
233 
234     ThresholdConfigFree(threshold_config);
235     RateFilter_ConfigFree(rate_filter_config);
236     DetectionFilterConfigFree(detection_filter_config);
237 
238     if ( event_queue_config )
239         EventQueueConfigFree(event_queue_config);
240 
241     fpDeleteFastPacketDetection(this);
242     OtnLookupFree(otn_map);
243 
244     delete rtn_hash_table;
245 
246     if (eth_dst )
247         snort_free(eth_dst);
248 
249     if ( fast_pattern_config &&
250         (!snort_conf || this == snort_conf ||
251         (fast_pattern_config->get_search_api() !=
252         get_conf()->fast_pattern_config->get_search_api())) )
253     {
254         MpseManager::stop_search_engine(fast_pattern_config->get_search_api());
255     }
256     delete fast_pattern_config;
257 
258     delete policy_map;
259     InspectorManager::delete_config(this);
260     ActionManager::delete_config(this);
261 
262     delete[] state;
263     delete thread_config;
264     delete trace_config;
265     delete overlay_trace_config;
266     delete ha_config;
267 
268     delete profiler;
269     delete latency;
270     delete memory;
271     delete daq_config;
272     delete proto_ref;
273     delete[] evalOrder;
274     delete so_rules;
275     if ( plugins )
276         delete plugins;
277     delete payload_injector_config;
278     InspectorManager::free_flow_tracking(flow_tracking);
279     PolicySelector::free_policy_selector(global_selector);
280     clear_reload_resource_tuner_list();
281 
282     trim_heap();
283 }
284 
setup()285 void SnortConfig::setup()
286 {
287     if ( output_use_utc() )
288         thiszone = 0;
289 
290     else
291         thiszone = gmt2local(0);
292 
293     init_policies(this);
294     ParseRules(this);
295 
296     // Allocate evalOrder before calling the OrderRuleLists
297     evalOrder = new int[Actions::get_max_types()]();
298 
299     OrderRuleLists(this);
300 
301     if ( rule_states )
302     {
303         rule_states->apply(this);
304         delete rule_states;
305         rule_states = nullptr;
306     }
307 
308     ParseRulesFinish(this);
309     ShowPolicyStats(this);
310 
311     /* Need to do this after dynamic detection stuff is initialized, too */
312     IpsManager::verify(this);
313     ModuleManager::load_commands(policy_map->get_shell());
314 
315     fpCreateFastPacketDetection(this);
316 }
317 
post_setup()318 void SnortConfig::post_setup()
319 {
320     unsigned int handler_count = scratch_handlers.size();
321 
322     // Ensure we have allocated the scratch space vector for each thread
323     for ( unsigned i = 0; i < num_slots; ++i )
324         state[i].resize(handler_count);
325 
326     for ( auto* s : scratch_handlers )
327     {
328         if ( s and s->setup(this) )
329             scratchers.push_back(s);
330     }
331 }
332 
clone(const SnortConfig * const conf)333 void SnortConfig::clone(const SnortConfig* const conf)
334 {
335     *this = *conf;
336     if (conf->homenet.get_family() != 0)
337         memcpy(&homenet, &conf->homenet, sizeof(homenet));
338 
339     if (conf->obfuscation_net.get_family() != 0)
340         memcpy(&obfuscation_net, &conf->obfuscation_net, sizeof(obfuscation_net));
341 }
342 
343 // merge in everything from the command line config
merge(const SnortConfig * cmd_line_conf)344 void SnortConfig::merge(const SnortConfig* cmd_line_conf)
345 {
346     // -D / -H / -Q / -r / -T / -x / --alert-before-pass / --create-pidfile / --enable-inline-test / --mem-check /
347     // --nolock-pidfile / --pause / --pcap-file / --pcap-dir / --pcap-list / --pcap-show / --pedantic / --piglet /
348     // --shell / --show-file-codes
349     run_flags |= cmd_line_conf->run_flags;
350 
351     // -A / -C / -d / -e / -f / -O / -U / -X / -y / --nostamps
352     output_flags |= cmd_line_conf->output_flags;
353 
354     // -B
355     if (cmd_line_conf->obfuscation_net.get_family() != 0)
356         memcpy(&obfuscation_net, &cmd_line_conf->obfuscation_net, sizeof(obfuscation_net));
357 
358     // -g
359     if (cmd_line_conf->group_id != -1)
360         group_id = cmd_line_conf->group_id;
361 
362     // -G / --logid
363     event_log_id = cmd_line_conf->event_log_id;
364 
365     // -i / -s / --daq / --daq-batch-size / --daq-dir / --daq-list / --daq-mode / --daq-var / --snaplen
366     daq_config->overlay(cmd_line_conf->daq_config);
367 
368     // -k (only configures eval, not drop)
369     int cl_chk = cmd_line_conf->policy_map->get_network_policy()->checksum_eval;
370     if (!(cl_chk & CHECKSUM_FLAG__DEF))
371     {
372         for (unsigned idx = 0; idx < policy_map->network_policy_count(); ++idx)
373         {
374             NetworkPolicy* nw_policy = policy_map->get_network_policy(idx);
375             if (!(cl_chk & CHECKSUM_FLAG__DEF))
376                 nw_policy->checksum_eval = cl_chk;
377         }
378     }
379 
380     // -l
381     if ( !cmd_line_conf->log_dir.empty() )
382         log_dir = cmd_line_conf->log_dir;
383 
384     // -L (output is only set by cmd_line_conf to override other conf output settings)
385     output = cmd_line_conf->output;
386 
387     // -m
388     if (cmd_line_conf->file_mask != 0)
389         file_mask = cmd_line_conf->file_mask;
390 
391     // -n
392     if (cmd_line_conf->pkt_cnt != 0)
393         pkt_cnt = cmd_line_conf->pkt_cnt;
394 
395     // -t
396     if (!cmd_line_conf->chroot_dir.empty())
397         chroot_dir = cmd_line_conf->chroot_dir;
398 
399     // -u
400     if (cmd_line_conf->user_id != -1)
401         user_id = cmd_line_conf->user_id;
402 
403     // --bpf
404     if (!cmd_line_conf->bpf_filter.empty())
405         bpf_filter = cmd_line_conf->bpf_filter;
406 
407     // --dirty-pig
408     if (cmd_line_conf->dirty_pig)
409         dirty_pig = cmd_line_conf->dirty_pig;
410 
411     // --dump-rule-databases
412     if (!cmd_line_conf->rule_db_dir.empty())
413         rule_db_dir = cmd_line_conf->rule_db_dir;
414 
415     // --id-offset
416     id_offset = cmd_line_conf->id_offset;
417     // --id-subdir
418     id_subdir = cmd_line_conf->id_subdir;
419     // --id-zero
420     id_zero = cmd_line_conf->id_zero;
421 
422     // --include-path
423     include_path = cmd_line_conf->include_path;
424 
425     // --metadata-filter
426     if (!cmd_line_conf->metadata_filter.empty())
427         metadata_filter = cmd_line_conf->metadata_filter;
428 
429     // --pause-after-n
430     if (cmd_line_conf->pkt_pause_cnt != 0)
431         pkt_pause_cnt = cmd_line_conf->pkt_pause_cnt;
432 
433     // --process-all-events
434     if (cmd_line_conf->run_flags & RUN_FLAG__PROCESS_ALL_EVENTS)
435         event_queue_config->process_all_events = 1;
436 
437     // --run-prefix
438     run_prefix = cmd_line_conf->run_prefix;
439 
440     // --skip
441     if (cmd_line_conf->pkt_skip != 0)
442         pkt_skip = cmd_line_conf->pkt_skip;
443 
444     // --stdin-rules
445     stdin_rules = cmd_line_conf->stdin_rules;
446 
447 #ifdef SHELL
448     // -j
449     if (cmd_line_conf->remote_control_port)
450         remote_control_port = cmd_line_conf->remote_control_port;
451     // --control-socket
452     else if (!cmd_line_conf->remote_control_socket.empty())
453         remote_control_socket = cmd_line_conf->remote_control_socket;
454 #endif
455 
456     // Finalize the log directory, save a copy in case we need to chroot
457     if ( log_dir.empty() )
458         log_dir = DEFAULT_LOG_DIR;
459     orig_log_dir = log_dir;
460 
461     // Initialize the slotted state memory for threads
462     assert(!state);
463     num_slots = offload_threads + ThreadConfig::get_instance_max();
464     state = new std::vector<void*>[num_slots];
465 }
466 
verify() const467 bool SnortConfig::verify() const
468 {
469     bool config_ok = false;
470     const SnortConfig* sc = get_conf();
471 
472     if ( sc->asn1_mem != asn1_mem )
473         ReloadError("Changing detection.asn1_mem requires a restart.\n");
474 
475     else if ( sc->bpf_filter != bpf_filter )
476         ReloadError("Changing packets.bfp_filter requires a restart.\n");
477 
478     else if ( sc->respond_attempts != respond_attempts )
479         ReloadError("Changing active.attempts requires a restart.\n");
480 
481     else if (  sc->respond_device != respond_device )
482         ReloadError("Changing active.device requires a restart.\n");
483 
484     else if (sc->chroot_dir != chroot_dir)
485         ReloadError("Changing process.chroot requires a restart.\n");
486 
487     else if ((sc->run_flags & RUN_FLAG__DAEMON) != (run_flags & RUN_FLAG__DAEMON))
488         ReloadError("Changing process.daemon requires a restart.\n");
489 
490     else if (sc->orig_log_dir != orig_log_dir)
491         ReloadError("Changing output.logdir requires a restart.\n");
492 
493     else if (sc->group_id != group_id)
494         ReloadError("Changing process.setgid requires a restart.\n");
495 
496     else if (sc->user_id != user_id)
497         ReloadError("Changing process.setuid requires a restart.\n");
498 
499     else if (sc->daq_config->get_mru_size() != daq_config->get_mru_size())
500         ReloadError("Changing daq.snaplen requires a restart.\n");
501 
502     else if (sc->threshold_config->memcap != threshold_config->memcap)
503         ReloadError("Changing alerts.event_filter_memcap requires a restart.\n");
504 
505     else  if (sc->rate_filter_config->memcap != rate_filter_config->memcap)
506         ReloadError("Changing alerts.rate_filter_memcap requires a restart.\n");
507 
508     else if (sc->detection_filter_config->memcap != detection_filter_config->memcap)
509         ReloadError("Changing alerts.detection_filter_memcap requires a restart.\n");
510 
511     else
512         config_ok = true;
513 
514     return config_ok;
515 }
516 
set_alert_before_pass(bool enabled)517 void SnortConfig::set_alert_before_pass(bool enabled)
518 {
519     if (enabled)
520         run_flags |= RUN_FLAG__ALERT_BEFORE_PASS;
521     else
522         run_flags &= ~RUN_FLAG__ALERT_BEFORE_PASS;
523 }
524 
set_chroot_dir(const char * directory)525 void SnortConfig::set_chroot_dir(const char* directory)
526 {
527     if (directory)
528         chroot_dir = directory;
529     else
530         chroot_dir.clear();
531 }
532 
set_create_pid_file(bool enabled)533 void SnortConfig::set_create_pid_file(bool enabled)
534 {
535     if (enabled)
536         run_flags |= RUN_FLAG__CREATE_PID_FILE;
537     else
538         run_flags &= ~RUN_FLAG__CREATE_PID_FILE;
539 }
540 
set_daemon(bool enabled)541 void SnortConfig::set_daemon(bool enabled)
542 {
543     if (enabled)
544     {
545         run_flags |= RUN_FLAG__DAEMON;
546     }
547     else
548         run_flags &= ~RUN_FLAG__DAEMON;
549 }
550 
set_decode_data_link(bool enabled)551 void SnortConfig::set_decode_data_link(bool enabled)
552 {
553     if (enabled)
554     {
555         output_flags |= OUTPUT_FLAG__SHOW_DATA_LINK;
556     }
557     else
558         output_flags &= ~OUTPUT_FLAG__SHOW_DATA_LINK;
559 }
560 
set_dump_chars_only(bool enabled)561 void SnortConfig::set_dump_chars_only(bool enabled)
562 {
563     if (enabled)
564     {
565         /* dump the application layer as text only */
566         output_flags |= OUTPUT_FLAG__CHAR_DATA;
567     }
568     else
569         output_flags &= ~OUTPUT_FLAG__CHAR_DATA;
570 }
571 
set_dump_payload(bool enabled)572 void SnortConfig::set_dump_payload(bool enabled)
573 {
574     if (enabled)
575     {
576         /* dump the application layer */
577         output_flags |= OUTPUT_FLAG__APP_DATA;
578     }
579     else
580         output_flags &= ~OUTPUT_FLAG__APP_DATA;
581 }
582 
set_dump_payload_verbose(bool enabled)583 void SnortConfig::set_dump_payload_verbose(bool enabled)
584 {
585     if (enabled)
586     {
587         output_flags |= OUTPUT_FLAG__VERBOSE_DUMP;
588     }
589     else
590         output_flags &= ~OUTPUT_FLAG__VERBOSE_DUMP;
591 }
592 
set_dst_mac(const char * mac_addr)593 void SnortConfig::set_dst_mac(const char* mac_addr)
594 {
595     if (mac_addr)
596     {
597         eth_addr_t dst;
598 
599         if (eth_pton(mac_addr, &dst) < 0)
600         {
601             ParseError("Format check failed: %s,  Use format like 12:34:56:78:90:1a", mac_addr);
602             return;
603         }
604         snort_free(eth_dst);
605         eth_dst = (uint8_t*)snort_calloc(sizeof(dst.data));
606         memcpy(eth_dst, dst.data, sizeof(dst.data));
607     }
608     else
609     {
610         snort_free(eth_dst);
611         eth_dst = nullptr;
612     }
613 }
614 
set_log_dir(const char * directory)615 void SnortConfig::set_log_dir(const char* directory)
616 {
617     if (directory)
618         log_dir = directory;
619     else
620         log_dir.clear();
621 }
622 
set_dirty_pig(bool enabled)623 void SnortConfig::set_dirty_pig(bool enabled)
624 {
625     dirty_pig = enabled;
626 }
627 
set_obfuscate(bool enabled)628 void SnortConfig::set_obfuscate(bool enabled)
629 {
630     if (enabled)
631         output_flags |= OUTPUT_FLAG__OBFUSCATE;
632     else
633         output_flags &= ~OUTPUT_FLAG__OBFUSCATE;
634 }
635 
set_no_logging_timestamps(bool enabled)636 void SnortConfig::set_no_logging_timestamps(bool enabled)
637 {
638     if (enabled)
639         output_flags |= OUTPUT_FLAG__NO_TIMESTAMP;
640     else
641         output_flags &= ~OUTPUT_FLAG__NO_TIMESTAMP;
642 }
643 
set_obfuscation_mask(const char * mask)644 void SnortConfig::set_obfuscation_mask(const char* mask)
645 {
646     if (!mask)
647         return;
648 
649     output_flags |= OUTPUT_FLAG__OBFUSCATE;
650 
651     obfuscation_net.set(mask);
652 }
653 
set_rule_db_dir(const char * directory)654 void SnortConfig::set_rule_db_dir(const char* directory)
655 {
656     assert(directory);
657     rule_db_dir = directory;
658 }
659 
set_gid(const char * args)660 void SnortConfig::set_gid(const char* args)
661 {
662     struct group* gr;
663     long target_gid;
664     char* endptr;
665 
666     if (!args)
667         return;
668 
669     target_gid = SnortStrtol(args, &endptr, 10);
670     if (*endptr != '\0')
671         gr = getgrnam(args); // main thread only
672     else if (errno == ERANGE || target_gid < 0)
673     {
674         ParseError("group id '%s' out of range.", args);
675         return;
676     }
677     else
678         gr = getgrgid((gid_t)target_gid);  // main thread only
679 
680     if (!gr)
681     {
682         ParseError("group '%s' unknown.", args);
683         return;
684     }
685 
686     /* If we're already running as the desired group ID, don't bother to try changing it later. */
687     if (gr->gr_gid != getgid())
688         group_id = (int)gr->gr_gid;
689 }
690 
set_uid(const char * args)691 void SnortConfig::set_uid(const char* args)
692 {
693     struct passwd* pw;
694     long target_uid;
695     char* endptr;
696 
697     if (!args)
698         return;
699 
700     target_uid = SnortStrtol(args, &endptr, 10);
701     if (*endptr != '\0')
702         pw = getpwnam(args); // main thread only
703     else if (errno == ERANGE || target_uid < 0)
704     {
705         ParseError("user id '%s' out of range.", args);
706         return;
707     }
708     else
709         pw = getpwuid((uid_t)target_uid);  // main thread only
710 
711     if (!pw)
712     {
713         ParseError("user '%s' unknown.", args);
714         return;
715     }
716 
717     /* Set group ID to user's default group if not already set.
718        If we're already running as the desired user and/or group ID,
719        don't bother to try changing it later. */
720     if (pw->pw_uid != getuid())
721         user_id = (int)pw->pw_uid;
722 
723     if (group_id == -1 && pw->pw_gid != getgid())
724         group_id = (int)pw->pw_gid;
725 }
726 
set_show_year(bool enabled)727 void SnortConfig::set_show_year(bool enabled)
728 {
729     if (enabled)
730     {
731         output_flags |= OUTPUT_FLAG__INCLUDE_YEAR;
732     }
733     else
734         output_flags &= ~OUTPUT_FLAG__INCLUDE_YEAR;
735 }
736 
set_process_all_events(bool enabled)737 void SnortConfig::set_process_all_events(bool enabled)
738 {
739     if (enabled)
740         run_flags |= RUN_FLAG__PROCESS_ALL_EVENTS;
741     else
742         run_flags &= ~RUN_FLAG__PROCESS_ALL_EVENTS;
743 }
744 
745 #ifdef ACCESSPERMS
746 # define FILE_ACCESS_BITS ACCESSPERMS
747 #else
748 # ifdef S_IAMB
749 #  define FILE_ACCESS_BITS S_IAMB
750 # else
751 #  define FILE_ACCESS_BITS 0x1FF
752 # endif
753 #endif
754 
set_umask(uint32_t mask)755 void SnortConfig::set_umask(uint32_t mask)
756 {
757     file_mask = (mode_t)mask;
758 }
759 
set_utc(bool enabled)760 void SnortConfig::set_utc(bool enabled)
761 {
762     if (enabled)
763         output_flags |= OUTPUT_FLAG__USE_UTC;
764     else
765         output_flags &= ~OUTPUT_FLAG__USE_UTC;
766 }
767 
set_overlay_trace_config(TraceConfig * tc)768 void SnortConfig::set_overlay_trace_config(TraceConfig* tc)
769 {
770     delete overlay_trace_config;
771     overlay_trace_config = tc;
772 }
773 
set_latency_enable()774 bool SnortConfig::set_latency_enable()
775 {
776     if (latency)
777     {
778         latency->packet_latency.force_enable = true;
779         return true;
780     }
781     return false;
782 }
783 
set_tunnel_verdicts(const char * args)784 void SnortConfig::set_tunnel_verdicts(const char* args)
785 {
786     char* tmp, * tok;
787 
788     tmp = snort_strdup(args);
789     char* lasts = nullptr;
790     tok = strtok_r(tmp, " ,", &lasts);
791 
792     while (tok)
793     {
794         if (!strcasecmp(tok, "gtp"))
795             tunnel_mask |= TUNNEL_GTP;
796 
797         else if (!strcasecmp(tok, "teredo"))
798             tunnel_mask |= TUNNEL_TEREDO;
799 
800         else if (!strcasecmp(tok, "vxlan"))
801             tunnel_mask |= TUNNEL_VXLAN;
802 
803         else if (!strcasecmp(tok, "6in4"))
804             tunnel_mask |= TUNNEL_6IN4;
805 
806         else if (!strcasecmp(tok, "4in6"))
807             tunnel_mask |= TUNNEL_4IN6;
808 
809         else if (!strcasecmp(tok, "4in4"))
810             tunnel_mask |= TUNNEL_4IN4;
811 
812         else if (!strcasecmp(tok, "6in6"))
813             tunnel_mask |= TUNNEL_6IN6;
814 
815         else if (!strcasecmp(tok, "gre"))
816             tunnel_mask |= TUNNEL_GRE;
817 
818         else if (!strcasecmp(tok, "mpls"))
819             tunnel_mask |= TUNNEL_MPLS;
820 
821         else if (!strcasecmp(tok, "geneve"))
822             tunnel_mask |= TUNNEL_GENEVE;
823 
824         else
825         {
826             ParseError("unknown tunnel bypass protocol");
827             return;
828         }
829 
830         tok = strtok_r(nullptr, " ,", &lasts);
831     }
832     snort_free(tmp);
833 }
834 
set_include_path(const char * path)835 void SnortConfig::set_include_path(const char* path)
836 {
837     if (path)
838         include_path = path;
839     else
840         include_path.clear();
841 }
842 
add_plugin_path(const char * path)843 void SnortConfig::add_plugin_path(const char* path)
844 {
845     if (!path)
846         return;
847 
848     if (!plugin_path.empty())
849         plugin_path += ":" + std::string(path);
850     else
851         plugin_path = path;
852 }
853 
set_tweaks(const char * t)854 void SnortConfig::set_tweaks(const char* t)
855 {
856     if (t)
857         tweaks = t;
858     else
859         tweaks.clear();
860 }
861 
add_script_path(const char * path)862 void SnortConfig::add_script_path(const char* path)
863 {
864     if (path)
865         script_paths.emplace_back(path);
866 }
867 
set_alert_mode(const char * val)868 void SnortConfig::set_alert_mode(const char* val)
869 {
870     if (strcasecmp(val, ALERT_NONE) == 0)
871         EventManager::enable_alerts(false);
872 
873     else if ( !strcasecmp(val, ALERT_CMG) or !strcasecmp(val, ALERT_JH) or
874         !strcasecmp(val, ALERT_DJR) )
875     {
876         output = OUTPUT_FAST;
877         output_flags |= OUTPUT_FLAG__SHOW_DATA_LINK;
878         output_flags |= OUTPUT_FLAG__APP_DATA;
879     }
880     else if ( !strcasecmp(val, ALERT_U2) or !strcasecmp(val, ALERT_AJK) )
881         output = OUTPUT_U2;
882 
883     else
884         output = val;
885 
886     output_flags |= OUTPUT_FLAG__ALERTS;
887     Analyzer::set_main_hook(DetectionEngine::inspect);
888 }
889 
set_log_mode(const char * val)890 void SnortConfig::set_log_mode(const char* val)
891 {
892     if (strcasecmp(val, LOG_NONE) == 0)
893     {
894         Analyzer::set_main_hook(snort_ignore);
895         EventManager::enable_logs(false);
896     }
897     else
898     {
899         if ( !strcmp(val, LOG_DUMP) )
900             val = LOG_CODECS;
901         output = val;
902         Analyzer::set_main_hook(snort_log);
903     }
904 }
905 
enable_syslog()906 void SnortConfig::enable_syslog()
907 {
908     static bool syslog_configured = false;
909 
910     if (syslog_configured)
911         return;
912 
913     openlog("snort", LOG_PID | LOG_CONS, LOG_DAEMON);
914 
915     enable_log_syslog();
916     syslog_configured = true;
917 }
918 
get_default_rule_state() const919 bool SnortConfig::get_default_rule_state() const
920 {
921     switch ( get_ips_policy()->default_rule_state )
922     {
923     case IpsPolicy::INHERIT_ENABLE:
924         return global_default_rule_state;
925 
926     case IpsPolicy::ENABLED:
927         return true;
928 
929     case IpsPolicy::DISABLED:
930         return false;
931     }
932     return true;
933 }
934 
create_config_output() const935 ConfigOutput* SnortConfig::create_config_output() const
936 {
937     ConfigOutput* output = nullptr;
938 
939     switch (dump_config_type)
940     {
941     case DUMP_CONFIG_JSON_ALL:
942         output = new JsonAllConfigOutput();
943         break;
944     case DUMP_CONFIG_JSON_TOP:
945         output = new JsonTopConfigOutput();
946         break;
947     case DUMP_CONFIG_TEXT:
948         output = new TextConfigOutput();
949         break;
950     default:
951         break;
952     }
953 
954     return output;
955 }
956 
tunnel_bypass_enabled(uint16_t proto) const957 bool SnortConfig::tunnel_bypass_enabled(uint16_t proto) const
958 {
959     return !((tunnel_mask & proto) or SFDAQ::get_tunnel_bypass(proto));
960 }
961 
request_scratch(ScratchAllocator * s)962 int SnortConfig::request_scratch(ScratchAllocator* s)
963 {
964     scratch_handlers.emplace_back(s);
965 
966     // We return an index that the caller uses to reference their per thread
967     // scratch space
968     return scratch_handlers.size() - 1;
969 }
970 
release_scratch(int id)971 void SnortConfig::release_scratch(int id)
972 {
973     assert((unsigned)id < scratch_handlers.size());
974     scratch_handlers[id] = nullptr;
975 }
976 
get_main_conf()977 SnortConfig* SnortConfig::get_main_conf()
978 { return const_cast<SnortConfig*>(snort_conf); }
979 
get_conf()980 const SnortConfig* SnortConfig::get_conf()
981 { return snort_conf; }
982 
set_conf(const SnortConfig * sc)983 void SnortConfig::set_conf(const SnortConfig* sc)
984 {
985     snort_conf = sc;
986 
987     if ( sc )
988     {
989         Shell* sh = sc->policy_map->get_shell(0);
990         if (sc->policy_map->get_policies(sh))
991             set_policies(sc, sh);
992     }
993 }
994 
register_reload_resource_tuner(ReloadResourceTuner * rrt)995 void SnortConfig::register_reload_resource_tuner(ReloadResourceTuner* rrt)
996 {
997     if (Snort::is_reloading())
998         reload_tuners.push_back(rrt);
999     else
1000         delete rrt;
1001 }
1002 
clear_reload_resource_tuner_list()1003 void SnortConfig::clear_reload_resource_tuner_list()
1004 {
1005     for (ReloadResourceTuner* rrt : reload_tuners)
1006         delete rrt;
1007     reload_tuners.clear();
1008 }
1009 
update_reload_id()1010 void SnortConfig::update_reload_id()
1011 {
1012     static unsigned reload_id_tracker = 0;
1013     reload_id = ++reload_id_tracker;
1014 }
1015 
cleanup_fatal_error()1016 void SnortConfig::cleanup_fatal_error()
1017 {
1018     // FIXIT-L need a generic way to manage type other threads
1019     // and preferably not start them too soon
1020     FileService::close();
1021 
1022 #ifdef REG_TEST
1023     const SnortConfig* sc = SnortConfig::get_conf();
1024     if ( sc && !sc->dirty_pig )
1025     {
1026         ModuleManager::term();
1027         EventManager::release_plugins();
1028         IpsManager::release_plugins();
1029         InspectorManager::release_plugins();
1030     }
1031 #endif
1032 }
1033 
1034