/* * 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 */ #include "includes.h" /* A regex function to match paterns */ int lt_match(const char *string, char *pattern) /* This means "what you want to search", "what you want to search for" */ { int status; regex_t re; if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB) != 0) { return(FALSE); /* report error */ } status = regexec(&re, string, (size_t) 0, NULL, 0); regfree(&re); if (status != 0) { return(FALSE); /* report error */ } return(TRUE); } /* a function to match against pre-compiled regex's */ int lt_match_re(const char *string, regex_t re) { int status; status = regexec(&re, string, (size_t) 0, NULL, 0); if (status != 0) { return FALSE; } else { return TRUE; } } int lt_filelen(FILE *file) { int retval = 0; /* find out how long the file is */ fseek(file, 0, SEEK_END); /* seek end of file */ retval = ftell(file); /* get byte value */ fseek(file, 0, SEEK_SET); /* return to begin */ return retval; /* return size of file */ } short int lt_load_regex(char *file, char **dest, regex_t *re) { char line[LSIZE]; char tmp[LSIZE]; char count = 1; FILE *fileptr; short int retval; DIR *dir; struct stat *stbuf; char *fname; struct dirent *de; stbuf=malloc(sizeof(struct stat)); if(stat(file, stbuf)<0) { /* Could not stat, so, back out */ if(cf.debug) fprintf(stderr, "Could not stat %s\n", file); return FALSE; } if(S_ISDIR(stbuf->st_mode)) { dir=opendir(file); if( ! dir ) { if(cf.debug) fprintf(stderr, "Could not opendir %s\n", file); return FALSE; } while((de=readdir(dir))) { if(!strncmp(de->d_name, ".", 1)) continue; fname=malloc(strlen(file)+strlen(de->d_name)+2); sprintf(fname, "%s/%s", file, de->d_name); if(!lt_load_regex(fname, dest, re)) { if(cf.debug) fprintf(stderr, "error occured, bailing out\n"); free(fname); return FALSE; } free(fname); } return TRUE; } fileptr = fopen(file, "r"); if( ! fileptr ) { if(cf.debug) fprintf(stderr, "unable to open file: %s\n", file); /* oopsie; no such file; abort this loading, and return FALSE */ return FALSE; } /* we malloc enough space for 2 of these files just to be safe we don't * overflow as we add |'s and such to build the regexec string */ *dest = malloc(lt_filelen(fileptr) * 2); *dest[0] = '\0'; /* while we read the file, and don't have comments */ while(fgets(line, LSIZE, fileptr) != NULL) { if(lt_match(line, "^#|^$") == 0) { sscanf(line, "%[^\n]", tmp); if(count == 1) { strncat(*dest, tmp, strlen(tmp) + 1); count = 2; } else { strncat(*dest, "|", 2); strncat(*dest, tmp, strlen(tmp) + 1); } } } /* close off yee ole file pointer */ fclose(fileptr); /* if we got no valid regex's, then return false */ if(*dest[0] == '\0') { /* we had no strings, nevermind */ retval = FALSE; } else { retval = TRUE; /* assume those strings are valid */ /* see if we can compile the patern into a regex */ if (regcomp(re, *dest, REG_EXTENDED|REG_NOSUB) != 0) { /* oops; wouldn't compile.. nevermind */ return(FALSE); /* report error */ } } if(cf.debug) fprintf(stderr, "opened file: %s and got strings >%s<\n", file, *dest); return (retval); } void lt_loadstrings() { /* for all the regex's we want to load, hit em up here */ /* if you're adding one of these, see logtool.h, readconf.c and regex.c */ /* I need to get off my butt and init this in lt_set_regfile() in readconf.c instead of here, :) */ reg.include_check = lt_load_regex(reg.include_file, ®.include_strs, ®.include_reg); reg.exclude_check = lt_load_regex(reg.exclude_file, ®.exclude_strs, ®.exclude_reg); reg.green_check = lt_load_regex(reg.green_file, ®.green_strs, ®.green_reg); reg.brightgreen_check = lt_load_regex(reg.brightgreen_file, ®.brightgreen_strs, ®.brightgreen_reg); reg.yellow_check = lt_load_regex(reg.yellow_file, ®.yellow_strs, ®.yellow_reg); reg.brightyellow_check =lt_load_regex(reg.brightyellow_file, ®.brightyellow_strs, ®.brightyellow_reg); reg.blue_check = lt_load_regex(reg.blue_file, ®.blue_strs, ®.blue_reg); reg.brightblue_check = lt_load_regex(reg.brightblue_file, ®.brightblue_strs, ®.brightblue_reg); reg.cyan_check = lt_load_regex(reg.cyan_file, ®.cyan_strs, ®.cyan_reg); reg.brightcyan_check = lt_load_regex(reg.brightcyan_file, ®.brightcyan_strs, ®.brightcyan_reg); reg.magenta_check = lt_load_regex(reg.magenta_file, ®.magenta_strs, ®.magenta_reg); reg.brightmagenta_check = lt_load_regex(reg.brightmagenta_file, ®.brightmagenta_strs, ®.brightmagenta_reg); reg.brightred_check = lt_load_regex(reg.brightred_file, ®.brightred_strs, ®.brightred_reg); } /* our different event types defined: for EVENT_*. They are (currently) SYSLOG, SNORT, and IPTABLES */ /* Laurent Jacquot: I have got some lines not matching ^[A-Z] ... */ char syslog_format[256] = "^[A-Za-z][a-z][a-z] .[0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9] .* .* .*$"; char snort_format[256] = "^[A-Za-z][a-z][a-z] .[0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9] .* snort.*: .*[0-9] -> .*[0-9].*$"; char iptables_format[256] = "^[A-Za-z][a-z][a-z] .[0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9] .*IN=.* OUT=.* SRC=.* DST=.* .*$"; regex_t syslog_freg; regex_t snort_freg; regex_t iptables_freg; void lt_regexinit() { regcomp(&syslog_freg, syslog_format, REG_EXTENDED|REG_NOSUB); regcomp(&snort_freg, snort_format, REG_EXTENDED|REG_NOSUB); regcomp(&iptables_freg, iptables_format, REG_EXTENDED|REG_NOSUB); lt_loadstrings(); } /* currently known event types: SNORT SYSLOG UNKNOWN */ short int lt_fmtcheck(char *tmp) { short int retval = -1; if(lt_match_re(tmp, syslog_freg) == TRUE) { retval = EVENT_SYSLOG; } if(lt_match_re(tmp, snort_freg) == TRUE) { retval = EVENT_SNORT; } if(lt_match_re(tmp, iptables_freg) == TRUE) { retval = EVENT_IPTABLES; } if(retval == -1) { retval = EVENT_UNKNOWN; } return retval; }