1 /* $Id$ */
2 /*
3 ** Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
4 ** Copyright (C) 2002-2013 Sourcefire, Inc.
5 ** Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>
6 **
7 ** This program is free software; you can redistribute it and/or modify
8 ** it under the terms of the GNU General Public License Version 2 as
9 ** published by the Free Software Foundation. You may not use, modify or
10 ** distribute this program under any other version of the GNU General
11 ** Public License.
12 **
13 ** This program is distributed in the hope that it will be useful,
14 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ** GNU General Public License for more details.
17 **
18 ** You should have received a copy of the GNU General Public License
19 ** along with this program; if not, write to the Free Software
20 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <sys/types.h>
28 #include <unistd.h>
29 #include <stdlib.h>
30 #include <string.h>
31
32 #ifdef HAVE_STRINGS_H
33 #include <strings.h>
34 #endif
35
36 #ifndef WIN32
37 #include <sys/socket.h>
38 #include <netinet/in.h>
39 #include <arpa/inet.h>
40 #endif /* !WIN32 */
41 #include <time.h>
42 #include <errno.h>
43
44 #include "sf_types.h"
45 #include "plugbase.h"
46 #include "spo_plugbase.h"
47 #include "snort.h"
48 #include "snort_debug.h"
49 #include "util.h"
50 #include "log.h"
51 #include "detect.h"
52
53 /* built-in preprocessors */
54 #include "preprocessors/spp_rpc_decode.h"
55 #include "preprocessors/spp_bo.h"
56 #include "preprocessors/spp_session.h"
57 #include "preprocessors/spp_stream6.h"
58 #include "preprocessors/spp_arpspoof.h"
59 #include "preprocessors/spp_perfmonitor.h"
60 #include "preprocessors/spp_httpinspect.h"
61 #include "preprocessors/spp_sfportscan.h"
62 #include "preprocessors/spp_frag3.h"
63 #include "preprocessors/spp_normalize.h"
64
65 /* built-in detection plugins */
66 #include "detection-plugins/sp_pattern_match.h"
67 #include "detection-plugins/sp_tcp_flag_check.h"
68 #include "detection-plugins/sp_icmp_type_check.h"
69 #include "detection-plugins/sp_icmp_code_check.h"
70 #include "detection-plugins/sp_ttl_check.h"
71 #include "detection-plugins/sp_ip_id_check.h"
72 #include "detection-plugins/sp_tcp_ack_check.h"
73 #include "detection-plugins/sp_tcp_seq_check.h"
74 #include "detection-plugins/sp_dsize_check.h"
75 #include "detection-plugins/sp_ipoption_check.h"
76 #include "detection-plugins/sp_rpc_check.h"
77 #include "detection-plugins/sp_icmp_id_check.h"
78 #include "detection-plugins/sp_icmp_seq_check.h"
79 #include "detection-plugins/sp_session.h"
80 #include "detection-plugins/sp_ip_tos_check.h"
81 #include "detection-plugins/sp_ip_fragbits.h"
82 #include "detection-plugins/sp_tcp_win_check.h"
83 #include "detection-plugins/sp_ip_same_check.h"
84 #include "detection-plugins/sp_ip_proto.h"
85 #include "detection-plugins/sp_ip_same_check.h"
86 #include "detection-plugins/sp_clientserver.h"
87 #include "detection-plugins/sp_byte_check.h"
88 #include "detection-plugins/sp_byte_jump.h"
89 #include "detection-plugins/sp_byte_extract.h"
90 #include "detection-plugins/sp_byte_math.h"
91 #include "detection-plugins/sp_isdataat.h"
92 #include "detection-plugins/sp_pcre.h"
93 #include "detection-plugins/sp_flowbits.h"
94 #include "detection-plugins/sp_file_data.h"
95 #include "detection-plugins/sp_base64_decode.h"
96 #include "detection-plugins/sp_base64_data.h"
97 #include "detection-plugins/sp_pkt_data.h"
98 #include "detection-plugins/sp_asn1.h"
99
100 #ifdef ENABLE_REACT
101 #include "detection-plugins/sp_react.h"
102 #endif
103
104 #ifdef ENABLE_RESPOND
105 #include "detection-plugins/sp_respond.h"
106 #endif
107
108 #include "detection-plugins/sp_ftpbounce.h"
109 #include "detection-plugins/sp_urilen_check.h"
110 #include "detection-plugins/sp_cvs.h"
111 #include "detection-plugins/sp_file_type.h"
112
113 #if defined(FEAT_OPEN_APPID)
114 #include "detection-plugins/sp_appid.h"
115 #endif /* defined(FEAT_OPEN_APPID) */
116
117 /* built-in output plugins */
118 #include "output-plugins/spo_alert_syslog.h"
119 #include "output-plugins/spo_log_tcpdump.h"
120 #include "output-plugins/spo_alert_fast.h"
121 #include "output-plugins/spo_alert_full.h"
122 #include "output-plugins/spo_alert_unixsock.h"
123 #include "output-plugins/spo_csv.h"
124 #include "output-plugins/spo_log_null.h"
125 #include "output-plugins/spo_log_ascii.h"
126 #include "output-plugins/spo_unified2.h"
127
128 #ifdef DUMP_BUFFER
129 #include "output-plugins/spo_log_buffer_dump.h"
130 #endif
131
132 #ifdef LINUX
133 #include "output-plugins/spo_alert_sf_socket.h"
134 #endif
135
136 #include "output-plugins/spo_alert_test.h"
137
138 extern ListHead *head_tmp;
139 extern PreprocConfigFuncNode *preproc_config_funcs;
140 extern OutputConfigFuncNode *output_config_funcs;
141 extern RuleOptConfigFuncNode *rule_opt_config_funcs;
142 extern RuleOptOverrideInitFuncNode *rule_opt_override_init_funcs;
143 extern RuleOptParseCleanupNode *rule_opt_parse_cleanup_list;
144 extern RuleOptByteOrderFuncNode *rule_opt_byte_order_funcs;
145 extern PreprocSignalFuncNode *preproc_clean_exit_funcs;
146 extern PreprocSignalFuncNode *preproc_shutdown_funcs;
147 extern PreprocSignalFuncNode *preproc_reset_funcs;
148 extern PreprocSignalFuncNode *preproc_reset_stats_funcs;
149 extern PreprocStatsFuncNode *preproc_stats_funcs;
150 extern PluginSignalFuncNode *plugin_shutdown_funcs;
151 extern PluginSignalFuncNode *plugin_clean_exit_funcs;
152 extern OutputFuncNode *AlertList;
153 extern OutputFuncNode *LogList;
154
155 /**************************** Detection Plugin API ****************************/
156 /* For translation from enum to char* */
157 #ifdef DEBUG_MSGS
158 static const char *optTypeMap[OPT_TYPE_MAX] =
159 {
160 "action",
161 "logging",
162 "detection"
163 };
164
165 #define ENUM2STR(num, map) \
166 ((num < sizeof(map)/sizeof(map[0])) ? map[num] : "undefined")
167 #endif
168
169 static GetHttpXffFieldsFunc getHttpXffFieldsFunc = NULL;
170
RegisterRuleOptions(void)171 void RegisterRuleOptions(void)
172 {
173 LogMessage("Initializing Plug-ins!\n");
174
175 SetupPatternMatch();
176 SetupTCPFlagCheck();
177 SetupIcmpTypeCheck();
178 SetupIcmpCodeCheck();
179 SetupTtlCheck();
180 SetupIpIdCheck();
181 SetupTcpAckCheck();
182 SetupTcpSeqCheck();
183 SetupDsizeCheck();
184 SetupIpOptionCheck();
185 SetupRpcCheck();
186 SetupIcmpIdCheck();
187 SetupIcmpSeqCheck();
188 SetupSession();
189 SetupIpTosCheck();
190 SetupFragBits();
191 SetupFragOffset();
192 SetupTcpWinCheck();
193 SetupIpProto();
194 SetupIpSameCheck();
195 SetupClientServer();
196 SetupPktData();
197 SetupByteTest();
198 SetupByteJump();
199 SetupByteExtract();
200 SetupByteMath();
201 SetupIsDataAt();
202 SetupFileData();
203 SetupBase64Decode();
204 SetupBase64Data();
205 SetupPcre();
206 SetupFlowBits();
207 SetupAsn1();
208 #ifdef ENABLE_REACT
209 SetupReact();
210 #endif
211 #ifdef ENABLE_RESPOND
212 SetupRespond();
213 #endif
214 SetupFTPBounce();
215 SetupUriLenCheck();
216 SetupCvs();
217 SetupFileType();
218 #if defined(FEAT_OPEN_APPID)
219 SetupAppId();
220 #endif /* defined(FEAT_OPEN_APPID) */
221 }
222
223 /****************************************************************************
224 *
225 * Function: RegisterRuleOption(char *, void (*func)(), enum OptionType)
226 *
227 * Purpose: Associates a rule option keyword with an option setup/linking
228 * function.
229 *
230 * Arguments: keyword => The option keyword to associate with the option
231 * handler
232 * *func => function pointer to the handler
233 * type => used to determine where keyword is allowed
234 *
235 * Returns: void function
236 *
237 ***************************************************************************/
RegisterRuleOption(char * opt_name,RuleOptConfigFunc ro_config_func,RuleOptOverrideInitFunc override_init_func,RuleOptType opt_type,RuleOptOtnHandler otn_handler)238 void RegisterRuleOption(char *opt_name, RuleOptConfigFunc ro_config_func,
239 RuleOptOverrideInitFunc override_init_func,
240 RuleOptType opt_type,
241 RuleOptOtnHandler otn_handler)
242 {
243 RuleOptConfigFuncNode *node;
244
245 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Registering keyword:func => %s/%s:%p\n",
246 ENUM2STR(opt_type, optTypeMap), opt_name, ro_config_func););
247
248 node = (RuleOptConfigFuncNode *)SnortAlloc(sizeof(RuleOptConfigFuncNode));
249
250 if (rule_opt_config_funcs == NULL)
251 {
252 rule_opt_config_funcs = node;
253 }
254 else
255 {
256 RuleOptConfigFuncNode *tmp = rule_opt_config_funcs;
257 RuleOptConfigFuncNode *last;
258
259 do
260 {
261 if (strcasecmp(tmp->keyword, opt_name) == 0)
262 {
263 free(node);
264 FatalError("%s(%d) Duplicate detection plugin keyword: %s.\n",
265 file_name, file_line, opt_name);
266 }
267
268 last = tmp;
269 tmp = tmp->next;
270
271 } while (tmp != NULL);
272
273 last->next = node;
274 }
275
276 node->keyword = SnortStrdup(opt_name);
277 node->type = opt_type;
278 node->func = ro_config_func;
279 node->otn_handler = otn_handler;
280
281 if (override_init_func != NULL)
282 {
283 RuleOptOverrideInitFuncNode *node_override =
284 (RuleOptOverrideInitFuncNode *)SnortAlloc(sizeof(RuleOptOverrideInitFuncNode));
285
286 if (rule_opt_override_init_funcs == NULL)
287 {
288 rule_opt_override_init_funcs = node_override;
289 }
290 else
291 {
292 RuleOptOverrideInitFuncNode *tmp = rule_opt_override_init_funcs;
293 RuleOptOverrideInitFuncNode *last;
294
295 do
296 {
297 if (strcasecmp(tmp->keyword, opt_name) == 0)
298 {
299 free(node_override);
300 FatalError("RegisterRuleOption: Duplicate detection plugin keyword:"
301 " (%s) (%s)!\n", tmp->keyword, opt_name);
302 }
303
304 last = tmp;
305 tmp = tmp->next;
306
307 } while (tmp != NULL);
308
309 last->next = node_override;
310 }
311
312 node_override->keyword = SnortStrdup(opt_name);
313 node_override->type = opt_type;
314 node_override->func = override_init_func;
315 node_override->otn_handler = otn_handler;
316 }
317 }
318
RegisterOverrideKeyword(char * keyword,char * option,RuleOptOverrideFunc roo_func)319 void RegisterOverrideKeyword(char *keyword, char *option, RuleOptOverrideFunc roo_func)
320 {
321 RuleOptOverrideInitFuncNode *node = rule_opt_override_init_funcs;
322
323 while (node != NULL)
324 {
325 if (strcasecmp(node->keyword, keyword) == 0)
326 {
327 node->func(keyword, option, roo_func);
328 break;
329 }
330
331 node = node->next;
332 }
333 }
334
RegisterByteOrderKeyword(char * keyword,RuleOptByteOrderFunc roo_func)335 void RegisterByteOrderKeyword(char *keyword, RuleOptByteOrderFunc roo_func)
336 {
337 RuleOptByteOrderFuncNode *node = (RuleOptByteOrderFuncNode *)SnortAlloc(sizeof(RuleOptByteOrderFuncNode));
338 RuleOptByteOrderFuncNode *list = rule_opt_byte_order_funcs;
339 RuleOptByteOrderFuncNode *last;
340
341 node->keyword = SnortStrdup(keyword);
342 node->func = roo_func;
343 node->next = NULL;
344
345 if (list == NULL)
346 rule_opt_byte_order_funcs = node;
347 else
348 {
349 while (list != NULL)
350 {
351 if (strcasecmp(node->keyword, list->keyword) == 0)
352 {
353 free(node->keyword);
354 free(node);
355 return;
356 }
357
358 last = list;
359 list = list->next;
360 }
361
362 last->next = node;
363 }
364 }
365
GetByteOrderFunc(char * keyword)366 RuleOptByteOrderFunc GetByteOrderFunc(char *keyword)
367 {
368 RuleOptByteOrderFuncNode *node = rule_opt_byte_order_funcs;
369
370 while (node != NULL)
371 {
372 if (strcasecmp(keyword, node->keyword) == 0)
373 return node->func;
374
375 node = node->next;
376 }
377
378 return NULL;
379 }
380
381 /****************************************************************************
382 *
383 * Function: DumpPlugIns()
384 *
385 * Purpose: Prints the keyword->function list
386 *
387 * Arguments: None.
388 *
389 * Returns: void function
390 *
391 ***************************************************************************/
DumpRuleOptions(void)392 void DumpRuleOptions(void)
393 {
394 RuleOptConfigFuncNode *node;
395
396 node = rule_opt_config_funcs;
397
398 LogMessage("-------------------------------------------------\n");
399 LogMessage(" Keyword | Plugin Registered @\n");
400 LogMessage("-------------------------------------------------\n");
401
402 while (node != NULL)
403 {
404 LogMessage("%-13s: %p\n", node->keyword, (void *)node->vfunc);
405 node = node->next;
406 }
407
408 LogMessage("-------------------------------------------------\n");
409 LogMessage("\n");
410 }
411
412
413 /****************************************************************************
414 *
415 * Function: AddOptFuncToList(int (*func)(), OptTreeNode *)
416 *
417 * Purpose: Links the option detection module to the OTN
418 *
419 * Arguments: (*func)() => function pointer to the detection module
420 * otn => pointer to the current OptTreeNode
421 *
422 * Returns: void function
423 *
424 ***************************************************************************/
AddOptFuncToList(RuleOptEvalFunc ro_eval_func,OptTreeNode * otn)425 OptFpList * AddOptFuncToList(RuleOptEvalFunc ro_eval_func, OptTreeNode *otn)
426 {
427 OptFpList *ofp = (OptFpList *)SnortAlloc(sizeof(OptFpList));
428
429 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Adding new rule to list\n"););
430
431 /* if there are no nodes on the function list... */
432 if (otn->opt_func == NULL)
433 {
434 otn->opt_func = ofp;
435 }
436 else
437 {
438 OptFpList *tmp = otn->opt_func;
439
440 /* walk to the end of the list */
441 while (tmp->next != NULL)
442 tmp = tmp->next;
443
444 tmp->next = ofp;
445 }
446
447 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Set OptTestFunc to %p\n", ro_eval_func););
448
449 ofp->OptTestFunc = ro_eval_func;
450
451 return ofp;
452 }
453
454 /****************************************************************************
455 *
456 * Function: AddRspFuncToList(int (*func)(), OptTreeNode *)
457 *
458 * Purpose: Adds Response function to OTN
459 *
460 * Arguments: (*func)() => function pointer to the response module
461 * otn => pointer to the current OptTreeNode
462 *
463 * Returns: void function
464 *
465 ***************************************************************************/
466 // TBD this can prolly be replaced with a single item
467 // because we allow at most one response per packet
AddRspFuncToList(ResponseFunc resp_func,OptTreeNode * otn,void * params)468 void AddRspFuncToList(ResponseFunc resp_func, OptTreeNode *otn, void *params)
469 {
470 RspFpList *rsp = (RspFpList *)SnortAlloc(sizeof(RspFpList));
471
472 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Adding response to list\n"););
473
474 /* if there are no nodes on the function list... */
475 if (otn->rsp_func == NULL)
476 {
477 otn->rsp_func = rsp;
478 }
479 else
480 {
481 RspFpList *tmp = otn->rsp_func;
482
483 /* walk to the end of the list */
484 while (tmp->next != NULL)
485 tmp = tmp->next;
486
487 tmp->next = rsp;
488 }
489
490 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Set ResponseFunc to %p\n", resp_func););
491
492 rsp->func = resp_func;
493 rsp->params = params;
494 }
495
PostConfigInitPlugins(struct _SnortConfig * sc,PostConfigFuncNode * post_config_funcs)496 void PostConfigInitPlugins(struct _SnortConfig *sc, PostConfigFuncNode *post_config_funcs)
497 {
498 while (post_config_funcs != NULL)
499 {
500 post_config_funcs->func(sc, 0, post_config_funcs->arg);
501 post_config_funcs = post_config_funcs->next;
502 }
503 }
504
FreeRuleOptConfigFuncs(RuleOptConfigFuncNode * head)505 void FreeRuleOptConfigFuncs(RuleOptConfigFuncNode *head)
506 {
507
508 while (head != NULL)
509 {
510 RuleOptConfigFuncNode *tmp = head;
511
512 head = head->next;
513
514 if (tmp->keyword != NULL)
515 free(tmp->keyword);
516
517 free(tmp);
518 }
519 }
520
FreeRuleOptOverrideInitFuncs(RuleOptOverrideInitFuncNode * head)521 void FreeRuleOptOverrideInitFuncs(RuleOptOverrideInitFuncNode *head)
522 {
523
524 while (head != NULL)
525 {
526 RuleOptOverrideInitFuncNode *tmp = head;
527
528 head = head->next;
529
530 if (tmp->keyword != NULL)
531 free(tmp->keyword);
532
533 free(tmp);
534 }
535 }
536
FreeRuleOptByteOrderFuncs(RuleOptByteOrderFuncNode * head)537 void FreeRuleOptByteOrderFuncs(RuleOptByteOrderFuncNode *head)
538 {
539 while (head != NULL)
540 {
541 RuleOptByteOrderFuncNode *tmp = head;
542
543 head = head->next;
544
545 if (tmp->keyword != NULL)
546 free(tmp->keyword);
547
548 free(tmp);
549 }
550 }
551
FreePluginSigFuncs(PluginSignalFuncNode * head)552 void FreePluginSigFuncs(PluginSignalFuncNode *head)
553 {
554 while (head != NULL)
555 {
556 PluginSignalFuncNode *tmp = head;
557
558 head = head->next;
559
560 /* don't free sig->arg, that's free'd by the CleanExit func */
561 free(tmp);
562 }
563 }
564
FreePluginPostConfigFuncs(PostConfigFuncNode * head)565 void FreePluginPostConfigFuncs(PostConfigFuncNode *head)
566 {
567 while (head != NULL)
568 {
569 PostConfigFuncNode *tmp = head;
570
571 head = head->next;
572
573 /* don't free sig->arg, that's free'd by the CleanExit func */
574 free(tmp);
575 }
576 }
577
578 /************************** Non Rule Detection Plugin API *********************/
AddFuncToDetectionList(SnortConfig * sc,DetectionEvalFunc detect_eval_func,uint16_t priority,uint32_t detect_id,uint32_t proto_mask)579 DetectionEvalFuncNode * AddFuncToDetectionList(SnortConfig *sc,
580 DetectionEvalFunc detect_eval_func,
581 uint16_t priority, uint32_t detect_id,
582 uint32_t proto_mask)
583 {
584 DetectionEvalFuncNode *node;
585 tSfPolicyId policy_id = getParserPolicy(sc);
586 SnortPolicy *p;
587
588 if (sc == NULL)
589 {
590 FatalError("%s(%d) Snort config for parsing is NULL.\n",
591 __FILE__, __LINE__);
592 }
593
594 p = sc->targeted_policies[policy_id];
595 if (p == NULL)
596 return NULL;
597
598 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,
599 "Adding detection function ID %d/bit %d/pri %d to list\n",
600 detect_id, p->num_detects, priority););
601
602 node = (DetectionEvalFuncNode *)SnortAlloc(sizeof(DetectionEvalFuncNode));
603
604 if (p->detect_eval_funcs == NULL)
605 {
606 p->detect_eval_funcs = node;
607 }
608 else
609 {
610 DetectionEvalFuncNode *tmp = p->detect_eval_funcs;
611 DetectionEvalFuncNode *last = NULL;
612
613 do
614 {
615 if (tmp->detect_id == detect_id)
616 {
617 free(node);
618 FatalError("Detection function already registered with ID %d\n",
619 detect_id);
620 }
621
622 /* Insert higher priority preprocessors first. Lower priority
623 * number means higher priority */
624 if (priority < tmp->priority)
625 break;
626
627 last = tmp;
628 tmp = tmp->next;
629
630 } while (tmp != NULL);
631
632 /* Priority higher than first item in list */
633 if (last == NULL)
634 {
635 node->next = tmp;
636 p->detect_eval_funcs = node;
637 }
638 else
639 {
640 node->next = tmp;
641 last->next = node;
642 }
643 }
644
645 node->func = detect_eval_func;
646 node->priority = priority;
647 node->detect_id = detect_id;
648 //node->detect_bit = (1 << detect_id);
649 node->proto_mask = proto_mask;
650
651 p->num_detects++;
652 p->detect_proto_mask |= proto_mask;
653 //p->detect_bit_mask |= node->detect_bit;
654
655 return node;
656 }
657
FreeDetectionEvalFuncs(DetectionEvalFuncNode * head)658 void FreeDetectionEvalFuncs(DetectionEvalFuncNode *head)
659 {
660 DetectionEvalFuncNode *tmp;
661
662 while (head != NULL)
663 {
664 tmp = head->next;
665 //if (head->context)
666 // free(head->context);
667 free(head);
668 head = tmp;
669 }
670 }
671
672 /************************** Buffer Dump Plugin API ***************************/
673 #ifdef DUMP_BUFFER
RegisterBufferTracer(TraceBuffer * (* bdfunc)(),BUFFER_DUMP_FUNC type)674 void RegisterBufferTracer(TraceBuffer *(*bdfunc)(), BUFFER_DUMP_FUNC type)
675 {
676 getBuffers[type] = bdfunc;
677 bdmask |= (UINT64_C(1) << type);
678 }
679 #endif
680
681 /************************** Preprocessor Plugin API ***************************/
682 static void AddFuncToPreprocSignalList(PreprocSignalFunc, void *,
683 PreprocSignalFuncNode **, uint16_t, uint32_t);
684
685
RegisterPreprocessors(void)686 void RegisterPreprocessors(void)
687 {
688 LogMessage("Initializing Preprocessors!\n");
689
690 SetupARPspoof();
691 #ifdef NORMALIZER
692 SetupNormalizer();
693 #endif
694 SetupFrag3();
695 SetupSessionManager();
696 SetupStream6();
697 SetupRpcDecode();
698 SetupBo();
699 SetupHttpInspect();
700 SetupPerfMonitor();
701 SetupSfPortscan();
702 }
703
704 /****************************************************************************
705 *
706 * Function: RegisterPreprocessor(char *, void (*)(char *))
707 *
708 * Purpose: Associates a preprocessor statement with its function.
709 *
710 * Arguments: keyword => The option keyword to associate with the
711 * preprocessor
712 * *func => function pointer to the handler
713 *
714 * Returns: void function
715 *
716 ***************************************************************************/
717 #ifndef SNORT_RELOAD
RegisterPreprocessor(const char * keyword,PreprocConfigFunc pp_config_func)718 void RegisterPreprocessor(const char *keyword, PreprocConfigFunc pp_config_func)
719 #else
720 void RegisterPreprocessor(const char *keyword, PreprocConfigFunc pp_config_func,
721 PreprocReloadFunc rfunc, PreprocReloadVerifyFunc rvfunc,
722 PreprocReloadSwapFunc sfunc, PreprocReloadSwapFreeFunc ffunc)
723 #endif
724 {
725 PreprocConfigFuncNode *node =
726 (PreprocConfigFuncNode *)SnortAlloc(sizeof(PreprocConfigFuncNode));
727
728 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Registering keyword:preproc => %s:%p\n", keyword, pp_config_func););
729
730 if (preproc_config_funcs == NULL)
731 {
732 preproc_config_funcs = node;
733 }
734 else
735 {
736 PreprocConfigFuncNode *tmp = preproc_config_funcs;
737 PreprocConfigFuncNode *last;
738
739 do
740 {
741 if (strcasecmp(tmp->keyword, keyword) == 0)
742 {
743 free(node);
744 FatalError("Duplicate preprocessor keyword: %s.\n", keyword);
745 }
746
747 last = tmp;
748 tmp = tmp->next;
749
750 } while (tmp != NULL);
751
752 last->next = node;
753 }
754
755 node->keyword = SnortStrdup(keyword);
756 node->config_func = pp_config_func;
757
758 #ifdef SNORT_RELOAD
759 node->reload_func = rfunc;
760 node->reload_verify_func = rvfunc;
761 node->reload_swap_func = sfunc;
762 node->reload_swap_free_func = ffunc;
763 #endif
764 }
765
766 #ifdef SNORT_RELOAD
GetRelatedReloadData(SnortConfig * sc,const char * keyword)767 void *GetRelatedReloadData(SnortConfig *sc, const char *keyword)
768 {
769 PreprocessorSwapData *swapData;
770 for (swapData = sc->preprocSwapData; swapData; swapData = swapData->next)
771 {
772 if (swapData->preprocNode && swapData->preprocNode->keyword &&
773 strcasecmp(swapData->preprocNode->keyword, keyword) == 0)
774 {
775 return swapData->data;
776 }
777 }
778 return NULL;
779 }
780
GetReloadStreamConfig(SnortConfig * sc)781 void *GetReloadStreamConfig(SnortConfig *sc)
782 {
783 return sc->streamReloadConfig;
784 }
785 #endif
786
GetPreprocConfig(char * keyword)787 PreprocConfigFuncNode * GetPreprocConfig(char *keyword)
788 {
789 PreprocConfigFuncNode *head = preproc_config_funcs;
790
791 if (keyword == NULL)
792 return NULL;
793
794 while (head != NULL)
795 {
796 if (strcasecmp(head->keyword, keyword) == 0)
797 return head;
798
799 head = head->next;
800 }
801
802 return NULL;
803 }
804
GetPreprocConfigFunc(char * keyword)805 PreprocConfigFunc GetPreprocConfigFunc(char *keyword)
806 {
807 PreprocConfigFuncNode *head = preproc_config_funcs;
808
809 if (keyword == NULL)
810 return NULL;
811
812 while (head != NULL)
813 {
814 if (strcasecmp(head->keyword, keyword) == 0)
815 return head->config_func;
816
817 head = head->next;
818 }
819
820 return NULL;
821 }
822
823 /****************************************************************************
824 *
825 * Function: RegisterPreprocStats(char *keyword, void (*func)(int))
826 *
827 * Purpose: Registers a function for printing preprocessor final stats
828 * (or other if it has a use for printing final stats)
829 *
830 * Arguments: keyword => keyword (preprocessor) whose stats will print
831 * func => function pointer to the handler
832 *
833 * Returns: void function
834 *
835 ***************************************************************************/
RegisterPreprocStats(const char * keyword,PreprocStatsFunc pp_stats_func)836 void RegisterPreprocStats(const char *keyword, PreprocStatsFunc pp_stats_func)
837 {
838 PreprocStatsFuncNode *node;
839
840 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Registering final stats function: "
841 "preproc => %s:%p\n", keyword, pp_stats_func););
842
843 node = (PreprocStatsFuncNode *)SnortAlloc(sizeof(PreprocStatsFuncNode));
844
845 if (preproc_stats_funcs == NULL)
846 {
847 preproc_stats_funcs = node;
848 }
849 else
850 {
851 PreprocStatsFuncNode *tmp = preproc_stats_funcs;
852 PreprocStatsFuncNode *last;
853
854 do
855 {
856 if (strcasecmp(tmp->keyword, keyword) == 0)
857 {
858 free(node);
859 FatalError("Duplicate preprocessor keyword: %s.\n", keyword);
860 }
861
862 last = tmp;
863 tmp = tmp->next;
864
865 } while (tmp != NULL);
866
867 last->next = node;
868 }
869
870 node->keyword = SnortStrdup(keyword);
871 node->func = pp_stats_func;
872 }
873
874 /****************************************************************************
875 *
876 * Function: DumpPreprocessors()
877 *
878 * Purpose: Prints the keyword->preprocess list
879 *
880 * Arguments: None.
881 *
882 * Returns: void function
883 *
884 ***************************************************************************/
DumpPreprocessors(void)885 void DumpPreprocessors(void)
886 {
887 PreprocConfigFuncNode *node = preproc_config_funcs;
888
889 LogMessage("-------------------------------------------------\n");
890 LogMessage(" Keyword | Preprocessor @ \n");
891 LogMessage("-------------------------------------------------\n");
892
893 while (node != NULL)
894 {
895 LogMessage("%-13s: %p\n", node->keyword, node->config_vfunc);
896 node = node->next;
897 }
898
899 LogMessage("-------------------------------------------------\n\n");
900 }
901
IsPreprocEnabled(SnortConfig * sc,uint32_t preproc_id)902 int IsPreprocEnabled(SnortConfig *sc, uint32_t preproc_id)
903 {
904 PreprocEvalFuncNode *node;
905 tSfPolicyId policy_id = getParserPolicy(sc);
906 SnortPolicy *p;
907
908 if (sc == NULL)
909 {
910 FatalError("%s(%d) Snort config for parsing is NULL.\n",
911 __FILE__, __LINE__);
912 }
913
914 p = sc->targeted_policies[policy_id];
915 if (p == NULL)
916 return 0;
917
918 for (node = p->preproc_eval_funcs; node != NULL; node = node->next)
919 {
920 if (node->preproc_id == preproc_id)
921 return 1;
922 }
923
924 return 0;
925 }
926
AddFuncToPreprocList(SnortConfig * sc,PreprocEvalFunc pp_eval_func,uint16_t priority,uint32_t preproc_id,uint32_t proto_mask)927 PreprocEvalFuncNode * AddFuncToPreprocList(SnortConfig *sc, PreprocEvalFunc pp_eval_func, uint16_t priority,
928 uint32_t preproc_id, uint32_t proto_mask)
929 {
930 PreprocEvalFuncNode *node;
931 tSfPolicyId policy_id = getParserPolicy(sc);
932 SnortPolicy *p;
933
934 if (sc == NULL)
935 {
936 FatalError("%s(%d) Snort config for parsing is NULL.\n",
937 __FILE__, __LINE__);
938 }
939
940 p = sc->targeted_policies[policy_id];
941 if (p == NULL)
942 return NULL;
943
944 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,
945 "Adding preprocessor function ID %d/bit %d/pri %d to list\n",
946 preproc_id, p->num_preprocs, priority););
947
948 node = (PreprocEvalFuncNode *)SnortAlloc(sizeof(PreprocEvalFuncNode));
949
950 if (p->preproc_eval_funcs == NULL)
951 {
952 p->preproc_eval_funcs = node;
953 }
954 else
955 {
956 PreprocEvalFuncNode *tmp = p->preproc_eval_funcs;
957 PreprocEvalFuncNode *last = NULL;
958
959 do
960 {
961 if (tmp->preproc_id == preproc_id)
962 {
963 free(node);
964 FatalError("Preprocessor already registered with ID %d\n",
965 preproc_id);
966 }
967
968 /* Insert higher priority preprocessors first. Lower priority
969 * number means higher priority */
970 if (priority < tmp->priority)
971 break;
972
973 last = tmp;
974 tmp = tmp->next;
975
976 } while (tmp != NULL);
977
978 /* Priority higher than first item in list */
979 if (last == NULL)
980 {
981 node->next = tmp;
982 p->preproc_eval_funcs = node;
983 }
984 else
985 {
986 node->next = tmp;
987 last->next = node;
988 }
989 }
990
991 node->func = pp_eval_func;
992 node->priority = priority;
993 node->preproc_id = preproc_id;
994 node->preproc_bit = (UINT64_C(1) << preproc_id);
995 node->proto_mask = proto_mask;
996
997 p->num_preprocs++;
998 p->preproc_proto_mask |= proto_mask;
999 p->preproc_bit_mask |= node->preproc_bit;
1000
1001 return node;
1002 }
1003
AddFuncToPreprocListAllNapPolicies(struct _SnortConfig * sc,PreprocEvalFunc pp_eval_func,uint16_t priority,uint32_t preproc_id,uint32_t proto_mask)1004 void AddFuncToPreprocListAllNapPolicies(struct _SnortConfig *sc, PreprocEvalFunc pp_eval_func, uint16_t priority,
1005 uint32_t preproc_id, uint32_t proto_mask)
1006 {
1007 tSfPolicyId save_policy_id = getParserPolicy( sc );
1008 uint32_t i;
1009
1010 if (sc == NULL)
1011 FatalError("%s(%d) Snort config for parsing is NULL.\n", __FILE__, __LINE__);
1012
1013 // preprocs are only registered in NAP policies so if num_prerocs > 0 then policy is NAP, this works here
1014 // because this func is always called after all policies have been parsed and preprocs configured per policy
1015 // have already registered...
1016 for( i = 0; i < sc->num_policies_allocated; i++ )
1017 if( ( sc->targeted_policies[ i ] != NULL ) && ( sc->targeted_policies[ i ]->num_preprocs > 0 ) )
1018 {
1019 setParserPolicy( sc, i );
1020 AddFuncToPreprocList( sc, pp_eval_func, priority, preproc_id, proto_mask );
1021 }
1022
1023 setParserPolicy( sc, save_policy_id );
1024 }
1025
1026
AddFuncToPreprocMetaEvalList(SnortConfig * sc,PreprocMetaEvalFunc pp_meta_eval_func,uint16_t priority,uint32_t preproc_id)1027 PreprocMetaEvalFuncNode * AddFuncToPreprocMetaEvalList(
1028 SnortConfig *sc,
1029 PreprocMetaEvalFunc pp_meta_eval_func,
1030 uint16_t priority,
1031 uint32_t preproc_id)
1032 {
1033 PreprocMetaEvalFuncNode *node;
1034 tSfPolicyId policy_id = getDefaultPolicy( );
1035 SnortPolicy *p;
1036
1037 if (sc == NULL)
1038 {
1039 FatalError("%s(%d) Snort config for parsing is NULL.\n",
1040 __FILE__, __LINE__);
1041 }
1042
1043 #ifndef HAVE_DAQ_ACQUIRE_WITH_META
1044 WarningMessage("Metadata not available for processing. Not registering Preprocessor Meta Eval id %d\n", preproc_id);
1045 return NULL; // Not supported
1046 #endif
1047
1048 p = sc->targeted_policies[policy_id];
1049 if (p == NULL)
1050 return NULL;
1051
1052 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,
1053 "Adding preprocessor function ID %d/bit %d/pri %d to list\n",
1054 preproc_id, p->num_preprocs, priority););
1055
1056 node = (PreprocMetaEvalFuncNode *)SnortAlloc(sizeof(PreprocMetaEvalFuncNode));
1057
1058 if (p->preproc_meta_eval_funcs == NULL)
1059 {
1060 p->preproc_meta_eval_funcs = node;
1061 SetupMetadataCallback();
1062 }
1063 else
1064 {
1065 PreprocMetaEvalFuncNode *tmp = p->preproc_meta_eval_funcs;
1066 PreprocMetaEvalFuncNode *last = NULL;
1067
1068 do
1069 {
1070 if (tmp->preproc_id == preproc_id)
1071 {
1072 free(node);
1073 FatalError("Preprocessor Meta Eval already registered with ID %d\n",
1074 preproc_id);
1075 }
1076
1077 /* Insert higher priority preprocessors first. Lower priority
1078 * number means higher priority */
1079 if (priority < tmp->priority)
1080 break;
1081
1082 last = tmp;
1083 tmp = tmp->next;
1084
1085 } while (tmp != NULL);
1086
1087 /* Priority higher than first item in list */
1088 if (last == NULL)
1089 {
1090 node->next = tmp;
1091 p->preproc_meta_eval_funcs = node;
1092 }
1093 else
1094 {
1095 node->next = tmp;
1096 last->next = node;
1097 }
1098 }
1099
1100 node->func = pp_meta_eval_func;
1101 node->priority = priority;
1102 node->preproc_id = preproc_id;
1103 node->preproc_bit = (UINT64_C(1) << preproc_id);
1104
1105 p->num_meta_preprocs++;
1106 p->preproc_meta_bit_mask |= node->preproc_bit;
1107
1108 return node;
1109 }
1110
AddFuncToPreprocPostConfigList(SnortConfig * sc,PreprocPostConfigFunc pp_post_config_func,void * data)1111 void AddFuncToPreprocPostConfigList(SnortConfig *sc, PreprocPostConfigFunc pp_post_config_func,
1112 void *data)
1113 {
1114 PreprocPostConfigFuncNode *node;
1115
1116 if (sc == NULL)
1117 {
1118 FatalError("%s(%d) Snort config for parsing is NULL.\n",
1119 __FILE__, __LINE__);
1120 }
1121
1122 node = (PreprocPostConfigFuncNode *)SnortAlloc(sizeof(PreprocPostConfigFuncNode));
1123
1124 if (sc->preproc_post_config_funcs == NULL)
1125 {
1126 sc->preproc_post_config_funcs = node;
1127 }
1128 else
1129 {
1130 PreprocPostConfigFuncNode *tmp = sc->preproc_post_config_funcs;
1131
1132 while (tmp->next != NULL)
1133 tmp = tmp->next;
1134
1135 tmp->next = node;
1136 }
1137
1138 node->data = data;
1139 node->func = pp_post_config_func;
1140 }
1141
PostConfigPreprocessors(SnortConfig * sc)1142 void PostConfigPreprocessors(SnortConfig *sc)
1143 {
1144 PreprocPostConfigFuncNode *list;
1145
1146 if (sc == NULL)
1147 {
1148 FatalError("%s(%d) Snort config is NULL.\n",
1149 __FILE__, __LINE__);
1150 }
1151
1152 list = sc->preproc_post_config_funcs;
1153
1154 for (; list != NULL; list = list->next)
1155 {
1156 if (list->func != NULL)
1157 list->func(sc, list->data);
1158 }
1159 }
1160
FilterConfigPreprocessors(SnortConfig * sc)1161 void FilterConfigPreprocessors(SnortConfig *sc)
1162 {
1163 tSfPolicyId policy_id;
1164 SnortPolicy *p;
1165 PreprocEvalFuncNode *node;
1166 PreprocEvalFuncNode **list;
1167 PreprocEvalFuncNode **free_list;
1168
1169 if (sc == NULL)
1170 {
1171 ParseError("%s(%d) Snort config is NULL.\n",
1172 __FILE__, __LINE__);
1173 }
1174
1175 if (!sc->disable_all_policies)
1176 return;
1177
1178 policy_id = getParserPolicy(sc);
1179 p = sc->targeted_policies[policy_id];
1180 if (p == NULL)
1181 return;
1182
1183 list = &p->preproc_eval_funcs;
1184 free_list = &p->unused_preproc_eval_funcs;
1185
1186 while ((node = *list) != NULL)
1187 {
1188 if (node->preproc_bit & sc->reenabled_preprocessor_bits)
1189 {
1190 list = &node->next;
1191 }
1192 else
1193 {
1194 *list = node->next;
1195 node->next = NULL;
1196 *free_list = node;
1197 free_list = &node->next;
1198 }
1199 }
1200 }
1201
1202 #ifdef SNORT_RELOAD
SwapPreprocConfigurations(SnortConfig * sc)1203 void SwapPreprocConfigurations(SnortConfig *sc)
1204 {
1205 PreprocessorSwapData *node;
1206 PreprocConfigFuncNode *preproc;
1207
1208 for (node = sc->preprocSwapData; node != NULL; node = node->next)
1209 {
1210 if ((preproc = node->preprocNode) && preproc->reload_swap_func)
1211 node->data = preproc->reload_swap_func(sc, node->data);
1212 }
1213 }
1214
FreeSwappedPreprocConfigurations(struct _SnortConfig * sc)1215 void FreeSwappedPreprocConfigurations(struct _SnortConfig *sc)
1216 {
1217 PreprocessorSwapData *node;
1218 PreprocConfigFuncNode *preproc;
1219
1220 for (node = sc->preprocSwapData; node != NULL; node = node->next)
1221 {
1222 if (node->data && (preproc = node->preprocNode) && preproc->reload_swap_free_func)
1223 {
1224 preproc->reload_swap_free_func(node->data);
1225 node->data = NULL;
1226 }
1227 }
1228 }
1229 #endif
1230
AddFuncToConfigCheckList(SnortConfig * sc,PreprocCheckConfigFunc pp_chk_config_func)1231 void AddFuncToConfigCheckList(SnortConfig *sc, PreprocCheckConfigFunc pp_chk_config_func)
1232 {
1233 PreprocCheckConfigFuncNode *node;
1234
1235 if (sc == NULL)
1236 {
1237 FatalError("%s(%d) Snort config for parsing is NULL.\n",
1238 __FILE__, __LINE__);
1239 }
1240
1241 node = (PreprocCheckConfigFuncNode *)SnortAlloc(sizeof(PreprocCheckConfigFuncNode));
1242
1243 if (sc->preproc_config_check_funcs == NULL)
1244 {
1245 sc->preproc_config_check_funcs = node;
1246 }
1247 else
1248 {
1249 PreprocCheckConfigFuncNode *tmp = sc->preproc_config_check_funcs;
1250
1251 while (tmp->next != NULL)
1252 tmp = tmp->next;
1253
1254 tmp->next = node;
1255 }
1256
1257 node->func = pp_chk_config_func;
1258 }
1259
1260 /* functions to aid in cleaning up after plugins */
AddFuncToPreprocCleanExitList(PreprocSignalFunc pp_sig_func,void * arg,uint16_t priority,uint32_t preproc_id)1261 void AddFuncToPreprocCleanExitList(PreprocSignalFunc pp_sig_func, void *arg,
1262 uint16_t priority, uint32_t preproc_id)
1263 {
1264 AddFuncToPreprocSignalList(pp_sig_func, arg, &preproc_clean_exit_funcs, priority, preproc_id);
1265 }
1266
AddFuncToPreprocShutdownList(PreprocSignalFunc pp_shutdown_func,void * arg,uint16_t priority,uint32_t preproc_id)1267 void AddFuncToPreprocShutdownList(PreprocSignalFunc pp_shutdown_func, void *arg,
1268 uint16_t priority, uint32_t preproc_id)
1269 {
1270 AddFuncToPreprocSignalList(pp_shutdown_func, arg, &preproc_shutdown_funcs, priority, preproc_id);
1271 }
1272
AddFuncToPreprocResetList(PreprocSignalFunc pp_sig_func,void * arg,uint16_t priority,uint32_t preproc_id)1273 void AddFuncToPreprocResetList(PreprocSignalFunc pp_sig_func, void *arg,
1274 uint16_t priority, uint32_t preproc_id)
1275 {
1276 AddFuncToPreprocSignalList(pp_sig_func, arg, &preproc_reset_funcs, priority, preproc_id);
1277 }
1278
AddFuncToPreprocResetStatsList(PreprocSignalFunc pp_sig_func,void * arg,uint16_t priority,uint32_t preproc_id)1279 void AddFuncToPreprocResetStatsList(PreprocSignalFunc pp_sig_func, void *arg,
1280 uint16_t priority, uint32_t preproc_id)
1281 {
1282 AddFuncToPreprocSignalList(pp_sig_func, arg, &preproc_reset_stats_funcs, priority, preproc_id);
1283 }
1284
AddFuncToPreprocSignalList(PreprocSignalFunc pp_sig_func,void * arg,PreprocSignalFuncNode ** list,uint16_t priority,uint32_t preproc_id)1285 static void AddFuncToPreprocSignalList(PreprocSignalFunc pp_sig_func, void *arg,
1286 PreprocSignalFuncNode **list,
1287 uint16_t priority, uint32_t preproc_id)
1288 {
1289 PreprocSignalFuncNode *node;
1290
1291 if (list == NULL)
1292 return;
1293
1294 node = (PreprocSignalFuncNode *)SnortAlloc(sizeof(PreprocSignalFuncNode));
1295
1296 if (*list == NULL)
1297 {
1298 *list = node;
1299 }
1300 else
1301 {
1302 PreprocSignalFuncNode *tmp = *list;
1303 PreprocSignalFuncNode *last = NULL;
1304
1305 do
1306 {
1307 /* Insert higher priority stuff first. Lower priority
1308 * number means higher priority */
1309 if (priority < tmp->priority)
1310 break;
1311
1312 last = tmp;
1313 tmp = tmp->next;
1314
1315 } while (tmp != NULL);
1316
1317 /* Priority higher than first item in list */
1318 if (last == NULL)
1319 {
1320 node->next = tmp;
1321 *list = node;
1322 }
1323 else
1324 {
1325 node->next = tmp;
1326 last->next = node;
1327 }
1328 }
1329
1330 node->func = pp_sig_func;
1331 node->arg = arg;
1332 node->preproc_id = preproc_id;
1333 node->priority = priority;
1334 }
1335
AddFuncToPeriodicCheckList(PeriodicFunc periodic_func,void * arg,uint16_t priority,uint32_t preproc_id,uint32_t period)1336 void AddFuncToPeriodicCheckList(PeriodicFunc periodic_func, void *arg,
1337 uint16_t priority, uint32_t preproc_id, uint32_t period )
1338 {
1339 PeriodicCheckFuncNode **list= &periodic_check_funcs;
1340 PeriodicCheckFuncNode *node;
1341
1342
1343 node = (PeriodicCheckFuncNode *)SnortAlloc(sizeof(PeriodicCheckFuncNode));
1344
1345 if (*list == NULL)
1346 {
1347 *list = node;
1348 }
1349 else
1350 {
1351 PeriodicCheckFuncNode *tmp = *list;
1352 PeriodicCheckFuncNode *last = NULL;
1353
1354 do
1355 {
1356 /* Insert higher priority stuff first. Lower priority
1357 * number means higher priority */
1358 if (priority < tmp->priority)
1359 break;
1360
1361 last = tmp;
1362 tmp = tmp->next;
1363
1364 } while (tmp != NULL);
1365
1366 /* Priority higher than first item in list */
1367 if (last == NULL)
1368 {
1369 node->next = tmp;
1370 *list = node;
1371 }
1372 else
1373 {
1374 node->next = tmp;
1375 last->next = node;
1376 }
1377 }
1378
1379 node->func = periodic_func;
1380 node->arg = arg;
1381 node->preproc_id = preproc_id;
1382 node->priority = priority;
1383 node->period = period;
1384 node->time_left = period;
1385 }
1386
FreePreprocConfigFuncs(void)1387 void FreePreprocConfigFuncs(void)
1388 {
1389 PreprocConfigFuncNode *head = preproc_config_funcs;
1390 PreprocConfigFuncNode *tmp;
1391
1392 while (head != NULL)
1393 {
1394 tmp = head->next;
1395 if (head->keyword != NULL)
1396 free(head->keyword);
1397 free(head);
1398 head = tmp;
1399 }
1400 }
1401
FreePreprocCheckConfigFuncs(PreprocCheckConfigFuncNode * head)1402 void FreePreprocCheckConfigFuncs(PreprocCheckConfigFuncNode *head)
1403 {
1404 PreprocCheckConfigFuncNode *tmp;
1405
1406 while (head != NULL)
1407 {
1408 tmp = head->next;
1409 free(head);
1410 head = tmp;
1411 }
1412 }
1413
FreePreprocPostConfigFuncs(PreprocPostConfigFuncNode * head)1414 void FreePreprocPostConfigFuncs(PreprocPostConfigFuncNode *head)
1415 {
1416 PreprocPostConfigFuncNode *tmp;
1417
1418 while (head != NULL)
1419 {
1420 tmp = head->next;
1421 free(head);
1422 head = tmp;
1423 }
1424 }
1425
FreePreprocStatsFuncs(PreprocStatsFuncNode * head)1426 void FreePreprocStatsFuncs(PreprocStatsFuncNode *head)
1427 {
1428 PreprocStatsFuncNode *tmp;
1429
1430 while (head != NULL)
1431 {
1432 tmp = head->next;
1433 if (head->keyword != NULL)
1434 free(head->keyword);
1435 free(head);
1436 head = tmp;
1437 }
1438 }
1439
FreePreprocEvalFuncs(PreprocEvalFuncNode * head)1440 void FreePreprocEvalFuncs(PreprocEvalFuncNode *head)
1441 {
1442 PreprocEvalFuncNode *tmp;
1443
1444 while (head != NULL)
1445 {
1446 tmp = head->next;
1447 //if (head->context)
1448 // free(head->context);
1449 free(head);
1450 head = tmp;
1451 }
1452 }
1453
FreePreprocMetaEvalFuncs(PreprocMetaEvalFuncNode * head)1454 void FreePreprocMetaEvalFuncs(PreprocMetaEvalFuncNode *head)
1455 {
1456 PreprocMetaEvalFuncNode *tmp;
1457
1458 while (head != NULL)
1459 {
1460 tmp = head->next;
1461 //if (head->context)
1462 // free(head->context);
1463 free(head);
1464 head = tmp;
1465 }
1466 }
1467
FreePreprocSigFuncs(PreprocSignalFuncNode * head)1468 void FreePreprocSigFuncs(PreprocSignalFuncNode *head)
1469 {
1470 PreprocSignalFuncNode *tmp;
1471
1472 while (head != NULL)
1473 {
1474 tmp = head->next;
1475 /* don't free sig->arg, that's free'd by the CleanExit func */
1476 free(head);
1477 head = tmp;
1478 }
1479 }
1480
FreePeriodicFuncs(PeriodicCheckFuncNode * head)1481 void FreePeriodicFuncs(PeriodicCheckFuncNode *head)
1482 {
1483 PeriodicCheckFuncNode *tmp;
1484
1485 while (head != NULL)
1486 {
1487 tmp = head->next;
1488 /* don't free sig->arg, that's free'd by the CleanExit func */
1489 free(head);
1490 head = tmp;
1491 }
1492 }
1493
CheckPreprocessorsConfig(SnortConfig * sc)1494 int CheckPreprocessorsConfig(SnortConfig *sc)
1495 {
1496 PreprocCheckConfigFuncNode *idx;
1497 int rval;
1498
1499 if (sc == NULL)
1500 {
1501 FatalError("%s(%d) Snort config is NULL.\n",
1502 __FILE__, __LINE__);
1503 }
1504
1505 idx = sc->preproc_config_check_funcs;
1506
1507 LogMessage("Verifying Preprocessor Configurations!\n");
1508
1509 while(idx != NULL)
1510 {
1511 if ((rval = idx->func(sc)))
1512 return rval;
1513 idx = idx->next;
1514 }
1515 return 0;
1516 }
1517
1518 #ifdef SNORT_RELOAD
VerifyReloadedPreprocessors(SnortConfig * sc)1519 int VerifyReloadedPreprocessors(SnortConfig *sc)
1520 {
1521 int rval;
1522 PreprocessorSwapData *node;
1523 PreprocConfigFuncNode *preproc;
1524
1525 for (node = sc->preprocSwapData; node != NULL; node = node->next)
1526 {
1527 if (node->data && (preproc = node->preprocNode) && preproc->reload_verify_func &&
1528 (rval = preproc->reload_verify_func(sc, node->data)))
1529 {
1530 return rval;
1531 }
1532 }
1533
1534 return 0;
1535 }
1536
FreePreprocessorReloadData(SnortConfig * sc)1537 void FreePreprocessorReloadData(SnortConfig *sc)
1538 {
1539 PreprocessorSwapData *node;
1540 PreprocConfigFuncNode *preproc;
1541
1542 while ((node = sc->preprocSwapData))
1543 {
1544 sc->preprocSwapData = node->next;
1545 if (node->data && (preproc = node->preprocNode) && preproc->reload_swap_free_func)
1546 preproc->reload_swap_free_func(node->data);
1547 free(node);
1548 }
1549 }
1550 #endif
1551
DisableAllPolicies(SnortConfig * sc)1552 void DisableAllPolicies(SnortConfig *sc)
1553 {
1554 if (!sc->disable_all_policies)
1555 {
1556 sc->disable_all_policies = 1;
1557 sc->reenabled_preprocessor_bits = (UINT64_C(1) << PP_FRAG3);
1558 sc->reenabled_preprocessor_bits |= (UINT64_C(1) << PP_STREAM);
1559 sc->reenabled_preprocessor_bits |= (UINT64_C(1) << PP_PERFMONITOR);
1560 }
1561 }
1562
ReenablePreprocBit(SnortConfig * sc,unsigned int preproc_id)1563 int ReenablePreprocBit(SnortConfig *sc, unsigned int preproc_id)
1564 {
1565 sc->reenabled_preprocessor_bits |= (UINT64_C(1) << preproc_id);
1566 return 0;
1567 }
1568
1569 /***************************** Output Plugin API *****************************/
1570 extern OutputConfigFuncNode *output_config_funcs;
1571
1572 static void AppendOutputFuncList(OutputFunc, void *, OutputFuncNode **);
1573
RegisterOutputPlugins(void)1574 void RegisterOutputPlugins(void)
1575 {
1576 LogMessage("Initializing Output Plugins!\n");
1577
1578 AlertSyslogSetup();
1579 LogTcpdumpSetup();
1580 AlertFastSetup();
1581 AlertFullSetup();
1582 #ifndef WIN32
1583 /* Win32 doesn't support AF_UNIX sockets */
1584 AlertUnixSockSetup();
1585 #endif /* !WIN32 */
1586 AlertCSVSetup();
1587 LogNullSetup();
1588 Unified2Setup();
1589 LogAsciiSetup();
1590
1591 #ifdef DUMP_BUFFER
1592 LogBufferDumpSetup();
1593 #endif
1594
1595 #ifdef LINUX
1596 /* This uses linux only capabilities */
1597 AlertSFSocket_Setup();
1598 #endif
1599
1600 AlertTestSetup();
1601 }
1602
1603 /****************************************************************************
1604 *
1605 * Function: RegisterOutputPlugin(char *, void (*func)(Packet *, u_char *))
1606 *
1607 * Purpose: Associates an output statement with its function.
1608 *
1609 * Arguments: keyword => The output keyword to associate with the
1610 * output processor
1611 * type => alert or log types
1612 * *func => function pointer to the handler
1613 *
1614 * Returns: void function
1615 *
1616 ***************************************************************************/
RegisterOutputPlugin(char * keyword,int type_flags,OutputConfigFunc oc_func)1617 void RegisterOutputPlugin(char *keyword, int type_flags, OutputConfigFunc oc_func)
1618 {
1619 OutputConfigFuncNode *node = (OutputConfigFuncNode *)SnortAlloc(sizeof(OutputConfigFuncNode));
1620
1621
1622 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Registering keyword:output => %s:%p\n",
1623 keyword, oc_func););
1624
1625 if (output_config_funcs == NULL)
1626 {
1627 output_config_funcs = node;
1628 }
1629 else
1630 {
1631 OutputConfigFuncNode *tmp = output_config_funcs;
1632 OutputConfigFuncNode *last;
1633
1634 do
1635 {
1636 if (strcasecmp(tmp->keyword, keyword) == 0)
1637 {
1638 free(node);
1639 FatalError("Duplicate output keyword: %s\n", keyword);
1640 }
1641
1642 last = tmp;
1643 tmp = tmp->next;
1644
1645 } while (tmp != NULL);
1646
1647 last->next = node;
1648 }
1649
1650 node->keyword = SnortStrdup(keyword);
1651 node->config_func = oc_func;
1652 node->output_type_flags = type_flags;
1653 }
1654
RemoveOutputPlugin(char * keyword)1655 void RemoveOutputPlugin(char *keyword)
1656 {
1657 OutputConfigFuncNode *head = output_config_funcs;
1658
1659 if (!head ||(keyword == NULL))
1660 return;
1661
1662 /*If head node, remove head*/
1663 if(head->keyword != NULL)
1664 {
1665 if (strcasecmp(head->keyword, keyword) == 0)
1666 {
1667 output_config_funcs = head->next;
1668 free(head->keyword);
1669 free(head);
1670 return;
1671 }
1672 }
1673
1674 while (head->next != NULL)
1675 {
1676 OutputConfigFuncNode *next;
1677 next = head->next;
1678 if(next->keyword != NULL )
1679 {
1680 if (strcasecmp(next->keyword, keyword) == 0)
1681 {
1682 head->next = next->next;
1683 free(next->keyword);
1684 free(next);
1685 break;
1686 }
1687 }
1688 head = head->next;
1689 }
1690
1691 return;
1692 }
1693
GetOutputConfigFunc(char * keyword)1694 OutputConfigFunc GetOutputConfigFunc(char *keyword)
1695 {
1696 OutputConfigFuncNode *head = output_config_funcs;
1697
1698 if (keyword == NULL)
1699 return NULL;
1700
1701 while (head != NULL)
1702 {
1703 if (strcasecmp(head->keyword, keyword) == 0)
1704 return head->config_func;
1705
1706 head = head->next;
1707 }
1708
1709 return NULL;
1710 }
1711
1712
GetOutputTypeFlags(char * keyword)1713 int GetOutputTypeFlags(char *keyword)
1714 {
1715 OutputConfigFuncNode *head = output_config_funcs;
1716
1717 if (keyword == NULL)
1718 return 0;
1719
1720 while (head != NULL)
1721 {
1722 if (strcasecmp(head->keyword, keyword) == 0)
1723 return head->output_type_flags;
1724
1725 head = head->next;
1726 }
1727
1728 return 0;
1729 }
1730
FreeOutputConfigFuncs(void)1731 void FreeOutputConfigFuncs(void)
1732 {
1733 OutputConfigFuncNode *head = output_config_funcs;
1734 OutputConfigFuncNode *tmp;
1735
1736 while (head != NULL)
1737 {
1738 tmp = head->next;
1739 if (head->keyword != NULL)
1740 free(head->keyword);
1741 free(head);
1742 head = tmp;
1743 }
1744 }
1745
FreeOutputList(OutputFuncNode * list)1746 void FreeOutputList(OutputFuncNode *list)
1747 {
1748 while (list != NULL)
1749 {
1750 OutputFuncNode *tmp = list;
1751
1752 list = list->next;
1753 free(tmp);
1754 }
1755 }
1756
1757 /****************************************************************************
1758 *
1759 * Function: DumpOutputPlugins()
1760 *
1761 * Purpose: Prints the keyword->preprocess list
1762 *
1763 * Arguments: None.
1764 *
1765 * Returns: void function
1766 *
1767 ***************************************************************************/
DumpOutputPlugins(void)1768 void DumpOutputPlugins(void)
1769 {
1770 OutputConfigFuncNode *idx = output_config_funcs;
1771
1772 LogMessage("-------------------------------------------------\n");
1773 LogMessage(" Keyword | Output @ \n");
1774 LogMessage("-------------------------------------------------\n");
1775 while(idx != NULL)
1776 {
1777 LogMessage("%-13s: %p\n", idx->keyword, idx->config_vfunc);
1778 idx = idx->next;
1779 }
1780 LogMessage("-------------------------------------------------\n\n");
1781 }
1782
AddFuncToOutputList(SnortConfig * sc,OutputFunc o_func,OutputType type,void * arg)1783 void AddFuncToOutputList(SnortConfig *sc, OutputFunc o_func, OutputType type, void *arg)
1784 {
1785 switch (type)
1786 {
1787 case OUTPUT_TYPE__ALERT:
1788 if (sc->head_tmp != NULL)
1789 AppendOutputFuncList(o_func, arg, &sc->head_tmp->AlertList);
1790 else
1791 AppendOutputFuncList(o_func, arg, &AlertList);
1792
1793 break;
1794
1795 case OUTPUT_TYPE__LOG:
1796 if (sc->head_tmp != NULL)
1797 AppendOutputFuncList(o_func, arg, &sc->head_tmp->LogList);
1798 else
1799 AppendOutputFuncList(o_func, arg, &LogList);
1800
1801 break;
1802
1803 default:
1804 /* just to be error-prone */
1805 FatalError("Unknown output type: %i. Possible bug, please "
1806 "report.\n", type);
1807 }
1808 }
1809
1810 #ifdef DUMP_BUFFER
1811 /****************************************************************************
1812 *
1813 * Function: AddBDFuncToOutputList()
1814 *
1815 * Purpose: This function is called only when buffer dump is enabled. For
1816 * BufferDump output plugin, bdfptr points to LogBufferDump function. For all
1817 * other output plugins, bdfptr points to NULL.
1818 *
1819 * Arguments: sc => snort config
1820 * o_func => output plugin function
1821 * type => alert or log types
1822 * arg => pointer to output stream to which buffers will be dumped
1823 *
1824 * Returns: void function
1825 *
1826 ***************************************************************************/
1827
AddBDFuncToOutputList(SnortConfig * sc,OutputFunc o_func,OutputType type,void * arg)1828 void AddBDFuncToOutputList(SnortConfig *sc, OutputFunc o_func, OutputType type, void *arg)
1829 {
1830
1831 OutputFuncNode *node;
1832
1833 if (sc->head_tmp != NULL)
1834 node = sc->head_tmp->LogList;
1835
1836 else
1837 node = LogList;
1838
1839 while (node->next != NULL)
1840 node = node->next;
1841
1842 node->bdfptr = o_func;
1843 }
1844 #endif
1845
AppendOutputFuncList(OutputFunc o_func,void * arg,OutputFuncNode ** list)1846 void AppendOutputFuncList(OutputFunc o_func, void *arg, OutputFuncNode **list)
1847 {
1848 OutputFuncNode *node;
1849
1850 if (list == NULL)
1851 return;
1852
1853 node = (OutputFuncNode *)SnortAlloc(sizeof(OutputFuncNode));
1854
1855 if (*list == NULL)
1856 {
1857 *list = node;
1858 }
1859 else
1860 {
1861 OutputFuncNode *tmp = *list;
1862
1863 while (tmp->next != NULL)
1864 tmp = tmp->next;
1865
1866 tmp->next = node;
1867 }
1868
1869 node->func = o_func;
1870 node->arg = arg;
1871
1872 #ifdef DUMP_BUFFER
1873 node->bdfptr = NULL;
1874 #endif
1875
1876 }
1877
1878
1879 /************************** Miscellaneous Functions **************************/
1880
1881 /* functions to aid in cleaning up after plugins
1882 * Used for both rule options and output. Preprocessors have their own */
_AddFuncToPostConfigList(PostConfigFunc pl_post_func,void * arg,PostConfigFuncNode ** list)1883 static inline void _AddFuncToPostConfigList(PostConfigFunc pl_post_func, void *arg, PostConfigFuncNode **list)
1884 {
1885 PostConfigFuncNode *node;
1886
1887 node = (PostConfigFuncNode *)SnortAlloc(sizeof(PostConfigFuncNode));
1888
1889 if (*list == NULL)
1890 {
1891 *list = node;
1892 }
1893 else
1894 {
1895 PostConfigFuncNode *tmp = *list;
1896
1897 while (tmp->next != NULL)
1898 tmp = tmp->next;
1899
1900 tmp->next = node;
1901 }
1902
1903 node->func = pl_post_func;
1904 node->arg = arg;
1905 }
1906
1907 #ifdef SNORT_RELOAD
AddFuncToReloadList(PostConfigFunc pl_post_func,void * arg)1908 void AddFuncToReloadList(PostConfigFunc pl_post_func, void *arg)
1909 {
1910 _AddFuncToPostConfigList(pl_post_func, arg, &plugin_reload_funcs);
1911 }
1912 #endif
1913
AddFuncToCleanExitList(PluginSignalFunc pl_sig_func,void * arg)1914 void AddFuncToCleanExitList(PluginSignalFunc pl_sig_func, void *arg)
1915 {
1916 AddFuncToSignalList(pl_sig_func, arg, &plugin_clean_exit_funcs);
1917 }
1918
AddFuncToShutdownList(PluginSignalFunc pl_sig_func,void * arg)1919 void AddFuncToShutdownList(PluginSignalFunc pl_sig_func, void *arg)
1920 {
1921 AddFuncToSignalList(pl_sig_func, arg, &plugin_shutdown_funcs);
1922 }
1923
AddFuncToPostConfigList(SnortConfig * sc,PostConfigFunc pl_post_func,void * arg)1924 void AddFuncToPostConfigList(SnortConfig *sc, PostConfigFunc pl_post_func, void *arg)
1925 {
1926 _AddFuncToPostConfigList(pl_post_func, arg, &sc->plugin_post_config_funcs);
1927 }
1928
AddFuncToSignalList(PluginSignalFunc pl_sig_func,void * arg,PluginSignalFuncNode ** list)1929 void AddFuncToSignalList(PluginSignalFunc pl_sig_func, void *arg, PluginSignalFuncNode **list)
1930 {
1931 PluginSignalFuncNode *node;
1932
1933 if (list == NULL)
1934 return;
1935
1936 node = (PluginSignalFuncNode *)SnortAlloc(sizeof(PluginSignalFuncNode));
1937
1938 if (*list == NULL)
1939 {
1940 *list = node;
1941 }
1942 else
1943 {
1944 PluginSignalFuncNode *tmp = *list;
1945
1946 while (tmp->next != NULL)
1947 tmp = tmp->next;
1948
1949 tmp->next = node;
1950 }
1951
1952 node->func = pl_sig_func;
1953 node->arg = arg;
1954 }
1955
AddFuncToRuleOptParseCleanupList(RuleOptParseCleanupFunc ro_parse_clean_func)1956 void AddFuncToRuleOptParseCleanupList(RuleOptParseCleanupFunc ro_parse_clean_func)
1957 {
1958 RuleOptParseCleanupNode *node =
1959 (RuleOptParseCleanupNode *)SnortAlloc(sizeof(RuleOptParseCleanupNode));
1960
1961 if (rule_opt_parse_cleanup_list == NULL)
1962 {
1963 rule_opt_parse_cleanup_list = node;
1964 }
1965 else
1966 {
1967 RuleOptParseCleanupNode *tmp = rule_opt_parse_cleanup_list;
1968
1969 while (tmp->next != NULL)
1970 tmp = tmp->next;
1971
1972 tmp->next = node;
1973 }
1974
1975 node->func = ro_parse_clean_func;
1976 }
1977
RuleOptParseCleanup(void)1978 void RuleOptParseCleanup(void)
1979 {
1980 RuleOptParseCleanupNode *list = rule_opt_parse_cleanup_list;
1981
1982 for (; list != NULL; list = list->next)
1983 {
1984 if (list->func != NULL)
1985 list->func();
1986 }
1987 }
1988
FreeRuleOptParseCleanupList(RuleOptParseCleanupNode * head)1989 void FreeRuleOptParseCleanupList(RuleOptParseCleanupNode *head)
1990 {
1991 while (head != NULL)
1992 {
1993 RuleOptParseCleanupNode *tmp = head;
1994
1995 head = head->next;
1996 free(tmp);
1997 }
1998 }
1999
RegisterGetHttpXffFields(GetHttpXffFieldsFunc fn)2000 void RegisterGetHttpXffFields(GetHttpXffFieldsFunc fn)
2001 {
2002 if (!getHttpXffFieldsFunc) getHttpXffFieldsFunc = fn;
2003 }
2004
GetHttpXffFields(int * nFields)2005 char** GetHttpXffFields(int* nFields)
2006 {
2007 if (getHttpXffFieldsFunc) return getHttpXffFieldsFunc(nFields);
2008 else return NULL;
2009 }
2010