00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #ifdef HAVE_CONFIG_H
00037 #include "config.h"
00038 #endif
00039
00040 #include <sys/types.h>
00041 #include <stdio.h>
00042 #include <stdlib.h>
00043 #ifndef WIN32
00044 #include <sys/socket.h>
00045 #include <netinet/in.h>
00046 #include <arpa/inet.h>
00047 #endif
00048
00049 #ifdef HAVE_STRINGS_H
00050 #include <strings.h>
00051 #endif
00052
00053 #include "event.h"
00054 #include "decode.h"
00055 #include "plugbase.h"
00056 #include "spo_plugbase.h"
00057 #include "parser.h"
00058 #include "debug.h"
00059 #include "mstring.h"
00060 #include "util.h"
00061 #include "log.h"
00062
00063 #include "snort.h"
00064
00065 #define DEFAULT_CSV "timestamp,sig_generator,sig_id,sig_rev,msg,proto,src,srcport,dst,dstport,ethsrc,ethdst,ethlen,tcpflags,tcpseq,tcpack,tcpln,tcpwindow,ttl,tos,id,dgmlen,iplen,icmptype,icmpcode,icmpid,icmpseq"
00066
00067 typedef struct _AlertCSVConfig
00068 {
00069 char *type;
00070 struct _AlertCSVConfig *next;
00071 } AlertCSVConfig;
00072
00073 typedef struct _AlertCSVData
00074 {
00075 FILE *file;
00076 char * csvargs;
00077 char ** args;
00078 int numargs;
00079 AlertCSVConfig *config;
00080 } AlertCSVData;
00081
00082
00083
00084 void AlertCSVInit(u_char *);
00085 AlertCSVData *AlertCSVParseArgs(char *);
00086 void AlertCSV(Packet *, char *, void *, Event *);
00087 void AlertCSVCleanExit(int, void *);
00088 void AlertCSVRestart(int, void *);
00089 void RealAlertCSV(Packet * p, char *msg, FILE * file, char **args,
00090 int numargs, Event *event);
00091 static char *CSVEscape(char *input);
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105 void AlertCSVSetup(void)
00106 {
00107
00108
00109 RegisterOutputPlugin("alert_CSV", NT_OUTPUT_ALERT, AlertCSVInit);
00110
00111 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Output plugin: alert_CSV is setup...\n"););
00112 }
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126 void AlertCSVInit(u_char *args)
00127 {
00128 AlertCSVData *data;
00129 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Output: CSV Initialized\n"););
00130
00131 pv.alert_plugin_active = 1;
00132
00133
00134 data = AlertCSVParseArgs(args);
00135
00136 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Linking CSV functions to call lists...\n"););
00137
00138
00139 AddFuncToOutputList(AlertCSV, NT_OUTPUT_ALERT, data);
00140 AddFuncToCleanExitList(AlertCSVCleanExit, data);
00141 AddFuncToRestartList(AlertCSVRestart, data);
00142 }
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157 AlertCSVData *AlertCSVParseArgs(char *args)
00158 {
00159 char **toks;
00160 int num_toks;
00161 char *filename;
00162 AlertCSVData *data;
00163
00164 int num;
00165
00166 data = (AlertCSVData *)SnortAlloc(sizeof(AlertCSVData));
00167 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "ParseCSVArgs: %s\n", args););
00168
00169 toks = mSplit(args, " ", 2, &num_toks, 0);
00170
00171 if(num_toks <= 1)
00172 {
00173 FatalError("You must supply at least TWO arguments for "
00174 "the CSV plugin...\n"
00175 "\t ... arguements of \"/path/to/output/file default\" "
00176 "as a minimum.\n");
00177 }
00178
00179 filename = ProcessFileOption(toks[0]);
00180 data->file = OpenAlertFile(filename);
00181 free(filename);
00182 DEBUG_WRAP(DebugMessage(DEBUG_INIT,"AlertCSV Got filename\n"););
00183
00184 if(!strncasecmp("default", toks[1], 7))
00185 {
00186 data->csvargs = DEFAULT_CSV;
00187 }
00188 else
00189 {
00190 data->csvargs = toks[1];
00191 }
00192
00193 DEBUG_WRAP(DebugMessage(DEBUG_LOG,"AlertCSV Got Config ARGS\n"););
00194
00195 toks = mSplit(data->csvargs, ",", 128, &num_toks, 0);
00196
00197 num = num_toks;
00198 data->args = toks;
00199 data->numargs = num;
00200
00201 return data;
00202 }
00203
00204 void AlertCSVCleanExit(int signal, void *arg)
00205 {
00206 AlertCSVData *data = (AlertCSVData *)arg;
00207
00208 DEBUG_WRAP(DebugMessage(DEBUG_LOG,"CSVCleanExitFunc\n"););
00209 fclose(data->file);
00210
00211 free(data);
00212 }
00213
00214 void AlertCSVRestart(int signal, void *arg)
00215 {
00216 AlertCSVData *data = (AlertCSVData *)arg;
00217
00218 DEBUG_WRAP(DebugMessage(DEBUG_LOG,"CSVRestartFunc\n"););
00219 fclose(data->file);
00220
00221 free(data);
00222 }
00223
00224
00225 void AlertCSV(Packet *p, char *msg, void *arg, Event *event)
00226 {
00227 AlertCSVData *data = (AlertCSVData *)arg;
00228 RealAlertCSV(p, msg, data->file, data->args, data->numargs, event);
00229 return;
00230 }
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248 void RealAlertCSV(Packet * p, char *msg, FILE * file, char **args,
00249 int numargs, Event *event)
00250 {
00251 char timestamp[TIMEBUF_SIZE];
00252 int num;
00253 char *type;
00254 char tcpFlags[9];
00255
00256 if(p == NULL)
00257 return;
00258
00259 bzero((char *) timestamp, TIMEBUF_SIZE);
00260 ts_print(p == NULL ? NULL : (struct timeval *) & p->pkth->ts, timestamp);
00261
00262 DEBUG_WRAP(DebugMessage(DEBUG_LOG,"Logging CSV Alert data\n"););
00263
00264 for (num = 0; num < numargs; num++)
00265 {
00266 type = args[num];
00267
00268 DEBUG_WRAP(DebugMessage(DEBUG_LOG, "CSV Got type %s %d\n", type, num););
00269
00270 if(!strncasecmp("timestamp", type, 9))
00271 {
00272 fwrite(timestamp, strlen(timestamp), 1, file);
00273 }
00274 else if(!strncasecmp("sig_generator",type,13))
00275 {
00276 if(event != NULL)
00277 {
00278 fprintf(file, "%lu", (unsigned long) event->sig_generator);
00279 }
00280 }
00281 else if(!strncasecmp("sig_id",type,6))
00282 {
00283 if(event != NULL)
00284 {
00285 fprintf(file, "%lu", (unsigned long) event->sig_id);
00286 }
00287 }
00288 else if(!strncasecmp("sig_rev",type,7))
00289 {
00290 if(event != NULL)
00291 {
00292 fprintf(file, "%lu", (unsigned long) event->sig_rev);
00293 }
00294 }
00295 else if(!strncasecmp("msg", type, 3))
00296 {
00297
00298 char *escaped_msg;
00299 if(!(escaped_msg = CSVEscape(msg)))
00300 {
00301 FatalError("Out of memory escaping msg string");
00302 }
00303 fwrite(escaped_msg, strlen(escaped_msg),1,file);
00304 free(escaped_msg);
00305 }
00306 else if(!strncasecmp("proto", type, 5))
00307 {
00308 if(p->iph)
00309 {
00310 switch (p->iph->ip_proto)
00311 {
00312 case IPPROTO_UDP:
00313 fwrite("UDP", 3,1,file);
00314 break;
00315 case IPPROTO_TCP:
00316 fwrite("TCP", 3,1,file);
00317 break;
00318 case IPPROTO_ICMP:
00319 fwrite("ICMP", 4,1,file);
00320 break;
00321 }
00322 }
00323 }
00324 else if(!strncasecmp("ethsrc", type, 6))
00325 {
00326 if(p->eh)
00327 {
00328 fprintf(file, "%X:%X:%X:%X:%X:%X", p->eh->ether_src[0],
00329 p->eh->ether_src[1], p->eh->ether_src[2], p->eh->ether_src[3],
00330 p->eh->ether_src[4], p->eh->ether_src[5]);
00331 }
00332 }
00333 else if(!strncasecmp("ethdst", type, 6))
00334 {
00335 if(p->eh)
00336 {
00337 fprintf(file, "%X:%X:%X:%X:%X:%X", p->eh->ether_dst[0],
00338 p->eh->ether_dst[1], p->eh->ether_dst[2], p->eh->ether_dst[3],
00339 p->eh->ether_dst[4], p->eh->ether_dst[5]);
00340 }
00341 }
00342 else if(!strncasecmp("ethtype", type, 7))
00343 {
00344 if(p->eh)
00345 {
00346 fprintf(file,"0x%X",ntohs(p->eh->ether_type));
00347 }
00348 }
00349 else if(!strncasecmp("udplength", type, 9))
00350 {
00351 if(p->udph)
00352 fprintf(file,"%d",ntohs(p->udph->uh_len));
00353 }
00354 else if(!strncasecmp("ethlen", type, 6))
00355 {
00356 if(p->eh)
00357 fprintf(file,"0x%X",p->pkth->len);
00358 }
00359 else if(!strncasecmp("trheader", type, 8))
00360 {
00361 if(p->trh)
00362 PrintTrHeader(file, p);
00363 }
00364 else if(!strncasecmp("srcport", type, 7))
00365 {
00366 if(p->iph)
00367 {
00368 switch(p->iph->ip_proto)
00369 {
00370 case IPPROTO_UDP:
00371 case IPPROTO_TCP:
00372 fprintf(file, "%d", p->sp);
00373 break;
00374 }
00375 }
00376 }
00377 else if(!strncasecmp("dstport", type, 7))
00378 {
00379 if(p->iph)
00380 {
00381 switch(p->iph->ip_proto)
00382 {
00383 case IPPROTO_UDP:
00384 case IPPROTO_TCP:
00385 fprintf(file, "%d", p->dp);
00386 break;
00387 }
00388 }
00389 }
00390 else if(!strncasecmp("src", type, 3))
00391 {
00392 if(p->iph)
00393 fputs(inet_ntoa(p->iph->ip_src), file);
00394 }
00395 else if(!strncasecmp("dst", type, 3))
00396 {
00397 if(p->iph)
00398 fputs(inet_ntoa(p->iph->ip_dst), file);
00399 }
00400 else if(!strncasecmp("icmptype",type,8))
00401 {
00402 if(p->icmph)
00403 {
00404 fprintf(file,"%d",p->icmph->type);
00405 }
00406 }
00407 else if(!strncasecmp("icmpcode",type,8))
00408 {
00409 if(p->icmph)
00410 {
00411 fprintf(file,"%d",p->icmph->code);
00412 }
00413 }
00414 else if(!strncasecmp("icmpid",type,6))
00415 {
00416 if(p->icmph)
00417 fprintf(file,"%d",ntohs(p->icmph->s_icmp_id));
00418 }
00419 else if(!strncasecmp("icmpseq",type,7))
00420 {
00421 if(p->icmph)
00422 fprintf(file,"%d",ntohs(p->icmph->s_icmp_seq));
00423 }
00424 else if(!strncasecmp("ttl",type,3))
00425 {
00426 if(p->iph)
00427 fprintf(file,"%d",p->iph->ip_ttl);
00428 }
00429 else if(!strncasecmp("tos",type,3))
00430 {
00431 if(p->iph)
00432 fprintf(file,"%d",p->iph->ip_tos);
00433 }
00434 else if(!strncasecmp("id",type,2))
00435 {
00436 if(p->iph)
00437 fprintf(file,"%d",ntohs(p->iph->ip_id));
00438 }
00439 else if(!strncasecmp("iplen",type,5))
00440 {
00441 if(p->iph)
00442 fprintf(file,"%d",IP_HLEN(p->iph) << 2);
00443 }
00444 else if(!strncasecmp("dgmlen",type,6))
00445 {
00446 if(p->iph)
00447 fprintf(file,"%d",ntohs(p->iph->ip_len));
00448 }
00449 else if(!strncasecmp("tcpseq",type,6))
00450 {
00451 if(p->tcph)
00452 fprintf(file,"0x%lX",(u_long) ntohl(p->tcph->th_seq));
00453 }
00454 else if(!strncasecmp("tcpack",type,6))
00455 {
00456 if(p->tcph)
00457 fprintf(file,"0x%lX",(u_long) ntohl(p->tcph->th_ack));
00458 }
00459 else if(!strncasecmp("tcplen",type,6))
00460 {
00461 if(p->tcph)
00462 fprintf(file,"%d",TCP_OFFSET(p->tcph) << 2);
00463 }
00464 else if(!strncasecmp("tcpwindow",type,9))
00465 {
00466 if(p->tcph)
00467 fprintf(file,"0x%X",ntohs(p->tcph->th_win));
00468 }
00469 else if(!strncasecmp("tcpflags",type,8))
00470 {
00471 if(p->tcph)
00472 {
00473 CreateTCPFlagString(p, tcpFlags);
00474 fprintf(file,"%s", tcpFlags);
00475 }
00476 }
00477
00478 if (num < numargs - 1)
00479 fwrite(",",1,1,file);
00480 }
00481 fputc('\n', file);
00482
00483
00484 return;
00485 }
00486
00487
00488 char *CSVEscape(char *input)
00489 {
00490 size_t strLen;
00491 char *buffer;
00492 char *current;
00493 if((strchr(input, ',') == NULL) && (strchr(input, '"') == NULL))
00494 return strdup(input);
00495
00496 strLen = strlen(input);
00497 buffer = (char *)SnortAlloc((strLen * 2) + 3);
00498 current = buffer;
00499 *current = '"';
00500 ++current;
00501 while(*input != '\0')
00502 {
00503 switch(*input)
00504 {
00505 case '"':
00506 *current = '\\';
00507 ++current;
00508 *current = '"';
00509 ++current;
00510 break;
00511 case '\\':
00512 *current = '\\';
00513 ++current;
00514 *current = '\\';
00515 ++current;
00516 break;
00517 default:
00518 *current = *input;
00519 ++current;
00520 break;
00521 }
00522 ++input;
00523 }
00524 *current = '"';
00525 return buffer;
00526 }
00527