/*
* logtool - a logfile parsing/monitoring/manipulation utility
*
* Copyright (C) Y2K (2000) A.L.Lambert
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* Yee ole includes (I put this all in one file for my sanity) */
#include "includes.h"
/*
* NOTES:
*
* This is some LONG and UGLY code. I think there's gotta be a way to
* simplify it a whole lot, and to clean up some of the ugly, but for now
* it's getting the job done. Too much stuff in one file for my tastes too.
* :(
*
* Also, all yee would be code tweakers; the order in which these functions
* are called is IMPORTANT!!! Each parser function modifies event.message,
* and all subsequent parsing efforts expect previous ones to have been
* completed. YOU WERE WARNED!!!
*
*/
/* function to parse up the SID's from event.message (if exists) */
short int ltm_snort_psids(char *sids) {
/* some tmp data storage */
char tmp_str[LSIZE];
long int i;
/* if we got SID information at the beginning of the message, then crunch it into separate variable */
if(lt_match(event.message, "^\\[.*:.*:.*\\] .*") == TRUE) {
sscanf(event.message, "%s %[^\n]", sids, tmp_str); /* strip the first string */
strcpy(event.message, tmp_str); /* copy the remainder back to event.message */
strcpy(tmp_str, "");
if(cf.outfmt == OUTPUT_ANSI || cf.outfmt == OUTPUT_HTML) {
for (i = 0 ; sids[i] != '\0' ; ++i ) {
if(sids[i] == '[') {
strcpy(tmp_str, "\033l[\033e\033c");
} else if(sids[i] == ']') {
strcat(tmp_str, "\033e\033l]\033e");
} else {
sprintf(tmp_str, "%s%c", tmp_str, sids[i]);
}
}
strcpy(sids, tmp_str);
}
}
/* add a space to the end of it so it doesn't look so cramped later */
return 0;
}
/* function to parse the (snort_preprocessor) text field (if exist) */
short int ltm_snort_pproc(char *pproc) {
/* some tmp data storage */
char tmp_str[LSIZE];
long int i;
/* see notes in ltm_snort_psids(); above */
if(lt_match(event.message, "^\\(.*_.*\\) ") == TRUE) {
sscanf(event.message, "%s %[^\n]", pproc, tmp_str);
strcpy(event.message, tmp_str);
/* do some special effects if our output format == ansi */
if(cf.outfmt == OUTPUT_ANSI || cf.outfmt == OUTPUT_HTML) {
for (i = 0 ; pproc[i] != '\0' ; ++i ) {
if(pproc[i] == '(') {
strcpy(tmp_str, "\033l(\033e\033c");
} else if(pproc[i] == ')') {
strcat(tmp_str, "\033e\033l)\033e");
} else {
sprintf(tmp_str, "%s%c", tmp_str, pproc[i]);
}
}
strcpy(pproc, tmp_str);
}
}
return 0;
}
/* function to parse the "x.x.x.x:x -> x.x.x.x:x" from the end of a Snort message (if exist) */
short int ltm_snort_pips(char *src, char *src_prt, char *dst, char *dst_prt, short int resolv) {
long int i, j;
char *ptr;
char tmp_str[LSIZE];
ptr = event.message;
/* backspace from the end of the line, counting spaces to three */
for(i = (strlen(event.message) - 1), j = 0; j < 3; --i) {
if(event.message[i] == ' ') ++j;
}
/* increment the ptr to the appropriate spot */
ptr = (ptr + i + 1);
/* null byte it (will insert null byte into event.message
* to clip the part we're about to parse separately) */
ptr[0] = '\0';
++ptr; /* move ptr forward so we can work with data directly */
if(strstr(ptr, ":") != NULL) { /* then we've got a src:src_prt scenario */
sscanf(ptr, "%[^:]:%s -> %[^:]:%s", src, src_prt, dst, dst_prt);
} else { /* this was probably an ICMP message; IP's only */
sscanf(ptr, "%s -> %s", src, dst);
strcpy(dst_prt, ""); /* overkill way to make sure variable is blank */
strcpy(src_prt, "");
}
if(resolv == TRUE) {
ptr = get_host(src);
if(ptr != NULL) {
strcpy(tmp_str, src);
strcpy(src, ptr);
strcat(src, "(");
strcat(src, tmp_str);
strcat(src, ")");
}
ptr = get_host(dst);
if(ptr != NULL) {
strcpy(tmp_str, dst);
strcpy(dst, ptr);
strcat(dst, "(");
strcat(dst, tmp_str);
strcat(dst, ")");
}
if(cf.outfmt == OUTPUT_ANSI || cf.outfmt == OUTPUT_HTML) {
sprintf(tmp_str, "\033l(\033e\033w");
lt_strep(src, 512, "(", tmp_str);
lt_strep(dst, 512, "(", tmp_str);
sprintf(tmp_str, "\033l)\033e");
lt_strep(src, 512, ")", tmp_str);
lt_strep(dst, 512, ")", tmp_str);
}
}
/* if we're making an ANSI event, then do some special fancy tricks. */
if(cf.outfmt == OUTPUT_ANSI || cf.outfmt == OUTPUT_HTML) {
/* yeah, I could do all the below as a single sprintf(), and I may be doing
* that soon. */
strcpy(tmp_str, "\033W");
strcat(tmp_str, src);
strcat(tmp_str, "\033e");
strcpy(src, tmp_str);
/* ditto */
strcpy(tmp_str, "\033W");
strcat(tmp_str, dst);
strcat(tmp_str, "\033e");
strcpy(dst, tmp_str);
/* if we got src/dst port's, then do the deed to them too */
if(src_prt[0] != '\0') {
strcpy(tmp_str, "\033W");
strcat(tmp_str, src_prt);
strcat(tmp_str, "\033e");
strcpy(src_prt, tmp_str);
strcpy(tmp_str, "\033W");
strcat(tmp_str, dst_prt);
strcat(tmp_str, "\033e");
strcpy(dst_prt, tmp_str);
}
}
return 0;
}
/* function to parse the {PROTOCOL} text from a Snort event (if exist) */
short int ltm_snort_pproto(char *proto) {
char *ptr = NULL;
char tmp_str[LSIZE];
/* if we got a TCP, UDP, or ICMP message */
if(lt_match(event.message, "\\{TCP\\}$|\\{UDP\\}$|\\{ICMP\\}$") == TRUE) {
/* parse it out of there */
ptr = strrchr(event.message, ' ');
ptr[0] = '\0';
++ptr;
strcpy(proto, ptr);
}
/* you know about the ANSI prettyfication by now, don't you? */
if(cf.outfmt == OUTPUT_ANSI || cf.outfmt == OUTPUT_HTML) {
strcpy(tmp_str, "\033l");
strcat(tmp_str, "{");
strcat(tmp_str, "\033e");
strcat(tmp_str, "\033C");
lt_strep(proto, 512, "{", tmp_str);
strcpy(tmp_str, "\033l");
strcat(tmp_str, "}");
strcat(tmp_str, "\033e");
lt_strep(proto, 512, "}", tmp_str);
}
return 0;
}
/* function to parse the [Priority: .*] text from a Snort event (if exist) */
short int ltm_snort_pprior(char *prior) {
char *ptr;
char tmp_str[LSIZE];
if((ptr = strstr(event.message, "[Priority: ")) != NULL) {
strcpy(prior, ptr);
--ptr;
ptr[0] = '\0';
}
lt_strep(prior, 512, "[Priority: ", "[Pri: ");
if(cf.outfmt == OUTPUT_ANSI || cf.outfmt == OUTPUT_HTML) {
strcpy(tmp_str, "\033l");
strcat(tmp_str, "[");
strcat(tmp_str, "\033e");
strcat(tmp_str, "\033c");
lt_strep(prior, 512, "[", tmp_str);
strcpy(tmp_str, "\033l");
strcat(tmp_str, "]");
strcat(tmp_str, "\033e");
lt_strep(prior, 512, "]", tmp_str);
}
return 0;
}
/* function to parse the [Classification: .*] text from a snrot event (if exist) */
short int ltm_snort_pclass(char *class) {
char *ptr;
char tmp_str[LSIZE];
if((ptr = strstr(event.message, "[Classification: ")) != NULL) {
strcpy(class, ptr);
--ptr;
ptr[0] = '\0';
}
lt_strep(class, 512, "[Classification: ", "[");
if(cf.outfmt == OUTPUT_ANSI || cf.outfmt == OUTPUT_HTML) {
strcpy(tmp_str, "\033l");
strcat(tmp_str, "[");
strcat(tmp_str, "\033e");
strcat(tmp_str, "\033c");
lt_strep(class, 512, "[", tmp_str);
strcpy(tmp_str, "\033l");
strcat(tmp_str, "]");
strcat(tmp_str, "\033e");
lt_strep(class, 512, "]", tmp_str);
}
return 0;
}
/*
* yee ole showtime function. This is the only function which should be
* called by any external routines.
*/
short int ltm_snort() {
/* various varibles and such are in mods.h struct SNORT */
/* we use these in parsing and such */
char msg_tmp[LSIZE];
/* some TRUE/FALSE variables for display opts */
short int modsn_dispclass = FALSE;
short int modsn_dispprior = FALSE;
short int modsn_dispproto = FALSE;
short int modsn_2lines = FALSE;
short int modsn_dispsids = FALSE;
short int modsn_dispproc = FALSE;
short int modsn_resolvips = FALSE;
/* setup the display opt's based no environment */
modsn_dispclass = mod_varcheck("modsn_dispclass");
modsn_dispprior = mod_varcheck("modsn_dispprior");
modsn_dispproto = mod_varcheck("modsn_dispproto");
modsn_dispsids = mod_varcheck("modsn_dispsids");
modsn_dispproc = mod_varcheck("modsn_dispproc");
modsn_2lines = mod_varcheck("modsn_2lines");
modsn_resolvips = mod_varcheck("modsn_resolvips");
/* Figure out what color this message should be */
lt_set_event_color();
/* parse up the basics (date format's, prog/src, etc) */
mod_premsg_setup();
/* initialize sids, and parse it if we can */
strcpy(sn.sids, "");
ltm_snort_psids(sn.sids);
/* ditto for pproc */
strcpy(sn.pproc, "");
ltm_snort_pproc(sn.pproc);
/* ok, got the first parts of the line processed, head
* for the rear of the line and do the IP's */
ltm_snort_pips(sn.src, sn.src_prt, sn.dst, sn.dst_prt, modsn_resolvips);
/* see comments above regarding sids and pproc */
strcpy(sn.proto, "");
ltm_snort_pproto(sn.proto);
strcpy(sn.prior, "");
ltm_snort_pprior(sn.prior);
strcpy(sn.class, "");
ltm_snort_pclass(sn.class);
/* ok, now we're ready to setup the event.pmsg
* (which is what we show the user later :)
*
* If we got display orders, and variables not == nothing, then do */
/* this puts the main message, in appropriate colors, into the output */
sprintf(msg_tmp, "%s%s%s", event.pcolor, event.message, "\033e");
strcpy(sn.msg, event.message);
strcat(event.pmsg, " ");
strcat(event.pmsg, msg_tmp);
if(modsn_dispproc == TRUE && sn.pproc[0] != '\0') {
strcat(event.pmsg, " ");
strcat(event.pmsg, sn.pproc);
}
if(modsn_dispsids == TRUE && sn.sids[0] != '\0') {
strcat(event.pmsg, " ");
strcat(event.pmsg, sn.sids);
}
/* if we want a 2line display, then do this */
if(modsn_2lines == TRUE && cf.outfmt != OUTPUT_CSV) strcat(event.pmsg, "\n\t");
if(modsn_dispclass == TRUE && sn.class[0] != '\0') {
strcat(event.pmsg, " ");
strcat(event.pmsg, sn.class);
}
if(modsn_dispprior == TRUE && sn.prior[0] != '\0') {
strcat(event.pmsg, " ");
strcat(event.pmsg, sn.prior);
}
if(modsn_dispproto == TRUE && sn.proto[0] != '\0') {
strcat(event.pmsg, " ");
strcat(event.pmsg, sn.proto);
}
if(sn.src_prt[0] != '\0') {
if(cf.outfmt == OUTPUT_ANSI || cf.outfmt == OUTPUT_HTML) {
sprintf(msg_tmp, "%s\033l:%s \033l-> %s\033l:\033e%s", sn.src, sn.src_prt, sn.dst, sn.dst_prt);
} else {
sprintf(msg_tmp, "%s:%s -> %s:%s", sn.src, sn.src_prt, sn.dst, sn.dst_prt);
}
} else {
if(cf.outfmt == OUTPUT_ANSI || cf.outfmt == OUTPUT_HTML) {
sprintf(msg_tmp, "%s \033l-> %s", sn.src, sn.dst);
} else {
sprintf(msg_tmp, "%s -> %s", sn.src, sn.dst);
}
}
/* final finishing off of event.pmsg */
strcat(event.pmsg, " ");
strcat(event.pmsg, msg_tmp);
event.m.snort = &sn;
/* we did some debug testing with the code block below */ /*
fprintf(stderr, "msg:%s\n", event.m.snort->msg);
fprintf(stderr, "dst:prt:%s:%s\n", event.m.snort->dst, event.m.snort->dst_prt);
fprintf(stderr, "src:prt:%s:%s\n", event.m.snort->src, event.m.snort->src_prt);
fprintf(stderr, "sids:%s\n", event.m.snort->sids);
fprintf(stderr, "pproc:%s\n", event.m.snort->pproc);
fprintf(stderr, "proto:%s\n", event.m.snort->proto);
fprintf(stderr, "class:%s\n", event.m.snort->class);
fprintf(stderr, "prior:%s\n", event.m.snort->prior);
*/
/* return 0; We really should be checking for errors above,
* and bombing out if we got something bad, but hey, such is life. */
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1