Main Page | Modules | Class List | Directories | File List | Class Members | File Members | Related Pages

plugbase.c

Go to the documentation of this file.
00001 /* $Id$ */
00002 /*
00003 ** Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>
00004 **
00005 ** This program is free software; you can redistribute it and/or modify
00006 ** it under the terms of the GNU General Public License as published by
00007 ** the Free Software Foundation; either version 2 of the License, or
00008 ** (at your option) any later version.
00009 **
00010 ** This program is distributed in the hope that it will be useful,
00011 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 ** GNU General Public License for more details.
00014 **
00015 ** You should have received a copy of the GNU General Public License
00016 ** along with this program; if not, write to the Free Software
00017 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00018 */
00019 
00020 #ifdef HAVE_CONFIG_H
00021 #include "config.h"
00022 #endif
00023 
00024 #include <sys/types.h>
00025 #include <unistd.h>
00026 #include <stdlib.h>
00027 #include <string.h>
00028 
00029 #ifdef HAVE_STRINGS_H
00030 #include <strings.h>
00031 #endif
00032 
00033 #ifndef WIN32
00034 #include <sys/socket.h>
00035 #include <netinet/in.h>
00036 #include <arpa/inet.h>
00037 #endif /* !WIN32 */
00038 #include <time.h>
00039 #include <errno.h>
00040 
00041 
00042 #include "plugbase.h"
00043 #include "spo_plugbase.h"
00044 #include "snort.h"
00045 #include "debug.h"
00046 #include "util.h"
00047 #include "log.h"
00048 #include "detect.h"
00049 
00050 /* built-in preprocessors */
00051 #include "preprocessors/spp_portscan.h"
00052 #include "preprocessors/spp_rpc_decode.h"
00053 #include "preprocessors/spp_bo.h"
00054 #include "preprocessors/spp_telnet_negotiation.h"
00055 #include "preprocessors/spp_stream4.h"
00056 #include "preprocessors/spp_frag2.h"
00057 #include "preprocessors/spp_arpspoof.h"
00058 #include "preprocessors/spp_conversation.h"
00059 #include "preprocessors/spp_portscan2.h"
00060 #include "preprocessors/spp_perfmonitor.h"
00061 #include "preprocessors/spp_httpinspect.h"
00062 #include "preprocessors/spp_flow.h"
00063 #include "preprocessors/spp_sfportscan.h"
00064 #include "preprocessors/spp_frag3.h"
00065 #include "preprocessors/spp_xlink2state.h"
00066 #include "preprocessors/spp_clamav.h"
00067 #ifdef GIDS
00068 #include "preprocessors/spp_stickydrop.h"
00069 #include "preprocessors/spp_bait_and_switch.h"
00070 #endif
00071 
00072 /* built-in detection plugins */
00073 #include "detection-plugins/sp_pattern_match.h"
00074 #include "detection-plugins/sp_tcp_flag_check.h"
00075 #include "detection-plugins/sp_icmp_type_check.h"
00076 #include "detection-plugins/sp_icmp_code_check.h"
00077 #include "detection-plugins/sp_ttl_check.h"
00078 #include "detection-plugins/sp_ip_id_check.h"
00079 #include "detection-plugins/sp_tcp_ack_check.h"
00080 #include "detection-plugins/sp_tcp_seq_check.h"
00081 #include "detection-plugins/sp_dsize_check.h"
00082 #include "detection-plugins/sp_ipoption_check.h"
00083 #include "detection-plugins/sp_rpc_check.h"
00084 #include "detection-plugins/sp_icmp_id_check.h"
00085 #include "detection-plugins/sp_icmp_seq_check.h"
00086 #include "detection-plugins/sp_session.h"
00087 #include "detection-plugins/sp_ip_tos_check.h"
00088 #include "detection-plugins/sp_ip_fragbits.h"
00089 #include "detection-plugins/sp_tcp_win_check.h"
00090 #include "detection-plugins/sp_ip_same_check.h"
00091 #include "detection-plugins/sp_ip_proto.h"
00092 #include "detection-plugins/sp_ip_same_check.h"
00093 #include "detection-plugins/sp_clientserver.h"
00094 #include "detection-plugins/sp_byte_check.h"
00095 #include "detection-plugins/sp_byte_jump.h"
00096 #include "detection-plugins/sp_isdataat.h"
00097 #include "detection-plugins/sp_pcre.h"
00098 #include "detection-plugins/sp_flowbits.h"
00099 #include "detection-plugins/sp_asn1.h"
00100 #ifdef ENABLE_RESPONSE
00101 #include "detection-plugins/sp_react.h"
00102 #include "detection-plugins/sp_respond.h"
00103 #endif
00104 #include "detection-plugins/sp_ftpbounce.h"
00105 #ifdef GIDS
00106 #include "detection-plugins/sp_stickydrop.h"
00107 #include "detection-plugins/sp_bait_and_switch.h"
00108 #endif
00109 
00110 
00111 /* built-in output plugins */
00112 #include "output-plugins/spo_alert_syslog.h"
00113 #include "output-plugins/spo_log_tcpdump.h"
00114 #include "output-plugins/spo_database.h"
00115 #include "output-plugins/spo_alert_fast.h"
00116 #include "output-plugins/spo_alert_full.h"
00117 #include "output-plugins/spo_alert_unixsock.h"
00118 #include "output-plugins/spo_csv.h"
00119 #include "output-plugins/spo_unified.h"
00120 #include "output-plugins/spo_log_null.h"
00121 #include "output-plugins/spo_log_ascii.h"
00122 #ifdef GIDS
00123 #include "output-plugins/spo_bait_and_switch.h"
00124 #include "output-plugins/spo_stickydrop.h"
00125 #endif
00126 #ifdef HAVE_LIBPRELUDE
00127 #include "output-plugins/spo_alert_prelude.h"
00128 #endif
00129 
00130 #ifdef LINUX
00131 #include "output-plugins/spo_alert_sf_socket.h"
00132 #endif
00133 
00134 PluginSignalFuncNode *PluginShutdownList;
00135 PluginSignalFuncNode *PluginCleanExitList;
00136 PluginSignalFuncNode *PluginRestartList;
00137 
00138 extern int file_line;
00139 extern char *file_name;
00140 
00141 
00142 
00143 
00144 /**************************** Detection Plugin API ****************************/
00145 KeywordXlateList *KeywordList;
00146 
00147 void InitPlugIns()
00148 {
00149     if(!pv.quiet_flag)
00150     {
00151         LogMessage("Initializing Plug-ins!\n");
00152     }
00153     SetupPatternMatch();
00154     SetupTCPFlagCheck();
00155     SetupIcmpTypeCheck();
00156     SetupIcmpCodeCheck();
00157     SetupTtlCheck();
00158     SetupIpIdCheck();
00159     SetupTcpAckCheck();
00160     SetupTcpSeqCheck();
00161     SetupDsizeCheck();
00162     SetupIpOptionCheck();
00163     SetupRpcCheck();
00164     SetupIcmpIdCheck();
00165     SetupIcmpSeqCheck();
00166     SetupSession();
00167     SetupIpTosCheck();
00168     SetupFragBits();
00169     SetupFragOffset();
00170     SetupTcpWinCheck();
00171     SetupIpProto();
00172     SetupIpSameCheck();
00173     SetupClientServer();
00174     SetupByteTest();
00175     SetupByteJump();
00176     SetupIsDataAt();
00177     SetupPcre();
00178     SetupFlowBits();
00179     SetupAsn1();
00180 #ifdef ENABLE_RESPONSE
00181     SetupReact();
00182     SetupRespond();
00183 #endif
00184     SetupFTPBounce();
00185 #ifdef GIDS
00186     SetupStickyDSp();
00187 #ifndef IPFW
00188     SetupBandSp();
00189 #endif /* IPFW */
00190 #endif /* GIDS */
00191 }
00192 
00193 /****************************************************************************
00194  *
00195  * Function: RegisterPlugin(char *, void (*func)())
00196  *
00197  * Purpose:  Associates a rule option keyword with an option setup/linking
00198  *           function.
00199  *
00200  * Arguments: keyword => The option keyword to associate with the option
00201  *                       handler
00202  *            *func => function pointer to the handler
00203  *
00204  * Returns: void function
00205  *
00206  ***************************************************************************/
00207 void RegisterPlugin(char *keyword, void (*func) (char *, OptTreeNode *, int))
00208 {
00209     KeywordXlateList *idx;
00210 
00211     DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Registering keyword:func => %s:%p\n",
00212                keyword, func););
00213 
00214     idx = KeywordList;
00215 
00216     if(idx == NULL)
00217     {
00218         KeywordList = (KeywordXlateList *) calloc(sizeof(KeywordXlateList), 
00219                 sizeof(char));
00220 
00221         KeywordList->entry.keyword = (char *) calloc(strlen(keyword) + 1, 
00222                 sizeof(char));
00223         strncpy(KeywordList->entry.keyword, keyword, strlen(keyword)+1);
00224         KeywordList->entry.func = func;
00225     }
00226     else
00227     {
00228         /* go to the end of the list */
00229         while(idx->next != NULL)
00230         {
00231             if(!strcasecmp(idx->entry.keyword, keyword))
00232             {
00233                 FatalError("RegisterPlugin: Duplicate detection plugin keyword:"
00234                         " (%s) (%s)!\n", idx->entry.keyword, keyword);
00235             }
00236             idx = idx->next;
00237         }
00238 
00239         idx->next = (KeywordXlateList *) calloc(sizeof(KeywordXlateList), 
00240                 sizeof(char));
00241 
00242         idx = idx->next;
00243 
00244         idx->entry.keyword = (char *) calloc(strlen(keyword) + 1, sizeof(char));
00245         strncpy(idx->entry.keyword, keyword, strlen(keyword)+1);
00246         idx->entry.func = func;
00247     }
00248 }
00249 
00250 
00251 
00252 
00253 /****************************************************************************
00254  *
00255  * Function: DumpPlugIns()
00256  *
00257  * Purpose:  Prints the keyword->function list
00258  *
00259  * Arguments: None.
00260  *
00261  * Returns: void function
00262  *
00263  ***************************************************************************/
00264 void DumpPlugIns()
00265 {
00266     KeywordXlateList *idx;
00267 
00268     if(pv.quiet_flag)
00269         return;
00270 
00271     idx = KeywordList;
00272 
00273     printf("-------------------------------------------------\n");
00274     printf(" Keyword     |      Plugin Registered @\n");
00275     printf("-------------------------------------------------\n");
00276     while(idx != NULL)
00277     {
00278         printf("%-13s:      %p\n", idx->entry.keyword, idx->entry.func);
00279         idx = idx->next;
00280     }
00281     printf("-------------------------------------------------\n\n");
00282 }
00283 
00284 
00285 /****************************************************************************
00286  * 
00287  * Function: AddOptFuncToList(int (*func)(), OptTreeNode *)
00288  *
00289  * Purpose: Links the option detection module to the OTN
00290  *
00291  * Arguments: (*func)() => function pointer to the detection module
00292  *            otn =>  pointer to the current OptTreeNode
00293  *
00294  * Returns: void function
00295  *
00296  ***************************************************************************/
00297 OptFpList *AddOptFuncToList(int (*func) (Packet *, struct _OptTreeNode *, 
00298             struct _OptFpList *), OptTreeNode * otn)
00299 {
00300     OptFpList *idx;     /* index pointer */
00301 
00302     DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Adding new rule to list\n"););
00303 
00304     /* set the index pointer to the start of this OTN's function list */
00305     idx = otn->opt_func;
00306 
00307     /* if there are no nodes on the function list... */
00308     if(idx == NULL)
00309     {
00310         /* calloc the list head */
00311         otn->opt_func = (OptFpList *) calloc(sizeof(OptFpList), sizeof(char));
00312 
00313         if(otn->opt_func == NULL)
00314         {
00315             FatalError("new node calloc failed: %s\n",
00316                        strerror(errno));
00317         }
00318 
00319         /* set the head function */
00320         otn->opt_func->OptTestFunc = func;
00321 
00322         idx = otn->opt_func;
00323     }
00324     else
00325     {
00326         /* walk to the end of the list */
00327         while(idx->next != NULL)
00328         {
00329             idx = idx->next;
00330         }
00331 
00332         /* allocate a new node on the end of the list */
00333         idx->next = (OptFpList *) calloc(sizeof(OptFpList), sizeof(char));
00334 
00335         if(idx->next == NULL)
00336         {
00337             FatalError("AddOptFuncToList new node calloc failed: %s\n",
00338                        strerror(errno));
00339         }
00340 
00341         /* move up to the new node */
00342         idx = idx->next;
00343 
00344         /* link the function to the new node */
00345         idx->OptTestFunc = func;
00346 
00347         DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Set OptTestFunc to %p\n", 
00348                     func););
00349     }
00350 
00351     return idx;
00352 }
00353 
00354 /****************************************************************************
00355  *
00356  * Function: AddRspFuncToList(int (*func)(), OptTreeNode *)
00357  *
00358  * Purpose: Adds Response function to OTN
00359  *
00360  * Arguments: (*func)() => function pointer to the response module
00361  *            otn =>  pointer to the current OptTreeNode
00362  *
00363  * Returns: void function
00364  *
00365  ***************************************************************************/
00366 void AddRspFuncToList(int (*func) (Packet *, struct _RspFpList *), OptTreeNode * otn, void *params)
00367 {
00368     RspFpList *idx;     /* index pointer */
00369 
00370     DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Adding response to list\n"););
00371 
00372     /* set the index pointer to the start of this OTN's function list */
00373     idx = otn->rsp_func;
00374 
00375     /* if there are no nodes on the function list... */
00376     if(idx == NULL)
00377     {
00378         /* calloc the list head */
00379         otn->rsp_func = (RspFpList *) calloc(sizeof(RspFpList), sizeof(char));
00380 
00381         if(otn->rsp_func == NULL)
00382         {
00383             FatalError("AddRspFuncToList new node calloc failed: %s\n", strerror(errno));
00384         }
00385         /* set the head function */
00386         otn->rsp_func->ResponseFunc = func;
00387         otn->rsp_func->params = params;
00388     }
00389     else
00390     {
00391         /* walk to the end of the list */
00392         while(idx->next != NULL)
00393         {
00394             idx = idx->next;
00395         }
00396 
00397         /* allocate a new node on the end of the list */
00398         idx->next = (RspFpList *) calloc(sizeof(RspFpList), sizeof(char));
00399 
00400         if(idx->next == NULL)
00401         {
00402             FatalError("AddRspFuncToList new node calloc failed: %s\n", strerror(errno));
00403         }
00404         /* link the function to the new node */
00405         idx->next->ResponseFunc = func;
00406         idx->next->params = params;
00407 
00408         DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Set ResponseFunc to %p\n", func););
00409     }
00410 }
00411 
00412 
00413 /************************* End Detection Plugin API ***************************/
00414 
00415 
00416 /************************** Preprocessor Plugin API ***************************/
00417 PreprocessKeywordList *PreprocessKeywords;
00418 PreprocessFuncNode *PreprocessList;
00419 
00420 void InitPreprocessors()
00421 {
00422     if(!pv.quiet_flag)
00423     {
00424         LogMessage("Initializing Preprocessors!\n");
00425     }
00426     SetupPortscan();
00427     SetupPortscanIgnoreHosts();
00428     SetupRpcDecode();
00429     SetupBo();
00430     SetupTelNeg();
00431     SetupStream4();
00432     SetupFrag2();
00433     SetupARPspoof();
00434     SetupConv();
00435     SetupScan2();
00436     SetupHttpInspect();
00437     SetupPerfMonitor();
00438     SetupFlow();
00439     SetupPsng();
00440     SetupFrag3();
00441     SetupXLINK2STATE();
00442 #ifdef CLAMAV
00443     SetupClamAV();
00444 #endif
00445 #ifdef GIDS
00446     SetupStickyDrop();
00447 #ifndef IPFW
00448     SetupBaitAndSwitch();
00449 #endif /* IPFW */
00450 #endif /* GIDS */
00451 }
00452 
00453 /****************************************************************************
00454  *
00455  * Function: RegisterPreprocessor(char *, void (*func)(u_char *))
00456  *
00457  * Purpose:  Associates a preprocessor statement with its function.
00458  *
00459  * Arguments: keyword => The option keyword to associate with the
00460  *                       preprocessor
00461  *            *func => function pointer to the handler
00462  *
00463  * Returns: void function
00464  *
00465  ***************************************************************************/
00466 void RegisterPreprocessor(char *keyword, void (*func) (u_char *))
00467 {
00468     PreprocessKeywordList *idx;
00469 
00470     DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Registering keyword:preproc => %s:%p\n", keyword, func););
00471 
00472     idx = PreprocessKeywords;
00473 
00474     if(idx == NULL)
00475     {
00476         /* alloc the node */
00477         PreprocessKeywords = (PreprocessKeywordList *) 
00478             calloc(sizeof(PreprocessKeywordList), sizeof(char));
00479 
00480         /* alloc space for the keyword */
00481         PreprocessKeywords->entry.keyword = (char *) calloc(strlen(keyword) + 1,
00482                 sizeof(char));
00483 
00484         /* copy the keyword into the struct */
00485         strncpy(PreprocessKeywords->entry.keyword, keyword, strlen(keyword)+1);
00486 
00487         /* set the function pointer to the keyword handler function */
00488         PreprocessKeywords->entry.func = (void *) func;
00489     }
00490     else
00491     {
00492         /* loop to the end of the list */
00493         while(idx->next != NULL)
00494         {
00495             if(!strcasecmp(idx->entry.keyword, keyword))
00496             {
00497                 FatalError("%s(%d) => Duplicate preprocessor keyword!\n",
00498                            file_name, file_line);
00499             }
00500             idx = idx->next;
00501         }
00502 
00503         idx->next = (PreprocessKeywordList *) 
00504             calloc(sizeof(PreprocessKeywordList), sizeof(char));
00505 
00506         idx = idx->next;
00507 
00508         /* alloc space for the keyword */
00509         idx->entry.keyword = (char *) calloc(strlen(keyword) + 1, sizeof(char));
00510 
00511         /* copy the keyword into the struct */
00512         strncpy(idx->entry.keyword, keyword, strlen(keyword)+1);
00513 
00514         /* set the function pointer to the keyword handler function */
00515         idx->entry.func = (void *) func;
00516     }
00517 }
00518 
00519 
00520 
00521 
00522 /****************************************************************************
00523  *
00524  * Function: DumpPreprocessors()
00525  *
00526  * Purpose:  Prints the keyword->preprocess list
00527  *
00528  * Arguments: None.
00529  *
00530  * Returns: void function
00531  *
00532  ***************************************************************************/
00533 void DumpPreprocessors()
00534 {
00535     PreprocessKeywordList *idx;
00536 
00537     if(pv.quiet_flag)
00538         return;
00539     idx = PreprocessKeywords;
00540 
00541     printf("-------------------------------------------------\n");
00542     printf(" Keyword     |       Preprocessor @ \n");
00543     printf("-------------------------------------------------\n");
00544     while(idx != NULL)
00545     {
00546         printf("%-13s:       %p\n", idx->entry.keyword, idx->entry.func);
00547         idx = idx->next;
00548     }
00549     printf("-------------------------------------------------\n\n");
00550 }
00551 
00552 
00553 PreprocessFuncNode *AddFuncToPreprocList(void (*func) (Packet *, void *))
00554 {
00555     PreprocessFuncNode *idx;
00556 
00557     idx = PreprocessList;
00558 
00559     if(idx == NULL)
00560     {
00561         PreprocessList = (PreprocessFuncNode *)
00562             calloc(sizeof(PreprocessFuncNode), sizeof(char));
00563 
00564         PreprocessList->func = func;
00565 
00566         idx = PreprocessList;
00567     }
00568     else
00569     {
00570         while(idx->next != NULL)
00571             idx = idx->next;
00572 
00573         idx->next = (PreprocessFuncNode *)
00574             calloc(sizeof(PreprocessFuncNode), sizeof(char));
00575 
00576         idx = idx->next;
00577         idx->func = func;
00578     }
00579 
00580     return idx;
00581 }
00582 
00583 /************************ End Preprocessor Plugin API  ************************/
00584 
00585 /***************************** Output Plugin API  *****************************/
00586 OutputKeywordList *OutputKeywords;
00587 OutputFuncNode *AlertList;
00588 OutputFuncNode *LogList;
00589 OutputFuncNode *AppendOutputFuncList(void (*) (Packet *,char *,void *,Event*),
00590                 void *, OutputFuncNode *);
00591 
00592 
00593 void InitOutputPlugins()
00594 {
00595     if(!pv.quiet_flag)
00596     {
00597         LogMessage("Initializing Output Plugins!\n");
00598     }
00599     AlertSyslogSetup();
00600     LogTcpdumpSetup();
00601     DatabaseSetup();
00602     AlertFastSetup();
00603     AlertFullSetup();
00604 #ifndef WIN32
00605     /* Win32 doesn't support AF_UNIX sockets */
00606     AlertUnixSockSetup();
00607 #endif /* !WIN32 */
00608     AlertCSVSetup();
00609     LogNullSetup();
00610     UnifiedSetup();
00611     LogAsciiSetup();
00612 #ifdef LINUX
00613     /* This uses linux only capabilities */
00614     AlertSFSocket_Setup();
00615 #endif
00616 #ifdef GIDS
00617     AlertStickyDSetup();
00618 #ifndef IPFW
00619     AlertBandSetup();
00620 #endif /* IPFW */
00621 #endif /* GIDS */
00622 #ifdef HAVE_LIBPRELUDE
00623     AlertPreludeSetup();
00624 #endif
00625 }
00626 
00627 int ActivateOutputPlugin(char *plugin_name, char *plugin_options)
00628 {
00629     OutputKeywordNode *plugin;
00630      
00631     if(!plugin_name)
00632         return -1;
00633     
00634     /* get the output plugin node */
00635     if(!(plugin = GetOutputPlugin(plugin_name)))
00636         return -1;
00637 
00638     switch(plugin->node_type)
00639     {
00640         case NT_OUTPUT_SPECIAL: /* both alert & logging in one plugin */
00641             plugin->func(plugin_options);
00642             break;
00643         case NT_OUTPUT_ALERT:
00644             plugin->func(plugin_options);
00645             break;
00646         case NT_OUTPUT_LOG:
00647             plugin->func(plugin_options);
00648             break;
00649     }
00650 #ifdef GIDS
00651     if(SppStickydIsRunning())
00652      {
00653        if(!StickyDOutputInitRun())
00654         {
00655            plugin = GetOutputPlugin("alert_StickyD");
00656 
00657            if(plugin != NULL)
00658            {
00659               plugin->func(NULL);
00660            }
00661            else
00662            {
00663              LogMessage("Something went wrong with auto enable of alert_StickyD\n\n\n\n");
00664            }
00665         }
00666         else
00667         {
00668             LogMessage("Great, I'm glad you found the alert_StickyD output plugin but there is no need to enable it in the conf as we do it for you \n");
00669         }
00670      }
00671 #ifndef IPFW
00672 
00673     if(BaitAndSwitchIsRunning())
00674      {         
00675        if(!BaitAndSwitchOutputInitRun())
00676         { 
00677            plugin = GetOutputPlugin("alert_BandS");
00678 
00679            if(plugin != NULL)
00680            {
00681               plugin->func(NULL);
00682            }
00683            else             
00684            {
00685              LogMessage("Something went wrong with auto enable of alert_BandS\n\n\n\n");
00686            }
00687         }
00688         else
00689         {
00690             LogMessage("Great, I'm glad you found the alert_BandS output plugin but there is no need to enable it in the conf as we do it for you \n");
00691         } 
00692      }
00693 #endif /* IPFW */
00694 #endif /* GIDS */                 
00695 
00696     return 0;
00697 }
00698 
00699 OutputKeywordNode *GetOutputPlugin(char *plugin_name)
00700 {
00701     OutputKeywordList *list_node;
00702 
00703     if(!plugin_name)
00704         return NULL;
00705 
00706     list_node = OutputKeywords;
00707 
00708     while(list_node)
00709     {
00710         if(strcasecmp(plugin_name, list_node->entry.keyword) == 0)
00711             return &(list_node->entry);
00712         list_node = list_node->next;
00713     }
00714     FatalError("unknown output plugin: '%s'", 
00715                plugin_name);
00716 
00717     return NULL;
00718 }
00719 
00720 
00721 /****************************************************************************
00722  *
00723  * Function: RegisterOutputPlugin(char *, void (*func)(Packet *, u_char *))
00724  *
00725  * Purpose:  Associates an output statement with its function.
00726  *
00727  * Arguments: keyword => The output keyword to associate with the
00728  *                       output processor
00729  *            type => alert or log types
00730  *            *func => function pointer to the handler
00731  *
00732  * Returns: void function
00733  *
00734  ***************************************************************************/
00735 void RegisterOutputPlugin(char *keyword, int type, void (*func) (u_char *))
00736 {
00737     OutputKeywordList *idx;
00738 
00739     DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Registering keyword:output => %s:%p\n", 
00740                             keyword, func););
00741 
00742     idx = OutputKeywords;
00743 
00744     if(idx == NULL)
00745     {
00746         /* alloc the node */
00747         OutputKeywords = (OutputKeywordList *) calloc(sizeof(OutputKeywordList),
00748                 sizeof(char));
00749 
00750         idx = OutputKeywords;
00751     }
00752     else
00753     {
00754         /* loop to the end of the list */
00755         while(idx->next != NULL)
00756         {
00757             if(!strcasecmp(idx->entry.keyword, keyword))
00758             {
00759                 FatalError("%s(%d) => Duplicate output keyword!\n", 
00760                         file_name, file_line);
00761             }
00762             idx = idx->next;
00763         }
00764 
00765         idx->next = (OutputKeywordList *) calloc(sizeof(OutputKeywordList), 
00766                 sizeof(char));
00767 
00768         idx = idx->next;
00769     }
00770 
00771     /* alloc space for the keyword */
00772     idx->entry.keyword = (char *) calloc(strlen(keyword) + 1, sizeof(char));
00773 
00774     /* copy the keyword into the struct */
00775     strncpy(idx->entry.keyword, keyword, strlen(keyword)+1);
00776 
00777     /*
00778      * set the plugin type, needed to determine whether an overriding command
00779      * line arg has been specified
00780      */
00781     idx->entry.node_type = (char) type;
00782 
00783     /* set the function pointer to the keyword handler function */
00784     idx->entry.func = (void *) func;
00785 }
00786 
00787 
00788 /****************************************************************************
00789  *
00790  * Function: DumpOutputPlugins()
00791  *
00792  * Purpose:  Prints the keyword->preprocess list
00793  *
00794  * Arguments: None.
00795  *
00796  * Returns: void function
00797  *
00798  ***************************************************************************/
00799 void DumpOutputPlugins()
00800 {
00801     OutputKeywordList *idx;
00802 
00803     if(pv.quiet_flag)
00804         return;
00805 
00806     idx = OutputKeywords;
00807 
00808     printf("-------------------------------------------------\n");
00809     printf(" Keyword     |          Output @ \n");
00810     printf("-------------------------------------------------\n");
00811     while(idx != NULL)
00812     {
00813         printf("%-13s:       %p\n", idx->entry.keyword, idx->entry.func);
00814         idx = idx->next;
00815     }
00816     printf("-------------------------------------------------\n\n");
00817 }
00818 
00819 extern ListHead *head_tmp;
00820 
00821 void AddFuncToOutputList(void (*func) (Packet *, char *, void *, Event *),
00822         char node_type, void *arg)
00823 {
00824     switch(node_type)
00825     {
00826         case NT_OUTPUT_ALERT:
00827             if(head_tmp != NULL)
00828                 head_tmp->AlertList = AppendOutputFuncList(func, arg,
00829                         head_tmp->AlertList);
00830             else
00831                 AlertList = AppendOutputFuncList(func, arg, AlertList);
00832             break;
00833 
00834         case NT_OUTPUT_LOG:
00835             if(head_tmp != NULL)
00836                 head_tmp->LogList = AppendOutputFuncList(func, arg,
00837                         head_tmp->LogList);
00838             else
00839                 LogList = AppendOutputFuncList(func, arg, LogList);
00840             break;
00841 
00842         default:
00843             /* just to be error-prone */
00844             FatalError("Unknown nodetype: %i. Possible bug, please report\n",
00845                     node_type);
00846     }
00847 
00848     return;
00849 }
00850 
00851 
00852 OutputFuncNode *AppendOutputFuncList(
00853         void (*func) (Packet *, char *, void *, Event *),
00854         void *arg, OutputFuncNode * list)
00855 {
00856     OutputFuncNode *idx = list;
00857 
00858     if(idx == NULL)
00859     {
00860         idx = (OutputFuncNode *) calloc(sizeof(OutputFuncNode), sizeof(char));
00861         idx->func = func;
00862         idx->arg = arg;
00863         list = idx;
00864     }
00865     else
00866     {
00867         while(idx->next != NULL)
00868             idx = idx->next;
00869 
00870         idx->next = (OutputFuncNode *) calloc(sizeof(OutputFuncNode),
00871                 sizeof(char));
00872         idx = idx->next;
00873         idx->func = func;
00874         idx->arg = arg;
00875     }
00876 
00877     idx->next = NULL;
00878 
00879     return list;
00880 }
00881 
00882 /*
00883  * frees the existing OutputList ands sets it a single node for the
00884  * function argument
00885  */
00886 void SetOutputList(void (*func) (Packet *, char *, void *, Event *),
00887         char node_type, void *arg)
00888 {
00889     OutputFuncNode *idx;
00890     OutputFuncNode *prev;
00891 
00892     switch(node_type)
00893     {
00894         case NT_OUTPUT_ALERT:
00895             prev = AlertList;
00896             break;
00897 
00898         case NT_OUTPUT_LOG:
00899             prev = LogList;
00900             break;
00901 
00902         default:
00903             return;
00904     }
00905 
00906     while(prev != NULL)
00907     {
00908         idx = prev->next;
00909         free(prev);
00910         prev = idx;
00911     }
00912 
00913     switch(node_type)
00914     {
00915         case NT_OUTPUT_ALERT:
00916             AlertList = prev;
00917             break;
00918 
00919         case NT_OUTPUT_LOG:
00920             LogList = prev;
00921             break;
00922 
00923         default:
00924             return;
00925     }
00926 
00927     AddFuncToOutputList(func, node_type, arg);
00928 
00929     return;
00930 }
00931 
00932 
00933 
00934 /*************************** End Output Plugin API  ***************************/
00935 
00936 
00937 /************************** Miscellaneous Functions  **************************/
00938 
00939 int PacketIsIP(Packet * p)
00940 {
00941     if(p->iph != NULL)
00942         return 1;
00943 
00944     return 0;
00945 }
00946 
00947 
00948 
00949 int PacketIsTCP(Packet * p)
00950 {
00951     if(p->iph != NULL && p->tcph != NULL)
00952         return 1;
00953 
00954     return 0;
00955 }
00956 
00957 
00958 
00959 int PacketIsUDP(Packet * p)
00960 {
00961     if(p->iph != NULL && p->udph != NULL)
00962         return 1;
00963 
00964     return 0;
00965 }
00966 
00967 
00968 
00969 int PacketIsICMP(Packet * p)
00970 {
00971     if(p->iph != NULL && p->icmph != NULL)
00972         return 1;
00973 
00974     return 0;
00975 }
00976 
00977 
00978 
00979 int DestinationIpIsHomenet(Packet * p)
00980 {
00981     if((p->iph->ip_dst.s_addr & pv.netmask) == pv.homenet)
00982     {
00983         return 1;
00984     }
00985     return 0;
00986 }
00987 
00988 
00989 
00990 int SourceIpIsHomenet(Packet * p)
00991 {
00992     if((p->iph->ip_src.s_addr & pv.netmask) == pv.homenet)
00993     {
00994         return 1;
00995     }
00996     return 0;
00997 }
00998 
00999 int CheckNet(struct in_addr * compare, struct in_addr * compare2)
01000 {
01001     if(compare->s_addr == compare2->s_addr)
01002     {
01003         return 1;
01004     }
01005     return 0;
01006 }
01007 
01008 /* functions to aid in cleaning up aftre plugins */
01009 void AddFuncToRestartList(void (*func) (int, void *), void *arg)
01010 {
01011     PluginRestartList = AddFuncToSignalList(func, arg, PluginRestartList);
01012 }
01013 
01014 void AddFuncToCleanExitList(void (*func) (int, void *), void *arg)
01015 {
01016     PluginCleanExitList = AddFuncToSignalList(func, arg, PluginCleanExitList);
01017 }
01018 
01019 void AddFuncToShutdownList(void (*func) (int, void *), void *arg)
01020 {
01021     PluginShutdownList = AddFuncToSignalList(func, arg, PluginShutdownList);
01022 }
01023 
01024 PluginSignalFuncNode *AddFuncToSignalList(void (*func) (int, void *), void *arg,
01025                                           PluginSignalFuncNode * list)
01026 {
01027     PluginSignalFuncNode *idx;
01028 
01029     idx = list;
01030 
01031     if(idx == NULL)
01032     {
01033         idx = (PluginSignalFuncNode *) calloc(sizeof(PluginSignalFuncNode), sizeof(char));
01034 
01035         idx->func = func;
01036         idx->arg = arg;
01037         list = idx;
01038     }
01039     else
01040     {
01041         while(idx->next != NULL)
01042             idx = idx->next;
01043 
01044         idx->next = (PluginSignalFuncNode *) calloc(sizeof(PluginSignalFuncNode), sizeof(char));
01045 
01046         idx = idx->next;
01047         idx->func = func;
01048         idx->arg = arg;
01049     }
01050     idx->next = NULL;
01051 
01052     return list;
01053 }
01054 
01055 
01056 /****************************************************************************
01057  *
01058  * Function: GetUniqueName(char * iface)
01059  *
01060  * Purpose: To return a string that has a high probability of being unique
01061  *          for a given sensor.
01062  *
01063  * Arguments: char * iface - The network interface you are sniffing
01064  *
01065  * Returns: A char * -- its a static char * so you should not free it
01066  *
01067  ***************************************************************************/
01068 char *GetUniqueName(char * iface)
01069 {
01070     char * rptr;
01071     static char uniq_name[256];
01072 
01073     if (iface == NULL) LogMessage("Interface is NULL. Name may not be unique for the host\n");
01074 #ifndef WIN32
01075     rptr = GetIP(iface); 
01076     if(rptr == NULL || !strcmp(rptr, "unknown"))
01077 #endif
01078     {
01079         snprintf(uniq_name, 255, "%s:%s\n",GetHostname(),iface);
01080         rptr = uniq_name; 
01081     }
01082     if (pv.verbose_flag) LogMessage("Node unique name is: %s\n", rptr);
01083     return rptr;
01084 }    
01085 
01086 /****************************************************************************
01087  *
01088  * Function: GetIP(char * iface)
01089  *
01090  * Purpose: To return a string representing the IP address for an interface
01091  *
01092  * Arguments: char * iface - The network interface you want to find an IP
01093  *            address for.
01094  *
01095  * Returns: A char * -- make sure you call free on this when you are done
01096  *          with it.
01097  *
01098  ***************************************************************************/
01099 char *GetIP(char * iface)
01100 {
01101     struct ifreq ifr;
01102     struct sockaddr_in *addr;
01103     int s;
01104 
01105     if(iface)
01106     {
01107         /* Set up a dummy socket just so we can use ioctl to find the
01108            ip address of the interface */
01109         s = socket(PF_INET, SOCK_DGRAM, 0);
01110         if(s == -1)
01111         {
01112             FatalError("Problem establishing socket to find IP address for interface: %s\n", iface);
01113         }
01114 
01115         strncpy(ifr.ifr_name, iface, strlen(iface) + 1);
01116 
01117 #ifndef WIN32
01118         if(ioctl(s, SIOCGIFADDR, &ifr) < 0) return NULL;
01119         else
01120 #endif
01121         {
01122             addr = (struct sockaddr_in *) &ifr.ifr_broadaddr;
01123         }
01124         close(s);
01125 
01126         return strdup(inet_ntoa(addr->sin_addr));
01127     }
01128     else
01129     {
01130         return "unknown";
01131     }
01132 }
01133 
01134 /****************************************************************************
01135  *
01136  * Function: GetHostname()
01137  *
01138  * Purpose: To return a string representing the hostname
01139  *
01140  * Arguments: None
01141  *
01142  * Returns: A static char * representing the hostname. 
01143  *
01144  ***************************************************************************/
01145 char *GetHostname()
01146 {
01147 #ifdef WIN32
01148     DWORD bufflen = 256;
01149     static char buff[256];
01150     GetComputerName(buff, &bufflen);
01151     return buff;
01152 #else
01153         char * error = "unknown";
01154     if(getenv("HOSTNAME")) return getenv("HOSTNAME");
01155     else if(getenv("HOST")) return getenv("HOST");
01156     else return error;
01157 #endif
01158 }
01159 
01160 /****************************************************************************
01161  *
01162  * Function: GetTimestamp(register const struct timeval *tvp, int tz)
01163  *
01164  * Purpose: Get an ISO-8601 formatted timestamp for tvp within the tz
01165  *          timezone. 
01166  *
01167  * Arguments: tvp is a timeval pointer. tz is a timezone. 
01168  *
01169  * Returns: char * -- You must free this char * when you are done with it.
01170  *
01171  ***************************************************************************/
01172 char *GetTimestamp(register const struct timeval *tvp, int tz)
01173 {
01174     struct tm *lt;  /* localtime */
01175     char * buf;
01176     int msec;
01177 
01178     buf = (char *)calloc(SMALLBUFFER, sizeof(char));
01179 
01180     msec = tvp->tv_usec / 1000;
01181 
01182     if(pv.use_utc == 1)
01183     {
01184         lt = gmtime((time_t *)&tvp->tv_sec);
01185         snprintf(buf, SMALLBUFFER, "%04i-%02i-%02i %02i:%02i:%02i.%03i",
01186                 1900 + lt->tm_year, lt->tm_mon + 1, lt->tm_mday,
01187                 lt->tm_hour, lt->tm_min, lt->tm_sec, msec);
01188     }
01189     else
01190     {
01191         lt = localtime((time_t *)&tvp->tv_sec);
01192         snprintf(buf, SMALLBUFFER,
01193                 "%04i-%02i-%02i %02i:%02i:%02i.%03i+%03i",
01194                 1900 + lt->tm_year, lt->tm_mon + 1, lt->tm_mday,
01195                 lt->tm_hour, lt->tm_min, lt->tm_sec, msec, tz);
01196     }
01197 
01198     return buf;
01199 }
01200 
01201 /****************************************************************************
01202  *
01203  * Function: GetLocalTimezone()
01204  *
01205  * Purpose: Find the offset from GMT for current host
01206  *
01207  * Arguments: none 
01208  *
01209  * Returns: int representing the offset from GMT
01210  *
01211  ***************************************************************************/
01212 int GetLocalTimezone()
01213 {
01214     time_t      ut;
01215     struct tm * ltm;
01216     long        seconds_away_from_utc;
01217 
01218     time(&ut);
01219     ltm = localtime(&ut);
01220 
01221 #if defined(WIN32) || defined(SOLARIS) || defined(AIX)
01222     /* localtime() sets the global timezone variable,
01223        which is defined in <time.h> */
01224     seconds_away_from_utc = timezone;
01225 #else
01226     seconds_away_from_utc = ltm->tm_gmtoff;
01227 #endif
01228 
01229     return  seconds_away_from_utc/3600;
01230 }
01231 
01232 /****************************************************************************
01233  *
01234  * Function: GetCurrentTimestamp()
01235  *
01236  * Purpose: Generate an ISO-8601 formatted timestamp for the current time.
01237  *
01238  * Arguments: none 
01239  *
01240  * Returns: char * -- You must free this char * when you are done with it.
01241  *
01242  ***************************************************************************/
01243 char *GetCurrentTimestamp()
01244 {
01245     struct tm *lt;
01246     struct timezone tz;
01247     struct timeval tv;
01248     struct timeval *tvp;
01249     char * buf;
01250     int tzone;
01251     int msec;
01252 
01253     buf = (char *)calloc(SMALLBUFFER, sizeof(char));
01254 
01255     bzero((char *)&tz,sizeof(tz));
01256     gettimeofday(&tv,&tz);
01257     tvp = &tv;
01258 
01259     msec = tvp->tv_usec/1000;
01260 
01261     if(pv.use_utc == 1)
01262     {
01263         lt = gmtime((time_t *)&tvp->tv_sec);
01264         snprintf(buf, SMALLBUFFER, "%04i-%02i-%02i %02i:%02i:%02i.%03i",
01265                 1900 + lt->tm_year, lt->tm_mon + 1, lt->tm_mday,
01266                 lt->tm_hour, lt->tm_min, lt->tm_sec, msec);
01267     }
01268     else
01269     {
01270         lt = localtime((time_t *)&tvp->tv_sec);
01271 
01272         tzone = GetLocalTimezone();
01273 
01274         snprintf(buf, SMALLBUFFER,
01275                 "%04i-%02i-%02i %02i:%02i:%02i.%03i+%03i",
01276                 1900 + lt->tm_year, lt->tm_mon + 1, lt->tm_mday,
01277                 lt->tm_hour, lt->tm_min, lt->tm_sec, msec, tzone);
01278     }
01279 
01280     return buf;
01281 }
01282 
01283 /****************************************************************************
01284  * Function: base64(char * xdata, int length)
01285  *
01286  * Purpose: Insert data into the database
01287  *
01288  * Arguments: xdata  => pointer to data to base64 encode
01289  *            length => how much data to encode 
01290  *
01291  * Make sure you allocate memory for the output before you pass
01292  * the output pointer into this function. You should allocate 
01293  * (1.5 * length) bytes to be safe.
01294  *
01295  * Returns: data base64 encoded as a char *
01296  *
01297  ***************************************************************************/
01298 char * base64(u_char * xdata, int length)
01299 {
01300     int count, cols, bits, c, char_count;
01301     unsigned char alpha[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
01302     char * payloadptr;
01303     char * output;
01304     char_count = 0;
01305     bits = 0;
01306     cols = 0;
01307 
01308     output = (char *)malloc( (unsigned int) (length * 1.5 + 4) );
01309 
01310     payloadptr = output;
01311 
01312     for(count = 0; count < length; count++)
01313     {
01314         c = xdata[count];
01315 
01316         if(c > 255)
01317         {
01318             ErrorMessage("plugbase.c->base64(): encountered char > 255 (decimal %d)\n If you see this error message a char is more than one byte on your machine\n This means your base64 results can not be trusted", c);
01319         }
01320 
01321         bits += c;
01322         char_count++;
01323 
01324         if(char_count == 3)
01325         {
01326             *output = alpha[bits >> 18]; output++;
01327             *output = alpha[(bits >> 12) & 0x3f]; output++;
01328             *output = alpha[(bits >> 6) & 0x3f]; output++;
01329             *output = alpha[bits & 0x3f]; output++; 
01330             cols += 4;
01331             if(cols == 72)
01332             {
01333                 *output = '\n'; output++;
01334                 cols = 0;
01335             }
01336             bits = 0;
01337             char_count = 0;
01338         }
01339         else
01340         {
01341             bits <<= 8;
01342         }
01343     }
01344 
01345     if(char_count != 0)
01346     {
01347         bits <<= 16 - (8 * char_count);
01348         *output = alpha[bits >> 18]; output++;
01349         *output = alpha[(bits >> 12) & 0x3f]; output++;
01350         if(char_count == 1)
01351         {
01352             *output = '='; output++;
01353             *output = '='; output++;
01354         }
01355         else
01356         {
01357             *output = alpha[(bits >> 6) & 0x3f]; 
01358             output++; *output = '='; 
01359             output++;
01360         }
01361     }
01362     *output = '\0';
01363     return payloadptr;
01364 } 
01365 
01366 /****************************************************************************
01367  *
01368  * Function: ascii(u_char *xdata, int length)
01369  *
01370  * Purpose: This function takes takes a buffer "xdata" and its length then
01371  *          returns a string of only the printible ASCII characters.
01372  *
01373  * Arguments: xdata is the buffer, length is the length of the buffer in
01374  *            bytes
01375  *
01376  * Returns: char * -- You must free this char * when you are done with it.
01377  *
01378  ***************************************************************************/
01379 char *ascii(u_char *xdata, int length)
01380 {
01381      char *d_ptr, *ret_val;
01382      int i,count = 0;
01383      int size;
01384      
01385      if(xdata == NULL)
01386      {
01387          return NULL;         
01388      }
01389      
01390      for(i=0;i<length;i++)
01391      {
01392          if(xdata[i] == '<')
01393              count+=4;              /* &lt; */
01394          else if(xdata[i] == '&')
01395              count+=5;              /* &amp; */
01396          else if(xdata[i] == '>')   /* &gt;  */
01397              count += 4;
01398      }
01399 
01400      size = length + count + 1;
01401      ret_val = (char *) malloc(size);
01402      
01403      if(ret_val == NULL)
01404      {
01405          LogMessage("plugbase.c: ascii(): Out of memory, can't log anything!\n");
01406          return NULL;
01407      }
01408      
01409      memset(ret_val, '\0',(length + count + 1));
01410      
01411      d_ptr = ret_val; 
01412      
01413      for(i=0;i<length;i++)
01414      {
01415          if((xdata[i] > 0x1F) && (xdata[i] < 0x7F))
01416          {
01417              if(xdata[i] == '<')
01418              {
01419                  strncpy(d_ptr, "&lt;", size - (d_ptr - ret_val));
01420                  d_ptr+=4;
01421              }
01422              else if(xdata[i] == '&')
01423              {
01424                  strncpy(d_ptr, "&amp;", size - (d_ptr - ret_val));
01425                  d_ptr += 5;
01426              }
01427              else if(xdata[i] == '>')
01428              {
01429                  strncpy(d_ptr, "&gt;", size - (d_ptr - ret_val));
01430                  d_ptr += 4;
01431              }
01432              else
01433              {
01434                  *d_ptr++ = xdata[i];
01435              }
01436          }
01437          else
01438          {
01439              *d_ptr++ = '.';
01440          }        
01441      }
01442      
01443      *d_ptr++ = '\0';
01444      
01445      return ret_val;
01446 }
01447 
01448 /****************************************************************************
01449  *
01450  * Function: hex(u_char *xdata, int length)
01451  *
01452  * Purpose: This function takes takes a buffer "xdata" and its length then
01453  *          returns a string of hex with no spaces
01454  *
01455  * Arguments: xdata is the buffer, length is the length of the buffer in
01456  *            bytes
01457  *
01458  * Returns: char * -- You must free this char * when you are done with it.
01459  *
01460  ***************************************************************************/
01461 char *hex(u_char *xdata, int length)
01462 {
01463     int x;
01464     char *rval;
01465     char *buf;
01466 
01467     buf = (char *)malloc(length * 2 + 1);
01468     rval = buf;
01469 
01470     for(x=0; x < length; x++)
01471     {
01472         snprintf(buf, 3, "%02X", xdata[x]);
01473         buf += 2;
01474     } 
01475 
01476     rval[length * 2] = '\0';
01477 
01478     return rval;
01479 }
01480 
01481 
01482 
01483 char *fasthex(u_char *xdata, int length)
01484 {
01485     char conv[] = "0123456789ABCDEF";
01486     char *retbuf = NULL; 
01487     char *index;
01488     char *end;
01489     char *ridx;
01490 
01491     index = xdata;
01492     end = xdata + length;
01493     retbuf = (char *) calloc((length*2)+1, sizeof(char));
01494     ridx = retbuf;
01495 
01496     while(index < end)
01497     {
01498         *ridx++ = conv[((*index & 0xFF)>>4)];
01499         *ridx++ = conv[((*index & 0xFF)&0x0F)];
01500         index++;
01501     }
01502 
01503     return retbuf;
01504 }
01505 

Generated on Sun May 14 14:51:15 2006 by  doxygen 1.4.2