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

spo_unified.c

Go to the documentation of this file.
00001 /*
00002 ** Copyright (C) 1998-2005 Martin Roesch <roesch@sourcefire.com>
00003 **
00004 ** This program is free software; you can redistribute it and/or modify
00005 ** it under the terms of the GNU General Public License as published by
00006 ** the Free Software Foundation; either version 2 of the License, or
00007 ** (at your option) any later version.
00008 **
00009 ** This program is distributed in the hope that it will be useful,
00010 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 ** GNU General Public License for more details.
00013 **
00014 ** You should have received a copy of the GNU General Public License
00015 ** along with this program; if not, write to the Free Software
00016 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017 */
00018 
00019 /* $Id$ */
00020 
00021 /* spo_unified 
00022  * 
00023  * Purpose:
00024  *
00025  * This plugin generates the new unified alert and logging formats
00026  *
00027  * Arguments:
00028  *   
00029  * filename of the alert and log spools
00030  *
00031  * Effect:
00032  *
00033  * Packet logs are written (quickly) to a unified output file
00034  *
00035  * Comments:
00036  *
00037  * The future...
00038  */
00039 
00040 #ifdef HAVE_CONFIG_H
00041 #include "config.h"
00042 #endif
00043 
00044 #include <sys/types.h>
00045 #include <stdlib.h>
00046 #include <string.h>
00047 #ifdef HAVE_STRINGS_H
00048 #include <strings.h>
00049 #endif
00050 #include <errno.h>
00051 #include <time.h>
00052 
00053 #include "decode.h"
00054 #include "rules.h"
00055 #include "util.h"
00056 #include "plugbase.h"
00057 #include "spo_plugbase.h"
00058 #include "parser.h"
00059 #include "debug.h"
00060 #include "mstring.h"
00061 #include "stream.h"
00062 #include "event.h"
00063 #include "generators.h"
00064 #include "snort_packet_header.h"
00065 
00066 #include "snort.h"
00067 
00068 #ifdef GIDS
00069 #include "inline.h"
00070 #endif
00071 
00072 #define SNORT_MAGIC     0xa1b2c3d4
00073 #define ALERT_MAGIC     0xDEAD4137  /* alert magic, just accept it */
00074 #define LOG_MAGIC       0xDEAD1080  /* log magic, what's 31337-speak for G? */
00075 #define SNORT_VERSION_MAJOR   1
00076 #define SNORT_VERSION_MINOR   2
00077 
00078 /* From fpdetect.c, for logging reassembled packets */
00079 extern u_int16_t   event_id;
00080 
00081 
00082 /* file header for snort unified format log files
00083  *
00084  * Identical to pcap file header, used for portability where the libpcap
00085  * might not be used after the pa_engine code becomes available
00086  */ 
00087 typedef struct _UnifiedLogFileHeader
00088 {
00089     u_int32_t magic;
00090     u_int16_t version_major;
00091     u_int16_t version_minor;
00092     u_int32_t timezone;
00093     u_int32_t sigfigs;
00094     u_int32_t snaplen;
00095     u_int32_t linktype;
00096 } UnifiedLogFileHeader;
00097 
00098 typedef struct _UnifiedAlertFileHeader
00099 {
00100     u_int32_t magic;
00101     u_int32_t version_major;
00102     u_int32_t version_minor;
00103     u_int32_t timezone;
00104 } UnifiedAlertFileHeader;
00105 
00106 
00107 /* unified log packet header format 
00108  *
00109  * One of these per packet in the log file, the packets are appended in the 
00110  * file after each UnifiedLog header (extended pcap format) 
00111  */
00112 typedef struct _UnifiedLog
00113 {
00114     Event event;
00115     u_int32_t flags;       /* bitmap for interesting flags */
00116     SnortPktHeader pkth;   /* SnortPktHeader schtuff */
00117 } UnifiedLog;
00118 
00119 
00120 /* Unified alert message format
00121  *
00122  * One per event notification, all the important data for people to know
00123  */
00124 typedef struct _UnifiedAlert
00125 {
00126     Event event;
00127     struct timeval ts;         /* event timestamp */
00128     u_int32_t sip;             /* src ip */
00129     u_int32_t dip;             /* dest ip */
00130     u_int16_t sp;              /* src port */
00131     u_int16_t dp;              /* dest port */
00132     u_int32_t protocol;        /* protocol id */
00133     u_int32_t flags;           /* any other flags (fragmented, etc) */
00134 } UnifiedAlert;
00135 
00136 
00137 
00138 /* ----------------External variables -------------------- */
00139 extern OptTreeNode *otn_tmp;
00140 extern int thiszone;
00141 
00142 #ifdef GIDS
00143 #ifndef IPFW
00144 extern ipq_packet_msg_t *g_m;
00145 #endif
00146 #endif
00147 
00148 /* ------------------ Data structures --------------------------*/
00149 typedef struct _UnifiedConfig
00150 {
00151     char *filename;
00152     FILE *stream;
00153     unsigned int limit;
00154     unsigned int current;
00155 } UnifiedConfig;
00156 
00157 typedef struct _FileHeader
00158 {
00159     u_int32_t magic;
00160     u_int32_t flags;
00161 } FileHeader;
00162 
00163 typedef struct _DataHeader
00164 {
00165     u_int32_t type;
00166     u_int32_t length;
00167 } DataHeader;
00168 
00169 #define UNIFIED_MAGIC 0x2dac5ceb
00170 
00171 #define UNIFIED_TYPE_ALERT          0x1
00172 #define UNIFIED_TYPE_PACKET_ALERT   0x2
00173 
00174 /* -------------------- Global Variables ----------------------*/
00175 #ifdef GIDS
00176 EtherHdr g_ethernet;
00177 #endif
00178 
00179 /* -------------------- Local Functions -----------------------*/
00180 static UnifiedConfig *UnifiedParseArgs(char *, char *);
00181 static void UnifiedCleanExit(int, void *);
00182 static void UnifiedRestart(int, void *);
00183 
00184 /* Unified Output functions */
00185 static void UnifiedInit(u_char *);
00186 static void UnifiedInitFile(UnifiedConfig *);
00187 static void UnifiedRotateFile(UnifiedConfig *);
00188 static void UnifiedLogAlert(Packet *, char *, void *, Event *);
00189 static void UnifiedLogPacketAlert(Packet *, char *, void *, Event *);
00190 static void RealUnifiedLogAlert(Packet *, char *, void *, Event *, 
00191         DataHeader *);
00192 static void RealUnifiedLogPacketAlert(Packet *, char *, void *, Event *, 
00193         DataHeader *);
00194 void RealUnifiedLogStreamAlert(Packet *,char *,void *,Event *,DataHeader *);
00195 static void UnifiedRotateFile(UnifiedConfig *data);
00196 
00197 /* Unified Alert functions (deprecated) */
00198 static void UnifiedAlertInit(u_char *);
00199 static void UnifiedInitAlertFile(UnifiedConfig *);
00200 static void UnifiedAlertRotateFile(UnifiedConfig *data);
00201 static void OldUnifiedLogAlert(Packet *, char *, void *, Event *);
00202 
00203 
00204 /* Unified Packet Log functions (deprecated) */
00205 static void UnifiedLogInit(u_char *);
00206 static void UnifiedInitLogFile(UnifiedConfig *);
00207 static void OldUnifiedLogPacketAlert(Packet *, char *, void *, Event *);
00208 static void UnifiedLogRotateFile(UnifiedConfig *data);
00209 
00210 
00211 static UnifiedConfig *unifiedConfig;
00212 
00213 /*
00214  * Function: SetupUnified()
00215  *
00216  * Purpose: Registers the output plugin keyword and initialization 
00217  *          function into the output plugin list.  This is the function that
00218  *          gets called from InitOutputPlugins() in plugbase.c.
00219  *
00220  * Arguments: None.
00221  *
00222  * Returns: void function
00223  *
00224  */
00225 void UnifiedSetup()
00226 {
00227     /* link the preprocessor keyword to the init function in 
00228        the preproc list */
00229     RegisterOutputPlugin("log_unified", NT_OUTPUT_LOG, UnifiedLogInit);
00230     RegisterOutputPlugin("alert_unified", NT_OUTPUT_ALERT, UnifiedAlertInit);
00231     RegisterOutputPlugin("unified", NT_OUTPUT_SPECIAL, UnifiedInit);
00232     DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Output plugin: Unified logging/alerting "
00233                 "is setup...\n"););
00234 }
00235 
00236 /*
00237  * Function: UnifiedInit(u_char *)
00238  *
00239  * Purpose: Calls the argument parsing function, performs final setup on data
00240  *          structs, links the preproc function into the function list.
00241  *
00242  * Arguments: args => ptr to argument string
00243  *
00244  * Returns: void function
00245  *
00246  */
00247 void UnifiedInit(u_char *args)
00248 {
00249     if(unifiedConfig)
00250     {
00251         FatalError("unified can only be instantiated once\n");
00252     }
00253 
00254     //DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Output: Unified Initialized\n"););
00255     pv.log_plugin_active = 1;
00256     pv.alert_plugin_active = 1;
00257 
00258     /* parse the argument list from the rules file */
00259     unifiedConfig = UnifiedParseArgs(args, "snort-unified");
00260 
00261     UnifiedInitFile(unifiedConfig);
00262 
00263 
00264     //LogMessage("UnifiedFilename = %s\n", unifiedConfig->filename);
00265     /* Set the preprocessor function into the function list */
00266     AddFuncToOutputList(UnifiedLogAlert, NT_OUTPUT_ALERT, unifiedConfig);
00267     AddFuncToOutputList(UnifiedLogPacketAlert, NT_OUTPUT_LOG, unifiedConfig);
00268 
00269     AddFuncToCleanExitList(UnifiedCleanExit, unifiedConfig);
00270     AddFuncToRestartList(UnifiedRestart, unifiedConfig);
00271 }
00272 
00273 /*
00274  * Function: InitOutputFile()
00275  *
00276  * Purpose: Initialize the unified ouput file 
00277  *
00278  * Arguments: data => pointer to the plugin's reference data struct 
00279  *
00280  * Returns: void function
00281  */
00282 static void UnifiedInitFile(UnifiedConfig *data)
00283 {
00284     time_t curr_time;      /* place to stick the clock data */
00285     char logdir[STD_BUF];
00286     FileHeader hdr;
00287     int value;
00288 
00289     bzero(logdir, STD_BUF);
00290     curr_time = time(NULL);
00291 
00292     if(data == NULL)
00293         FatalError("SpoUnified: Unable to get context data\n");
00294 
00295     if(*(data->filename) == '/')
00296         value = snprintf(logdir, STD_BUF, "%s.%lu", data->filename, 
00297                 (unsigned long)curr_time);
00298     else
00299         value = snprintf(logdir, STD_BUF, "%s/%s.%lu", pv.log_dir,  
00300                 data->filename, (unsigned long)curr_time);
00301 
00302     if(value == -1)
00303         FatalError("SpoUnified: filepath too long\n");
00304 
00305     //printf("Opening %s\n", logdir);
00306 
00307     if((data->stream = fopen(logdir, "wb")) == NULL)
00308         FatalError("UnifiedInitLogFile(%s): %s\n", logdir, strerror(errno));
00309 
00310     /* write the log file header */
00311     hdr.magic = UNIFIED_MAGIC;
00312     hdr.flags = 0;  /* XXX: not used yet */
00313 
00314     if(fwrite((char *)&hdr, sizeof(hdr), 1, data->stream) != 1)
00315     {
00316         FatalError("SpoUnified: InitOutputFile(): %s", strerror(errno));
00317     }
00318 
00319     fflush(data->stream);
00320 
00321     return;
00322 }
00323 
00324 void UnifiedRotateFile(UnifiedConfig *data)
00325 {
00326     fclose(data->stream);
00327     data->current = 0;
00328     UnifiedInitFile(data);
00329 }
00330 
00331 /* buffer */
00332 static char write_pkt_buffer[sizeof(DataHeader)+IP_MAXPACKET];
00333 /* buffer */
00334 int UnifiedLogData(u_int32_t type, u_int32_t length, void *data)
00335 {
00336     DataHeader dHdr;
00337     if(!unifiedConfig)
00338     {
00339         FatalError("Unified output not configured\n");
00340     }
00341     
00342     /* do not write if data is not available */
00343     if(!data)
00344     {
00345         LogMessage("WARNING: call to LogUnified with NULL data\n");
00346         return -1;
00347     }
00348 
00349     /* length check */
00350     if(length <= 0)
00351     {
00352         LogMessage("Empty Alert ....LogUnified bailing \n");
00353         return -1;
00354     }
00355     memset(write_pkt_buffer,'\0',sizeof(DataHeader)+IP_MAXPACKET);
00356 
00357     dHdr.type = type;
00358     dHdr.length = length;
00359    
00360     memcpy(write_pkt_buffer,&dHdr,sizeof(DataHeader));
00361     memcpy(write_pkt_buffer+sizeof(DataHeader),(char *)data,length);
00362 
00363 /*
00364     if(fwrite((char *)&dHdr, sizeof(DataHeader), 1, unifiedConfig->stream) 
00365             != 1)
00366     {
00367         FatalError("SpoUnified: write failed: %s\n", strerror(errno));
00368     }
00369 
00370     if(fwrite((char *)data, length, 1, unifiedConfig->stream) != 1)
00371     {
00372 */
00373     if(fwrite(write_pkt_buffer,length+sizeof(DataHeader),1,unifiedConfig->stream) != 1)
00374     {
00375         FatalError("SpoUnified: write failed: %s\n", strerror(errno));
00376     }
00377     fflush(unifiedConfig->stream);
00378 
00379     return 0;
00380 }
00381 
00382 void UnifiedLogAlert(Packet *p, char *msg, void *arg, Event *event)
00383 {
00384     DataHeader dHdr;
00385     dHdr.type = UNIFIED_TYPE_ALERT;
00386     dHdr.length = sizeof(UnifiedAlert);
00387     
00388     /* check for a pseudo-packet, we don't want to log those */
00389     RealUnifiedLogAlert(p, msg, arg, event, &dHdr);
00390 }
00391     
00392 void RealUnifiedLogAlert(Packet *p, char *msg, void *arg, Event *event, 
00393         DataHeader *dHdr)
00394 {
00395     UnifiedConfig *data = (UnifiedConfig *)arg;
00396     UnifiedAlert alertdata;
00397     Stream * s;
00398     StreamPacketData * spd;
00399     
00400     bzero(&alertdata, sizeof(alertdata));
00401 
00402     if(event != NULL)
00403     {
00404         alertdata.event.sig_generator = event->sig_generator;
00405         alertdata.event.sig_id = event->sig_id;
00406         alertdata.event.sig_rev = event->sig_rev;
00407         alertdata.event.classification = event->classification;
00408         alertdata.event.priority = event->priority;
00409         alertdata.event.event_id = event->event_id;
00410         alertdata.event.event_reference = event->event_reference;
00411         alertdata.event.ref_time.tv_sec = event->ref_time.tv_sec;
00412         alertdata.event.ref_time.tv_usec = event->ref_time.tv_usec;
00413 
00414     }
00415 
00416     if(p)
00417     {
00418         alertdata.ts.tv_sec = p->pkth->ts.tv_sec;
00419         alertdata.ts.tv_usec = p->pkth->ts.tv_usec;
00420        
00421        if(p->packet_flags & PKT_REBUILT_STREAM)
00422         {
00423             DEBUG_WRAP(DebugMessage(DEBUG_LOG, "man:Logging rebuilt stream data.\n");); 
00424 
00425             s = (Stream *) p->streamptr;
00426 
00427             /* get the first segment... */
00428             spd = (StreamPacketData *) ubi_btFirst((ubi_btNodePtr)&s->data);
00429 
00430            /* loop thru all the packets in the stream */
00431            if(spd != NULL )
00432            {
00433               alertdata.ts.tv_sec  = spd->pkth.ts.tv_sec;
00434               alertdata.ts.tv_usec = spd->pkth.ts.tv_usec;
00435           } 
00436        }
00437 
00438         if(p->iph != NULL)
00439         {
00440             /* everything needs to be written in host order */
00441             alertdata.sip = ntohl(p->iph->ip_src.s_addr);
00442             alertdata.dip = ntohl(p->iph->ip_dst.s_addr);
00443             if(p->iph->ip_proto == IPPROTO_ICMP)
00444             {
00445                 if(p->icmph != NULL)
00446                 {
00447                     alertdata.sp = p->icmph->type;
00448                     alertdata.dp = p->icmph->code;
00449                 }
00450             }
00451             else
00452             {
00453                 alertdata.sp = p->sp;
00454                 alertdata.dp = p->dp;
00455             }
00456             alertdata.protocol = p->iph->ip_proto;
00457             alertdata.flags = p->packet_flags;
00458         }
00459     }
00460     
00461     /* backward compatibility stuff */
00462     if(dHdr == NULL)
00463     {
00464         if((data->current + sizeof(UnifiedAlert)) > data->limit)
00465             UnifiedAlertRotateFile(data);
00466     }
00467     else
00468     {
00469         if((data->current + sizeof(UnifiedAlert)) > data->limit)
00470             UnifiedRotateFile(data);
00471     }
00472 
00473     if(dHdr)
00474     {
00475         if(fwrite((char *)dHdr, sizeof(DataHeader), 1, data->stream) != 1)
00476             FatalError("SpoUnified: write failed: %s\n", strerror(errno));
00477         data->current += sizeof(DataHeader);
00478     }
00479     
00480     if(fwrite((char *)&alertdata, sizeof(UnifiedAlert), 1, data->stream) != 1)
00481             FatalError("SpoUnified: write failed: %s\n", strerror(errno));
00482 
00483 
00484     fflush(data->stream);
00485     data->current += sizeof(UnifiedAlert);
00486 }
00487 
00488 
00489 void UnifiedLogPacketAlert(Packet *p, char *msg, void *arg, Event *event)
00490 {
00491     DataHeader dHdr;
00492     dHdr.type = UNIFIED_TYPE_PACKET_ALERT;
00493     dHdr.length = sizeof(UnifiedLog);
00494     
00495     if(p->packet_flags & PKT_REBUILT_STREAM)
00496     {
00497         DEBUG_WRAP(DebugMessage(DEBUG_LOG, 
00498                     "[*] Reassembled packet, dumping stream packets\n"););
00499         RealUnifiedLogStreamAlert(p, msg, arg, event, &dHdr);
00500     }
00501     else
00502     {
00503         DEBUG_WRAP(DebugMessage(DEBUG_LOG, "[*] Logging unified packets...\n"););
00504         RealUnifiedLogPacketAlert(p, msg, arg, event, &dHdr);
00505     }
00506 
00507 }
00508 
00509 
00510 void RealUnifiedLogPacketAlert(Packet *p, char *msg, void *arg, Event *event,
00511         DataHeader *dHdr)
00512 {
00513     UnifiedLog logheader;
00514     UnifiedConfig *data = (UnifiedConfig *)arg;
00515 
00516     if(event != NULL)
00517     {
00518         logheader.event.sig_generator = event->sig_generator;
00519         logheader.event.sig_id = event->sig_id;
00520         logheader.event.sig_rev = event->sig_rev;
00521         logheader.event.classification = event->classification;
00522         logheader.event.priority = event->priority;
00523         logheader.event.event_id = event->event_id;
00524         logheader.event.event_reference = event->event_reference;
00525         logheader.event.ref_time.tv_sec = event->ref_time.tv_sec;
00526         logheader.event.ref_time.tv_usec = event->ref_time.tv_usec;
00527 
00528         DEBUG_WRAP(DebugMessage(DEBUG_LOG, "------------\n");
00529         DebugMessage(DEBUG_LOG, "gen: %u\n", logheader.event.sig_generator);
00530         DebugMessage(DEBUG_LOG, "sid: %u\n", logheader.event.sig_id);
00531         DebugMessage(DEBUG_LOG, "rev: %u\n", logheader.event.sig_rev);
00532         DebugMessage(DEBUG_LOG, "cls: %u\n", logheader.event.classification);
00533         DebugMessage(DEBUG_LOG, "pri: %u\n", logheader.event.priority);
00534         DebugMessage(DEBUG_LOG, "eid: %u\n", logheader.event.event_id);
00535         DebugMessage(DEBUG_LOG, "erf: %u\n", logheader.event.event_reference);
00536         DebugMessage(DEBUG_LOG, "sec: %lu\n", logheader.event.ref_time.tv_sec);
00537         DebugMessage(DEBUG_LOG, "usc: %lu\n", logheader.event.ref_time.tv_usec););
00538     }
00539 
00540     if(p)
00541     {
00542         logheader.flags = p->packet_flags;
00543 
00544         /* 
00545          * this will have to be fixed when we transition to the pa_engine
00546          * code (p->pkth is libpcap specific)
00547          */ 
00548         memcpy(&logheader.pkth, p->pkth, sizeof(SnortPktHeader));
00549     }
00550     else
00551     {
00552         logheader.flags = 0;
00553         logheader.pkth.ts.tv_sec = 0;
00554         logheader.pkth.ts.tv_usec = 0;
00555         logheader.pkth.caplen = 0;
00556         logheader.pkth.pktlen = 0;
00557     }
00558     
00559     /* backward compatibility stuff */
00560     if(dHdr == NULL)
00561     {
00562         if((data->current + sizeof(UnifiedLog) + logheader.pkth.caplen) > 
00563                 data->limit)
00564             UnifiedLogRotateFile(data);
00565     }
00566     else
00567     {   
00568         if((data->current + sizeof(UnifiedLog) + sizeof(DataHeader) 
00569                     + logheader.pkth.caplen) > data->limit)
00570             UnifiedRotateFile(data);
00571     }
00572     if(dHdr)
00573     {
00574         if(fwrite((char *)dHdr, sizeof(DataHeader), 1, data->stream) != 1)
00575             FatalError("SpoUnified: write failed: %s\n", strerror(errno));
00576         data->current += sizeof(DataHeader);
00577     }
00578         
00579     
00580     if(fwrite((char*)&logheader, sizeof(UnifiedLog), 1, data->stream) != 1)
00581         FatalError("SpoUnified: write failed: %s\n", strerror(errno));
00582     data->current += sizeof(UnifiedLog);
00583     
00584     if(p)
00585     {
00586         if(fwrite((char*)p->pkt, p->pkth->caplen, 1, data->stream) != 1)
00587             FatalError("SpoUnified: write failed: %s\n", strerror(errno));
00588         data->current += p->pkth->caplen;
00589     }
00590 
00591     fflush(data->stream);
00592 }
00593 
00594 
00595 
00596 /**
00597  * Log a set of packets stored in the stream reassembler
00598  *
00599  */
00600 void RealUnifiedLogStreamAlert(Packet *p, char *msg, void *arg, Event *event,
00601         DataHeader *dHdr)
00602 {
00603     Stream *s = NULL;
00604     StreamPacketData *spd;
00605     UnifiedLog logheader;
00606     UnifiedConfig *data = (UnifiedConfig *)arg;
00607     int once = 0;
00608 
00609     /* setup the event header */
00610     if(event != NULL)
00611     {
00612         logheader.event.sig_generator = event->sig_generator;
00613         logheader.event.sig_id = event->sig_id;
00614         logheader.event.sig_rev = event->sig_rev;
00615         logheader.event.classification = event->classification;
00616         logheader.event.priority = event->priority;
00617         logheader.event.event_id = event->event_id;
00618         logheader.event.event_reference = event->event_reference;
00619         /* Note that ref_time is probably incorrect.  
00620          * See OldUnifiedLogPacketAlert() for details. */
00621         logheader.event.ref_time.tv_sec = event->ref_time.tv_sec;
00622         logheader.event.ref_time.tv_usec = event->ref_time.tv_usec;
00623 
00624         DEBUG_WRAP(DebugMessage(DEBUG_LOG, "------------\n");
00625         DebugMessage(DEBUG_LOG, "gen: %u\n", logheader.event.sig_generator);
00626         DebugMessage(DEBUG_LOG, "sid: %u\n", logheader.event.sig_id);
00627         DebugMessage(DEBUG_LOG, "rev: %u\n", logheader.event.sig_rev);
00628         DebugMessage(DEBUG_LOG, "cls: %u\n", logheader.event.classification);
00629         DebugMessage(DEBUG_LOG, "pri: %u\n", logheader.event.priority);
00630         DebugMessage(DEBUG_LOG, "eid: %u\n", logheader.event.event_id);
00631         DebugMessage(DEBUG_LOG, "erf: %u\n", 
00632                logheader.event.event_reference);
00633         DebugMessage(DEBUG_LOG, "sec: %lu\n", 
00634                logheader.event.ref_time.tv_sec);
00635         DebugMessage(DEBUG_LOG, "usc: %lu\n", 
00636                logheader.event.ref_time.tv_usec););
00637     }
00638 
00639     /* queue up the stream for logging */
00640     if(p)
00641     {
00642         s = (Stream *) p->streamptr;
00643 
00644         /* get the first segment... */
00645         spd = (StreamPacketData *) ubi_btFirst((ubi_btNodePtr)&s->data);
00646 
00647         /* loop thru all the packets in the stream */
00648         do
00649         {
00650             /* packets that are part of the currently reassembled stream
00651              * should be marked with the chuck flag
00652              */
00653             if(spd->chuck != SEG_UNASSEMBLED)
00654             {
00655                 /* copy it's pktheader data into the logheader */
00656                 memcpy(&logheader.pkth, &spd->pkth, sizeof(SnortPktHeader));
00657 
00658                 /* backward compatibility stuff */
00659                 if(dHdr == NULL)
00660                 {
00661                     if((data->current +
00662                         sizeof(UnifiedLog)+
00663                         logheader.pkth.caplen) > 
00664                         data->limit)
00665                     {
00666                         UnifiedLogRotateFile(data);
00667                     }
00668                 }
00669                 else
00670                 {   
00671                     if((data->current + sizeof(UnifiedLog) + sizeof(DataHeader) 
00672                                 + logheader.pkth.caplen) > data->limit)
00673                         UnifiedRotateFile(data);
00674                 }
00675 
00676                 if(dHdr)
00677                 {
00678                     if(fwrite((char*)dHdr,sizeof(DataHeader),1,data->stream) 
00679                             != 1)
00680                         FatalError("SpoUnified: write failed: %s\n", 
00681                                 strerror(errno));
00682                     data->current += sizeof(DataHeader);
00683                 }
00684 
00685                 if(fwrite((char*)&logheader,sizeof(UnifiedLog),1,data->stream)
00686                        != 1)
00687                     FatalError("SpoUnified: write failed: %s\n", 
00688                             strerror(errno));
00689 
00690                 data->current += sizeof(UnifiedLog);
00691 
00692                 if(spd->pkt)
00693                 {
00694                     if(fwrite((char*)spd->pkt,logheader.pkth.caplen,1
00695                                 ,data->stream) != 1)
00696                         FatalError("SpoUnified: write failed: %s\n", 
00697                                 strerror(errno));
00698 
00699                     data->current += logheader.pkth.caplen;
00700                 }
00701 
00702                 /* after the first logged packet modify the event headers */
00703                 if(!once++)
00704                 {
00705                     logheader.event.sig_generator = GENERATOR_TAG;
00706                     logheader.event.sig_id = TAG_LOG_PKT;
00707                     logheader.event.sig_rev = 1;
00708                     logheader.event.classification = 0;
00709                     logheader.event.priority = event->priority;
00710                     /* Note that event_id is now incorrect. 
00711                      * See OldUnifiedLogPacketAlert() for details. */
00712                 }
00713             }
00714 
00715         } while((spd=(StreamPacketData*)ubi_btNext((ubi_btNodePtr)spd))
00716                 !=NULL);
00717     }
00718     
00719     fflush(data->stream);
00720 }
00721     
00722 /*
00723  * Function: UnifiedParseArgs(char *)
00724  *
00725  * Purpose: Process the preprocessor arguements from the rules file and 
00726  *          initialize the preprocessor's data struct.  This function doesn't
00727  *          have to exist if it makes sense to parse the args in the init 
00728  *          function.
00729  *
00730  * Arguments: args => argument list
00731  *
00732  * Returns: void function
00733  *
00734  */
00735 UnifiedConfig *UnifiedParseArgs(char *args, char *default_filename)
00736 {
00737     UnifiedConfig *tmp;
00738     int limit = 0;
00739 
00740     tmp = (UnifiedConfig *)calloc(sizeof(UnifiedConfig), sizeof(char));
00741 
00742     if(tmp == NULL)
00743     {
00744         FatalError("Unable to allocate Unified Data struct!\n");
00745     }
00746 
00747     DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Args: %s\n", args););
00748 
00749     if(args != NULL)
00750     {
00751         char **toks;
00752         int num_toks;
00753         int i = 0;
00754         toks = mSplit(args, ",", 31, &num_toks, '\\');
00755         for(i = 0; i < num_toks; ++i)
00756         {
00757             char **stoks;
00758             int num_stoks;
00759             char *index = toks[i];
00760             while(isspace((int)*index))
00761                 ++index;
00762           
00763             stoks = mSplit(index, " ", 2, &num_stoks, 0);
00764             
00765             if(strcasecmp("filename", stoks[0]) == 0)
00766             {
00767                 if(num_stoks > 1 && tmp->filename == NULL)
00768                     tmp->filename = strdup(stoks[1]);
00769                 else
00770                     LogMessage("Argument Error in %s(%i): %s\n",
00771                             file_name, file_line, index);
00772             }
00773             if(strcasecmp("limit", stoks[0]) == 0)
00774             {
00775                 if(num_stoks > 1 && limit == 0)
00776                 {
00777                     limit = atoi(stoks[1]);
00778                 }
00779                 else
00780                 {
00781                     LogMessage("Argument Error in %s(%i): %s\n",
00782                             file_name, file_line, index);
00783                 }
00784             }
00785             do
00786                 free(stoks[--num_stoks]);
00787             while(num_stoks);
00788         }
00789         do
00790             free(toks[--num_toks]);
00791         while(num_toks);
00792     }
00793 
00794     if(tmp->filename == NULL)
00795         tmp->filename = strdup(default_filename);
00796     
00797     //LogMessage("limit == %i\n", limit);
00798 
00799     if(limit <= 0)
00800     {
00801         limit = 128;
00802     }
00803     if(limit > 512)
00804     {
00805         LogMessage("spo_unified %s(%d)=> Lowering limit of %iMB to 512MB\n", file_name, file_line, limit);
00806         limit = 512;
00807     }
00808 
00809     /* convert the limit to "MB" */
00810     tmp->limit = limit << 20;
00811 
00812     return tmp;
00813 }
00814 
00815 
00816 /*
00817  * Function: UnifiedCleanExitFunc()
00818  *
00819  * Purpose: Cleanup at exit time
00820  *
00821  * Arguments: signal => signal that caused this event
00822  *            arg => data ptr to reference this plugin's data
00823  *
00824  * Returns: void function
00825  */
00826 static void UnifiedCleanExit(int signal, void *arg)
00827 {
00828     /* cast the arg pointer to the proper type */
00829     UnifiedConfig *data = (UnifiedConfig *)arg;
00830 
00831     DEBUG_WRAP(DebugMessage(DEBUG_FLOW, "SpoUnified: CleanExit\n"););
00832 
00833     fclose(data->stream);
00834 
00835     /* free up initialized memory */
00836     free(data->filename);
00837     free(data);
00838 }
00839 
00840 
00841 
00842 /*
00843  * Function: Restart()
00844  *
00845  * Purpose: For restarts (SIGHUP usually) clean up structs that need it
00846  *
00847  * Arguments: signal => signal that caused this event
00848  *            arg => data ptr to reference this plugin's data
00849  *
00850  * Returns: void function
00851  */
00852 static void UnifiedRestart(int signal, void *arg)
00853 {
00854     UnifiedConfig *data = (UnifiedConfig *)arg;
00855 
00856     DEBUG_WRAP(DebugMessage(DEBUG_FLOW, "SpoUnified: Restart\n"););
00857 
00858     fclose(data->stream);
00859     free(data->filename);
00860     free(data);
00861 }
00862 
00863 
00864 
00865 /* Unified Alert functions (deprecated) */
00866 void UnifiedAlertInit(u_char *args)
00867 {
00868     UnifiedConfig *data;
00869 
00870     DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Output: Unified Alert Initialized\n"););
00871 
00872     pv.alert_plugin_active = 1;
00873 
00874     /* parse the argument list from the rules file */
00875     data = UnifiedParseArgs(args, "snort-unified.alert");
00876 
00877     UnifiedInitAlertFile(data);
00878 
00879 
00880     //LogMessage("UnifiedAlertFilename = %s\n", data->filename);
00881     /* Set the preprocessor function into the function list */
00882     AddFuncToOutputList(OldUnifiedLogAlert, NT_OUTPUT_ALERT, data);
00883     AddFuncToCleanExitList(UnifiedCleanExit, data);
00884     AddFuncToRestartList(UnifiedRestart, data);
00885 }
00886 /*
00887  * Function: UnifiedInitAlertFile()
00888  *
00889  * Purpose: Initialize the unified log alert file
00890  *
00891  * Arguments: data => pointer to the plugin's reference data struct 
00892  *
00893  * Returns: void function
00894  */
00895 void UnifiedInitAlertFile(UnifiedConfig *data)
00896 {
00897     time_t curr_time;      /* place to stick the clock data */
00898     char logdir[STD_BUF];
00899     int value;
00900     UnifiedAlertFileHeader hdr;
00901 
00902     bzero(logdir, STD_BUF);
00903     curr_time = time(NULL);
00904 
00905     if(data->filename[0] == '/')
00906         value = snprintf(logdir, STD_BUF, "%s.%lu",  data->filename, 
00907                 (unsigned long)curr_time);
00908     else
00909         value = snprintf(logdir, STD_BUF, "%s/%s.%lu", pv.log_dir, 
00910                 data->filename, (unsigned long)curr_time);
00911 
00912     if(value == -1)
00913     {
00914         FatalError("unified log file logging path and file name are "
00915                    "too long, aborting!\n");
00916     }
00917 
00918     DEBUG_WRAP(DebugMessage(DEBUG_LOG, "Opening %s\n", logdir););
00919 
00920     if((data->stream = fopen(logdir, "wb+")) == NULL)
00921     {
00922         FatalError("UnifiedInitAlertFile(%s): %s\n", logdir, strerror(errno));
00923     }
00924 
00925     hdr.magic = ALERT_MAGIC;
00926     hdr.version_major = 1;
00927     hdr.version_minor = 81;
00928     hdr.timezone = thiszone;
00929 
00930     if(fwrite((char *)&hdr, sizeof(hdr), 1, data->stream) != 1)
00931     {
00932         FatalError("UnifiedAlertInit(): %s\n", strerror(errno));
00933     }
00934         
00935     fflush(data->stream);
00936 
00937     return;
00938 }
00939 
00940 
00941 void OldUnifiedLogAlert(Packet *p, char *msg, void *arg, Event *event)
00942 {
00943     RealUnifiedLogAlert(p, msg, arg, event, NULL);
00944 }
00945 
00946 void UnifiedAlertRotateFile(UnifiedConfig *data)
00947 {
00948 
00949     fclose(data->stream);
00950     data->current = 0;
00951     UnifiedInitAlertFile(data);
00952 }
00953 
00954 /* Unified Packet Log functions (deprecated) */
00955 
00956 void UnifiedLogInit(u_char *args)
00957 {
00958     UnifiedConfig *UnifiedInfo;
00959 
00960     DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Output: Unified Log Initialized\n"););
00961 
00962     /* tell command line loggers to go away */
00963     pv.log_plugin_active = 1;
00964 
00965     /* parse the argument list from the rules file */
00966     UnifiedInfo = UnifiedParseArgs(args, "snort-unified.log");
00967 
00968     //LogMessage("UnifiedLogFilename = %s\n", UnifiedInfo->filename);
00969 
00970     UnifiedInitLogFile(UnifiedInfo);
00971 
00972     pv.log_bitmap |= LOG_UNIFIED;
00973 
00974     /* Set the preprocessor function into the function list */
00975     AddFuncToOutputList(OldUnifiedLogPacketAlert, NT_OUTPUT_LOG, UnifiedInfo);
00976     AddFuncToCleanExitList(UnifiedCleanExit, UnifiedInfo);
00977     AddFuncToRestartList(UnifiedRestart, UnifiedInfo);
00978 }
00979 
00980 
00981 /*
00982  * Function: UnifiedInitLogFile()
00983  *
00984  * Purpose: Initialize the unified log file header
00985  *
00986  * Arguments: data => pointer to the plugin's reference data struct 
00987  *
00988  * Returns: void function
00989  */
00990 void UnifiedInitLogFile(UnifiedConfig *data)
00991 {
00992     time_t curr_time;      /* place to stick the clock data */
00993     char logdir[STD_BUF];
00994     int value;
00995     UnifiedLogFileHeader hdr;
00996 
00997     bzero(logdir, STD_BUF);
00998     curr_time = time(NULL);
00999 
01000     if(data == NULL)
01001     {
01002         FatalError("Can't get unified plugin context, that's bad\n");
01003     }
01004 
01005     if(*(data->filename) == '/')
01006         value = snprintf(logdir, STD_BUF, "%s.%lu", data->filename, 
01007                 (unsigned long)curr_time);
01008     else
01009         value = snprintf(logdir, STD_BUF, "%s/%s.%lu", pv.log_dir,  
01010                 data->filename, (unsigned long)curr_time);
01011 
01012     if(value == -1)
01013     {
01014         FatalError("unified log file logging path and file name are "
01015                    "too long, aborting!\n");
01016     }
01017 
01018     if((data->stream = fopen(logdir, "wb")) == NULL)
01019     {
01020         FatalError("UnifiedInitLogFile(%s): %s\n", logdir, strerror(errno));
01021     }
01022 
01023     /* write the log file header */
01024     hdr.magic = LOG_MAGIC;
01025     hdr.version_major = SNORT_VERSION_MAJOR;
01026     hdr.version_minor = SNORT_VERSION_MINOR;
01027     hdr.timezone = thiszone;
01028     hdr.snaplen = snaplen;
01029     hdr.sigfigs = 0;
01030     hdr.linktype = datalink;
01031 
01032 #ifdef GIDS
01033     hdr.linktype = DLT_EN10MB;
01034 #endif
01035 
01036     if(fwrite((char *)&hdr, sizeof(hdr), 1, data->stream) != 1)
01037     {
01038         FatalError("UnifiedLogInit(): %s", strerror(errno));
01039     }
01040 
01041     fflush(data->stream);
01042 
01043     return;
01044 }
01045 
01046 /*
01047  * Function: LogUnified(Packet *, char *msg, void *arg)
01048  *
01049  * Purpose: Perform the preprocessor's intended function.  This can be
01050  *          simple (statistics collection) or complex (IP defragmentation)
01051  *          as you like.  Try not to destroy the performance of the whole
01052  *          system by trying to do too much....
01053  *
01054  * Arguments: p => pointer to the current packet data struct 
01055  *
01056  * Returns: void function
01057  */
01058 void OldUnifiedLogPacketAlert(Packet *p, char *msg, void *arg, Event *event)
01059 {
01060     Stream *s = NULL;
01061     StreamPacketData *spd = NULL;
01062     int first_time = 1;
01063     UnifiedLog logheader;
01064     UnifiedConfig *data = (UnifiedConfig *)arg;
01065 
01066     if(event != NULL)
01067     {
01068         logheader.event.sig_generator = event->sig_generator;
01069         logheader.event.sig_id = event->sig_id;
01070         logheader.event.sig_rev = event->sig_rev;
01071         logheader.event.classification = event->classification;
01072         logheader.event.priority = event->priority;
01073         logheader.event.event_id = event->event_id;
01074         logheader.event.event_reference = event->event_reference;
01075         logheader.event.ref_time.tv_sec = event->ref_time.tv_sec;
01076         logheader.event.ref_time.tv_usec = event->ref_time.tv_usec;
01077 
01078         DEBUG_WRAP(DebugMessage(DEBUG_LOG, "------------\n"););
01079         DEBUG_WRAP(DebugMessage(DEBUG_LOG, "gen: %u\n", 
01080                     logheader.event.sig_generator););
01081         DEBUG_WRAP(DebugMessage(DEBUG_LOG, "sid: %u\n", 
01082                     logheader.event.sig_id););
01083         DEBUG_WRAP(DebugMessage(DEBUG_LOG, "rev: %u\n", 
01084                     logheader.event.sig_rev););
01085         DEBUG_WRAP(DebugMessage(DEBUG_LOG, "cls: %u\n", 
01086                     logheader.event.classification););
01087         DEBUG_WRAP(DebugMessage(DEBUG_LOG, "pri: %u\n", 
01088                     logheader.event.priority););
01089         DEBUG_WRAP(DebugMessage(DEBUG_LOG, "eid: %u\n", 
01090                     logheader.event.event_id););
01091         DEBUG_WRAP(DebugMessage(DEBUG_LOG, "erf: %u\n", 
01092                     logheader.event.event_reference););
01093         DEBUG_WRAP(DebugMessage(DEBUG_LOG, "sec: %lu\n",
01094                     logheader.event.ref_time.tv_sec););
01095         DEBUG_WRAP(DebugMessage(DEBUG_LOG, "usc: %lu\n",
01096                     logheader.event.ref_time.tv_usec););
01097     }
01098 
01099     if(p->packet_flags & PKT_REBUILT_STREAM)
01100     {
01101         s = (Stream *) p->streamptr;
01102 
01103         /* get the first segment... */
01104         spd = (StreamPacketData *) ubi_btFirst((ubi_btNodePtr)&s->data);
01105 
01106         /* loop thru all the packets in the stream */
01107         while (spd != NULL )
01108         {
01109             /* packets that are part of the currently reassembled stream
01110              * should be marked with the chuck flag
01111              */
01112             if(spd->chuck != SEG_UNASSEMBLED)
01113             {
01114                 logheader.flags = p->packet_flags;
01115 
01116                 /* copy it's pktheader data into the logheader */
01117                 memcpy(&logheader.pkth, &spd->pkth, sizeof(SnortPktHeader));
01118 
01119 #ifdef GIDS
01120                 /*
01121                 **  Add the ethernet header size to the total pktlen.
01122                 **  If the ethernet hdr is already set, then this means
01123                 **  that it's a portscan packet and we don't add the
01124                 **  ethernet header.
01125                 */
01126                 if(!p->eh)
01127                 {
01128                     logheader.pkth.caplen += sizeof(EtherHdr);
01129                     logheader.pkth.pktlen += sizeof(EtherHdr);
01130                 }
01131 #endif
01132 
01133                /*  Set reference time equal to log time for the first packet  */
01134                 if (first_time)
01135                 {                    
01136                     logheader.event.ref_time.tv_sec = logheader.pkth.ts.tv_sec;
01137                     logheader.event.ref_time.tv_usec = logheader.pkth.ts.tv_usec;
01138                     DEBUG_WRAP(DebugMessage(DEBUG_LOG, "sec: %lu\n", 
01139                                 logheader.event.ref_time.tv_sec););
01140                     DEBUG_WRAP(DebugMessage(DEBUG_LOG, "usc: %lu\n", 
01141                                 logheader.event.ref_time.tv_usec););
01142 
01143                 }
01144 
01145                 if(fwrite((char*)&logheader,sizeof(UnifiedLog),1,data->stream)
01146                        != 1)
01147                     FatalError("SpoUnified: write failed: %s\n", 
01148                             strerror(errno));
01149 
01150                 data->current += sizeof(UnifiedLog);
01151 
01152                 if(spd->pkt)
01153                 {
01154 #ifdef GIDS
01155                     if(!p->eh)
01156                     {
01157 #ifndef IPFW
01158                         memcpy((u_char *)g_ethernet.ether_src,g_m->hw_addr,6);
01159                         memset((u_char *)g_ethernet.ether_dst,0x00,6);
01160 #else
01161                         memset(g_ethernet.ether_dst,0x00,6);
01162                         memset(g_ethernet.ether_src,0x00,6);
01163 #endif
01164                         g_ethernet.ether_type = htons(0x0800);
01165 
01166                         if(fwrite((char*)&g_ethernet,sizeof(EtherHdr),1,data->stream) != 1)
01167                             FatalError("SpoUnified: write failed: %s\n", strerror(errno));
01168                         data->current += sizeof(EtherHdr);
01169                     }
01170 #endif
01171         
01172                     if(fwrite((char*)spd->pkt,spd->pkth.caplen,1
01173                                 ,data->stream) != 1)
01174                         FatalError("SpoUnified: write failed: %s\n", 
01175                                 strerror(errno));
01176 
01177                     data->current += spd->pkth.caplen;
01178                 }
01179 
01180                 /* after the first logged packet modify the event headers */
01181                 if (first_time)
01182                 {                    
01183                     logheader.event.sig_generator = GENERATOR_TAG;
01184                     logheader.event.sig_id = TAG_LOG_PKT;
01185                     logheader.event.sig_rev = 1;
01186                     logheader.event.classification = 0;
01187                     logheader.event.priority = event->priority;    
01188                     first_time = 0;
01189                 }
01190 
01191                 /* Update event ID for subsequent logged packets */
01192                 logheader.event.event_id = ++event_id | pv.event_log_id;
01193             }
01194 
01195             spd = (StreamPacketData*) ubi_btNext((ubi_btNodePtr)spd);
01196         }
01197     }
01198     else
01199     {
01200         if(p)
01201         {
01202             logheader.flags = p->packet_flags;
01203 
01204             memcpy(&logheader.pkth, p->pkth, sizeof(SnortPktHeader));
01205 
01206 #ifdef GIDS
01207             /*
01208             **  Add the ethernet header size to the total pktlen.
01209             **  If the ethernet hdr is already set, then this means
01210             **  that it's a portscan packet and we don't add the
01211             **  ethernet header.
01212             */
01213             if(!p->eh)
01214             {
01215                 logheader.pkth.caplen += sizeof(EtherHdr);
01216                 logheader.pkth.pktlen += sizeof(EtherHdr);
01217             }
01218 #endif
01219         }
01220         else
01221         {
01222             logheader.flags = 0;
01223             logheader.pkth.ts.tv_sec = 0;
01224             logheader.pkth.ts.tv_usec = 0;
01225             logheader.pkth.caplen = 0;
01226             logheader.pkth.pktlen = 0;
01227         }
01228 
01229         if((data->current + sizeof(UnifiedLog) + logheader.pkth.caplen) > 
01230                 data->limit)
01231             UnifiedLogRotateFile(data);
01232 
01233         fwrite((char*)&logheader, sizeof(UnifiedLog), 1, data->stream);
01234 
01235         if(p)
01236         {
01237 #ifdef GIDS
01238             if(!p->eh)
01239             {
01240 #ifndef IPFW
01241                 memcpy((u_char *)g_ethernet.ether_src,g_m->hw_addr,6);
01242                 memset((u_char *)g_ethernet.ether_dst,0x00,6);
01243 #else
01244                 memset(g_ethernet.ether_dst,0x00,6);
01245                 memset(g_ethernet.ether_src,0x00,6);
01246 #endif
01247                 g_ethernet.ether_type = htons(0x0800);
01248 
01249                 if(fwrite((char*)&g_ethernet,sizeof(EtherHdr),1,data->stream) != 1)
01250                     FatalError("SpoUnified: write failed: %s\n", strerror(errno));
01251                 data->current += sizeof(EtherHdr);
01252             }
01253 #endif
01254         
01255             fwrite((char*)p->pkt, p->pkth->caplen, 1, data->stream);
01256         }
01257     }
01258 
01259     fflush(data->stream);
01260 
01261     data->current += sizeof(UnifiedLog) + p->pkth->caplen;
01262     
01263 }
01264 
01265 
01266 void UnifiedLogRotateFile(UnifiedConfig *data)
01267 {
01268 
01269     fclose(data->stream);
01270     data->current = 0;
01271     UnifiedInitLogFile(data);
01272 }
01273 

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