1 /* $Id$ */
2 /*
3 ** Copyright (C) 2002-2009 Sourcefire, Inc.
4 ** Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU General Public License Version 2 as
8 ** published by the Free Software Foundation. You may not use, modify or
9 ** distribute this program under any other version of the GNU General
10 ** Public License.
11 **
12 ** This program is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ** GNU General Public License for more details.
16 **
17 ** You should have received a copy of the GNU General Public License
18 ** along with this program; if not, write to the Free Software
19 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22 /*
23 ** Modifications by: Ian Firns <firnsy@securixlive.com>
24 **
25 ** History:
26 ** 2008-05-09 - Cleaned and amalgamated the input and output plugin API into
27 ** the one file.
28 */
29
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33
34 #include <sys/types.h>
35 #include <unistd.h>
36 #include <stdlib.h>
37 #include <string.h>
38
39 #ifdef HAVE_STRINGS_H
40 #include <strings.h>
41 #endif
42
43 //#include <sys/socket.h>
44 #include <netinet/in.h>
45 #include <arpa/inet.h>
46 #include <time.h>
47 #include <errno.h>
48
49 #include "plugbase.h"
50 #include "barnyard2.h"
51 #include "debug.h"
52 #include "util.h"
53
54 #include "unified2.h"
55
56 /* built-in input plugins */
57 #include "input-plugins/spi_unified2.h"
58
59 /* built-in output plugins */
60 #include "output-plugins/spo_alert_arubaaction.h"
61 #include "output-plugins/spo_alert_bro.h"
62 #include "output-plugins/spo_alert_cef.h"
63 #include "output-plugins/spo_alert_csv.h"
64 #include "output-plugins/spo_alert_fast.h"
65 #include "output-plugins/spo_alert_full.h"
66 #include "output-plugins/spo_alert_fwsam.h"
67 #include "output-plugins/spo_alert_syslog.h"
68 #include "output-plugins/spo_alert_test.h"
69 #include "output-plugins/spo_alert_prelude.h"
70 #include "output-plugins/spo_alert_unixsock.h"
71 #include "output-plugins/spo_database.h"
72 #include "output-plugins/spo_log_ascii.h"
73 #include "output-plugins/spo_log_null.h"
74 #include "output-plugins/spo_log_tcpdump.h"
75 #include "output-plugins/spo_echidna.h"
76 #include "output-plugins/spo_sguil.h"
77 #include "output-plugins/spo_syslog_full.h"
78
79 extern InputConfigFuncNode *input_config_funcs;
80 extern OutputConfigFuncNode *output_config_funcs;
81 extern PluginSignalFuncNode *plugin_shutdown_funcs;
82 extern PluginSignalFuncNode *plugin_clean_exit_funcs;
83 extern PluginSignalFuncNode *plugin_restart_funcs;
84
85 extern InputFuncNode *InputList;
86 extern OutputFuncNode *AlertList;
87 extern OutputFuncNode *LogList;
88
89 extern Barnyard2Config *barnyard2_conf_for_parsing;
90 extern int file_line;
91 extern char *file_name;
92
93 /***************************** Input Plugin API *****************************/
94 /*InputKeywordList *InputKeywords;
95
96 InputFuncNode *InputList;
97 */
RegisterInputPlugins()98 void RegisterInputPlugins()
99 {
100 LogMessage("Initializing Input Plugins!\n");
101 Unified2Setup();
102 }
103
GetInputPlugin(char * keyword)104 InputFuncNode *GetInputPlugin(char *keyword)
105 {
106 InputFuncNode *node = InputList;
107
108 if (keyword == NULL)
109 return NULL;
110
111 while ((node != NULL) && (strcasecmp(keyword, node->keyword) != 0))
112 {
113 node = node->next;
114 }
115
116 if (node == NULL)
117 {
118 FatalError("unknown input plugin: '%s'\n", keyword);
119 }
120
121 return node;
122 }
123
124 /****************************************************************************
125 *
126 * Function: RegisterInputPlugin(char *, InputConfigFunc *)
127 *
128 * Purpose: Associates an input statement with its function. It will also
129 * setup a InputFunctionNode of the same keyword which stores the
130 * apppropriate file processing methods.
131 *
132 * Arguments: keyword => The input keyword to associate with the
133 * input processor
134 * *func => function pointer to the handler
135 *
136 * Returns: void function
137 *
138 ***************************************************************************/
RegisterInputPlugin(char * keyword,InputConfigFunc func)139 void RegisterInputPlugin(char *keyword, InputConfigFunc func)
140 {
141 InputConfigFuncNode *node = (InputConfigFuncNode *)SnortAlloc(sizeof(InputConfigFuncNode));
142 InputFuncNode *node2 = (InputFuncNode *)SnortAlloc(sizeof(InputFuncNode));
143
144 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Registering keyword:input => %s:%p\n",
145 keyword, func););
146
147 if (input_config_funcs == NULL)
148 {
149 input_config_funcs = node;
150 }
151 else
152 {
153 InputConfigFuncNode *tmp = input_config_funcs;
154 InputConfigFuncNode *last;
155
156 do
157 {
158 if (strcasecmp(tmp->keyword, keyword) == 0)
159 {
160 free(node);
161 FatalError("Duplicate input keyword: %s\n", keyword);
162 }
163
164 last = tmp;
165 tmp = tmp->next;
166
167 } while (tmp != NULL);
168
169 last->next = node;
170 }
171
172 node->keyword = SnortStrdup(keyword);
173 node->func = func;
174
175 if (InputList == NULL)
176 {
177 InputList = node2;
178 }
179 else
180 {
181 InputFuncNode *tmp2 = InputList;
182 InputFuncNode *last2;
183
184 do
185 {
186 if (strcasecmp(tmp2->keyword, keyword) == 0)
187 {
188 free(node2);
189 FatalError("Duplicate input keyword: %s\n", keyword);
190 }
191
192 last2 = tmp2;
193 tmp2 = tmp2->next;
194
195 } while (tmp2 != NULL);
196
197 last2->next = node2;
198 }
199
200 node2->keyword = SnortStrdup(keyword);
201 }
202
203
GetInputConfigFunc(char * keyword)204 InputConfigFunc GetInputConfigFunc(char *keyword)
205 {
206 InputConfigFuncNode *head = input_config_funcs;
207
208 if (keyword == NULL)
209 return NULL;
210
211 while (head != NULL)
212 {
213 if (strcasecmp(head->keyword, keyword) == 0)
214 return head->func;
215
216 head = head->next;
217 }
218
219 return NULL;
220 }
221
222 /****************************************************************************
223 *
224 * Function: DumpInputPlugins()
225 *
226 * Purpose: Prints the keyword->function list
227 *
228 * Arguments: None.
229 *
230 * Returns: void function
231 *
232 ***************************************************************************/
DumpInputPlugins()233 void DumpInputPlugins()
234 {
235 InputConfigFuncNode *idx = input_config_funcs;
236 InputFuncNode *ifn = NULL;
237
238 LogMessage("-------------------------------------------------\n");
239 LogMessage(" Keyword | Input @ \n");
240 LogMessage("-------------------------------------------------\n");
241 while(idx != NULL)
242 {
243 LogMessage("%-13s: init() = %p\n", idx->keyword, idx->func);
244 ifn = GetInputPlugin(idx->keyword);
245
246 if ((ifn != NULL) && ifn->configured_flag)
247 {
248 LogMessage("%-13s: - readRecordHeader() = %p\n",
249 ifn->keyword, ifn->readRecordHeader);
250 LogMessage("%-13s: - readRecord() = %p\n",
251 ifn->keyword, ifn->readRecord);
252 }
253
254 idx = idx->next;
255 }
256 LogMessage("-------------------------------------------------\n\n");
257 }
258
AddArgToInputList(char * keyword,void * arg)259 int AddArgToInputList(char *keyword, void *arg)
260 {
261 InputFuncNode *node;
262
263 if(keyword == NULL)
264 return -1;
265
266 node = GetInputPlugin(keyword);
267
268 node->arg = arg;
269
270 return 0;
271 }
272
AddReadRecordHeaderFuncToInputList(char * keyword,int (* readRecordHeader)(void *))273 int AddReadRecordHeaderFuncToInputList(char *keyword, int (*readRecordHeader)(void *))
274 {
275 InputFuncNode *node;
276
277 if(keyword == NULL)
278 return -1;
279
280 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Registering keyword:readRecordHeader => %s:%p\n",
281 keyword, readRecordHeader););
282
283 node = GetInputPlugin(keyword);
284
285 node->readRecordHeader = readRecordHeader;
286 node->configured_flag = InputFuncNodeConfigured(node);
287
288 return 0;
289 }
290
AddReadRecordFuncToInputList(char * keyword,int (* readRecord)(void *))291 int AddReadRecordFuncToInputList(char *keyword, int (*readRecord)(void *))
292 {
293 InputFuncNode *node;
294
295 if(keyword == NULL)
296 return -1;
297
298 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Registering keyword:readRecord => %s:%p\n",
299 keyword, readRecord););
300
301 node = GetInputPlugin(keyword);
302
303 node->readRecord = readRecord;
304 node->configured_flag = InputFuncNodeConfigured(node);
305
306 return 0;
307 }
308
InputFuncNodeConfigured(InputFuncNode * ifn)309 int InputFuncNodeConfigured(InputFuncNode *ifn)
310 {
311 /* if not all functions are defined then return a zero flag */
312 if (!ifn->readRecordHeader || !ifn->readRecord)
313 return 0;
314
315 return 1;
316 }
317
318
319 /***************************** Output Plugin API *****************************/
320 extern OutputConfigFuncNode *output_config_funcs;
321
322 static void AppendOutputFuncList(OutputFunc, void *, OutputFuncNode **);
323
RegisterOutputPlugins(void)324 void RegisterOutputPlugins(void)
325 {
326 LogMessage("Initializing Output Plugins!\n");
327
328 AlertCEFSetup();
329 AlertSyslogSetup();
330
331 #ifdef HAVE_LIBPCAP
332 LogTcpdumpSetup();
333 #endif /* HAVE_LIBPCAP */
334
335 DatabaseSetup();
336 AlertFastSetup();
337 AlertFullSetup();
338 AlertFWsamSetup();
339 #ifndef WIN32
340 /* Win32 doesn't support AF_UNIX sockets */
341 AlertUnixSockSetup();
342 #endif /* !WIN32 */
343 AlertCSVSetup();
344 LogNullSetup();
345 LogAsciiSetup();
346
347 #ifdef ARUBA
348 AlertArubaActionSetup();
349 #endif
350
351 #ifdef HAVE_LIBPRELUDE
352 AlertPreludeSetup();
353 #endif
354
355 #ifdef BROCCOLI
356 AlertBroSetup();
357 #endif
358
359 AlertTestSetup();
360
361 #ifdef ENABLE_PLUGIN_ECHIDNA
362 EchidnaSetup();
363 #endif
364
365 SguilSetup();
366
367 OpSyslog_Setup();
368
369 }
370
371 /****************************************************************************
372 *
373 * Function: RegisterOutputPlugin(char *, void (*func)(Packet *, u_char *))
374 *
375 * Purpose: Associates an output statement with its function.
376 *
377 * Arguments: keyword => The output keyword to associate with the
378 * output processor
379 * type => alert or log types
380 * *func => function pointer to the handler
381 *
382 * Returns: void function
383 *
384 ***************************************************************************/
RegisterOutputPlugin(char * keyword,int type_flags,OutputConfigFunc func)385 void RegisterOutputPlugin(char *keyword, int type_flags, OutputConfigFunc func)
386 {
387 OutputConfigFuncNode *node = (OutputConfigFuncNode *)SnortAlloc(sizeof(OutputConfigFuncNode));
388
389 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Registering keyword:output => %s:%p\n",
390 keyword, func););
391
392 if (output_config_funcs == NULL)
393 {
394 output_config_funcs = node;
395 }
396 else
397 {
398 OutputConfigFuncNode *tmp = output_config_funcs;
399 OutputConfigFuncNode *last;
400
401 do
402 {
403 if (strcasecmp(tmp->keyword, keyword) == 0)
404 {
405 free(node);
406 FatalError("Duplicate output keyword: %s\n", keyword);
407 }
408
409 last = tmp;
410 tmp = tmp->next;
411
412 } while (tmp != NULL);
413
414 last->next = node;
415 }
416
417 node->keyword = SnortStrdup(keyword);
418 node->func = func;
419 node->output_type_flags = type_flags;
420 }
421
GetOutputConfigFunc(char * keyword)422 OutputConfigFunc GetOutputConfigFunc(char *keyword)
423 {
424 OutputConfigFuncNode *head = output_config_funcs;
425
426 if (keyword == NULL)
427 return NULL;
428
429 while (head != NULL)
430 {
431 if (strcasecmp(head->keyword, keyword) == 0)
432 return head->func;
433
434 head = head->next;
435 }
436
437 return NULL;
438 }
439
GetOutputTypeFlags(char * keyword)440 int GetOutputTypeFlags(char *keyword)
441 {
442 OutputConfigFuncNode *head = output_config_funcs;
443
444 if (keyword == NULL)
445 return 0;
446
447 while (head != NULL)
448 {
449 if (strcasecmp(head->keyword, keyword) == 0)
450 return head->output_type_flags;
451
452 head = head->next;
453 }
454
455 return 0;
456 }
457
FreeOutputConfigFuncs(void)458 void FreeOutputConfigFuncs(void)
459 {
460 OutputConfigFuncNode *head = output_config_funcs;
461 OutputConfigFuncNode *tmp;
462
463 while (head != NULL)
464 {
465 tmp = head->next;
466 if (head->keyword != NULL)
467 free(head->keyword);
468 free(head);
469 head = tmp;
470 }
471
472 output_config_funcs = NULL;
473 }
474
475
FreeInputPlugins(void)476 void FreeInputPlugins(void)
477 {
478
479 InputConfigFuncNode *tmp = input_config_funcs;
480 InputConfigFuncNode *next = NULL;
481
482 InputFuncNode *tmp2 = InputList;
483 InputFuncNode *next2 = NULL;
484
485 while(tmp != NULL)
486 {
487 next = tmp->next;
488
489 if(tmp->keyword != NULL)
490 {
491 free(tmp->keyword);
492 tmp->keyword = NULL;
493 }
494
495 free(tmp);
496 tmp = next;
497 }
498
499
500 while(tmp2 != NULL)
501 {
502 next2 =tmp2->next;
503
504 if( tmp2->keyword != NULL)
505 {
506 free(tmp2->keyword);
507 tmp2->keyword = NULL;
508 }
509
510 if( tmp2->arg != NULL)
511 {
512 free(tmp2->arg);
513 tmp2->arg = NULL;
514 }
515
516 free(tmp2);
517 tmp2 = next2;
518 }
519
520 input_config_funcs = NULL;
521 InputList = NULL;
522 return;
523 }
524
525
FreeOutputList(OutputFuncNode * list)526 void FreeOutputList(OutputFuncNode *list)
527 {
528 while (list != NULL)
529 {
530 OutputFuncNode *tmp = list;
531
532 list = list->next;
533
534 if(tmp != NULL)
535 {
536 free(tmp);
537 }
538 }
539
540 }
541
542 /****************************************************************************
543 *
544 * Function: DumpOutputPlugins()
545 *
546 * Purpose: Prints the Output keyword list
547 *
548 * Arguments: None.
549 *
550 * Returns: void function
551 *
552 ***************************************************************************/
DumpOutputPlugins(void)553 void DumpOutputPlugins(void)
554 {
555 OutputConfigFuncNode *idx = output_config_funcs;
556
557 LogMessage("-------------------------------------------------\n");
558 LogMessage(" Keyword | Output @ \n");
559 LogMessage("-------------------------------------------------\n");
560 while(idx != NULL)
561 {
562 LogMessage("%-13s: %p\n", idx->keyword, idx->func);
563 idx = idx->next;
564 }
565 LogMessage("-------------------------------------------------\n\n");
566 }
567
AddFuncToOutputList(OutputFunc func,OutputType type,void * arg)568 void AddFuncToOutputList(OutputFunc func, OutputType type, void *arg)
569 {
570 switch (type)
571 {
572 case OUTPUT_TYPE__ALERT:
573 AppendOutputFuncList(func, arg, &AlertList);
574 break;
575
576 case OUTPUT_TYPE__LOG:
577 AppendOutputFuncList(func, arg, &LogList);
578 break;
579
580 default:
581 /* just to be error-prone */
582 FatalError("Unknown output type: %i. Possible bug, please "
583 "report.\n", type);
584 }
585 }
586
AppendOutputFuncList(OutputFunc func,void * arg,OutputFuncNode ** list)587 void AppendOutputFuncList(OutputFunc func, void *arg, OutputFuncNode **list)
588 {
589 OutputFuncNode *node;
590
591 if (list == NULL)
592 return;
593
594 node = (OutputFuncNode *)SnortAlloc(sizeof(OutputFuncNode));
595
596 if (*list == NULL)
597 {
598 *list = node;
599 }
600 else
601 {
602 OutputFuncNode *tmp = *list;
603
604 while (tmp->next != NULL)
605 tmp = tmp->next;
606
607 tmp->next = node;
608 }
609
610 node->func = func;
611 node->arg = arg;
612 }
613
pbCheckSignatureSuppression(void * event)614 int pbCheckSignatureSuppression(void *event)
615 {
616 Unified2EventCommon *uCommon = (Unified2EventCommon *)event;
617 SigSuppress_list **sHead = BCGetSigSuppressHead();
618 SigSuppress_list *cNode = NULL;
619 u_int32_t gid = 0;
620 u_int32_t sid = 0;
621
622 if( (uCommon == NULL) ||
623 (sHead == NULL))
624 {
625 return 0;
626 }
627
628 cNode = *sHead;
629
630 gid = ntohl(uCommon->generator_id);
631 sid = ntohl(uCommon->signature_id);
632
633 while(cNode)
634 {
635 if(cNode->gid == gid)
636 {
637 switch(cNode->ss_type)
638 {
639 case SS_SINGLE:
640 if(cNode->ss_min == sid)
641 {
642 SigSuppressCount();
643 return 1;
644 }
645 break;
646
647 case SS_RANGE:
648 if( (sid >= cNode->ss_min) &&
649 (sid <= cNode->ss_max))
650 {
651 SigSuppressCount();
652 return 1;
653 }
654 break;
655
656 default:
657 FatalError("[%s()], Unknown Signature suppress type \n",
658 __FUNCTION__);
659 break;
660 }
661
662 }
663 cNode = cNode->next;
664 }
665
666 return 0;
667 }
668
669
670
CallOutputPlugins(OutputType out_type,Packet * packet,void * event,uint32_t event_type)671 void CallOutputPlugins(OutputType out_type, Packet *packet, void *event, uint32_t event_type)
672 {
673 OutputFuncNode *idx = NULL;
674
675 /* Plug for sid suppression */
676 if(event)
677 {
678 if(pbCheckSignatureSuppression(event))
679 return;
680 }
681
682
683 if (out_type == OUTPUT_TYPE__SPECIAL)
684 {
685 idx = AlertList;
686 while (idx != NULL)
687 {
688 idx->func(packet, event, event_type, idx->arg);
689 idx = idx->next;
690 }
691
692 idx = LogList;
693 while (idx != NULL)
694 {
695 idx->func(packet, event, event_type, idx->arg);
696 idx = idx->next;
697 }
698 }
699 else
700 {
701 //All those sub "Log" type will go away in the future..
702 //Iterate Log and Alert.
703 idx = LogList;
704
705 while (idx != NULL)
706 {
707 idx->func(packet, event, event_type, idx->arg);
708 idx = idx->next;
709 }
710
711 idx = AlertList;
712
713 while (idx != NULL)
714 {
715 idx->func(packet, event, event_type, idx->arg);
716 idx = idx->next;
717 }
718
719 }
720 }
721
722
723 /************************** Miscellaneous Functions **************************/
724
PostConfigInitPlugins(PluginSignalFuncNode * post_config_funcs)725 void PostConfigInitPlugins(PluginSignalFuncNode *post_config_funcs)
726 {
727 while (post_config_funcs != NULL)
728 {
729 post_config_funcs->func(0, post_config_funcs->arg);
730 post_config_funcs = post_config_funcs->next;
731 }
732 }
733
734 /* functions to aid in cleaning up after plugins
735 * Used for both rule options and output. Preprocessors have their own */
AddFuncToRestartList(PluginSignalFunc func,void * arg)736 void AddFuncToRestartList(PluginSignalFunc func, void *arg)
737 {
738 AddFuncToSignalList(func, arg, &plugin_restart_funcs);
739 }
740
AddFuncToCleanExitList(PluginSignalFunc func,void * arg)741 void AddFuncToCleanExitList(PluginSignalFunc func, void *arg)
742 {
743 AddFuncToSignalList(func, arg, &plugin_clean_exit_funcs);
744 }
745
AddFuncToShutdownList(PluginSignalFunc func,void * arg)746 void AddFuncToShutdownList(PluginSignalFunc func, void *arg)
747 {
748 AddFuncToSignalList(func, arg, &plugin_shutdown_funcs);
749 }
750
AddFuncToPostConfigList(PluginSignalFunc func,void * arg)751 void AddFuncToPostConfigList(PluginSignalFunc func, void *arg)
752 {
753 Barnyard2Config *bc = barnyard2_conf_for_parsing;
754
755 if (bc == NULL)
756 {
757 FatalError("%s(%d) Barnyard2 config for parsing is NULL.\n",
758 __FILE__, __LINE__);
759 }
760
761 AddFuncToSignalList(func, arg, &bc->plugin_post_config_funcs);
762 }
763
AddFuncToSignalList(PluginSignalFunc func,void * arg,PluginSignalFuncNode ** list)764 void AddFuncToSignalList(PluginSignalFunc func, void *arg, PluginSignalFuncNode **list)
765 {
766 PluginSignalFuncNode *node;
767
768 if (list == NULL)
769 return;
770
771 node = (PluginSignalFuncNode *)SnortAlloc(sizeof(PluginSignalFuncNode));
772
773 if (*list == NULL)
774 {
775 *list = node;
776 }
777 else
778 {
779 PluginSignalFuncNode *tmp = *list;
780
781 while (tmp->next != NULL)
782 tmp = tmp->next;
783
784 tmp->next = node;
785 }
786
787 node->func = func;
788 node->arg = arg;
789 }
790
791
FreePluginSigFuncs(PluginSignalFuncNode * head)792 void FreePluginSigFuncs(PluginSignalFuncNode *head)
793 {
794 while (head != NULL)
795 {
796 PluginSignalFuncNode *tmp = head;
797
798 head = head->next;
799
800 /* don't free sig->arg, that's free'd by the CleanExit/Restart func */
801 free(tmp);
802 }
803 }
804