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