/* ** Modular Logfile Analyzer ** Copyright 2000 Jan Kneschke ** ** Homepage: http://www.modlogan.org ** 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 of the License, or (at your option) any later version, and provided that the above copyright and permission notice is included with all distributed copies of this or derived software. 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA ** ** $Id: parse.c,v 1.12 2003/04/18 18:36:05 ostborn Exp $ */ #include #include #include #include #include #include #include "mlocale.h" #include "mplugins.h" #include "mrecord.h" #include "mdatatypes.h" #include "misc.h" #include "plugin_config.h" #if 0 #define DEBUG_PCRE 1 #endif unsigned long int str2ip(mconfig *ext_conf, const char *str) { #define N 20 + 1 const char **list; int ovector[3 * N], n; unsigned long int r = 0; config_input *conf = ext_conf->plugin_conf; if ((n = pcre_exec(conf->match_ip, NULL, str, strlen(str), 0, 0, ovector, 3 * N)) < 0) { if (n == PCRE_ERROR_NOMATCH) { fprintf(stderr, "%s.%d: string doesn't match: %s\n", __FILE__, __LINE__, str); return M_RECORD_CORRUPT; } else { fprintf(stderr, "%s.%d: execution error while matching: %d\n", __FILE__, __LINE__, n); return M_RECORD_HARD_ERROR; } } if (n > 0) { pcre_get_substring_list(str, ovector, n, &list); r = strtoul(list[1], NULL, 10) << 24 | strtoul(list[2], NULL, 10) << 16 | strtoul(list[3], NULL, 10) << 8 | strtoul(list[4], NULL, 10) << 0; pcre_free(list); } #undef N return r; } typedef struct { char *string; int id; } action_mapping; const action_mapping action_map[] = { { "ACCEPT", M_RECORD_IPCHAINS_ACTION_ACCEPT }, { "DENY", M_RECORD_IPCHAINS_ACTION_DENY }, { "REJECT", M_RECORD_IPCHAINS_ACTION_REJECT }, { "MASQ", M_RECORD_IPCHAINS_ACTION_MASQ }, { NULL, M_RECORD_IPCHAINS_ACTION_UNSET } }; const char *short_month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL}; int parse_timestamp(mconfig *ext_conf, const char *str, mlogrec *record) { #define N 20 + 1 int ovector[3 * N], n, i; char buf[10]; struct tm tm; config_input *conf = ext_conf->plugin_conf; if ((n = pcre_exec(conf->match_timestamp, NULL, str, strlen(str), 0, 0, ovector, 3 * N)) < 0) { if (n == PCRE_ERROR_NOMATCH) { fprintf(stderr, "%s.%d: string doesn't match: %s\n", __FILE__, __LINE__, str); return M_RECORD_CORRUPT; } else { fprintf(stderr, "%s.%d: execution error while matching: %d\n", __FILE__, __LINE__, n); return M_RECORD_HARD_ERROR; } } memset(&tm, 0, sizeof(struct tm)); /* everything has matched, take the different pieces and be happy :) */ pcre_copy_substring(str, ovector, n, 2, buf, sizeof(buf)); tm.tm_mday = strtol(buf, NULL, 10); pcre_copy_substring(str, ovector, n, 1, buf, sizeof(buf)); for (i = 0; short_month[i];i++) { if (!strcmp(buf, short_month[i])) { tm.tm_mon = i; } } /* no year provided :( */ tm.tm_year = 2000 - 1900; pcre_copy_substring(str, ovector, n, 3, buf, sizeof(buf)); tm.tm_hour = strtol(buf, NULL, 10); pcre_copy_substring(str, ovector, n, 4, buf, sizeof(buf)); tm.tm_min = strtol(buf, NULL, 10); pcre_copy_substring(str, ovector, n, 5, buf, sizeof(buf)); tm.tm_sec = strtol(buf, NULL, 10); record->timestamp = mktime (&tm); return M_RECORD_NO_ERROR; #undef N } int parse_record_pcre(mconfig *ext_conf, mlogrec *record, buffer *b) { #define N 20 + 1 const char **list; int ovector[3 * N], n, i; config_input *conf = ext_conf->plugin_conf; mlogrec_traffic *rectrf = NULL; mlogrec_traffic_ipchains *recipc = NULL; record->ext_type = M_RECORD_TYPE_TRAFFIC; record->ext = mrecord_init_traffic(); rectrf = record->ext; if (rectrf == NULL) return M_RECORD_HARD_ERROR; rectrf->ext = mrecord_init_traffic_ipchains(); rectrf->ext_type = M_RECORD_TYPE_TRAFFIC_IPCHAINS; recipc = rectrf->ext; if (recipc == NULL) return M_RECORD_HARD_ERROR; if ((n = pcre_exec(conf->match_syslog, NULL, b->ptr, b->used - 1, 0, 0, ovector, 3 * N)) < 0) { if (n == PCRE_ERROR_NOMATCH) { fprintf(stderr, "%s.%d: string doesn't match: %s\n", __FILE__, __LINE__, b->ptr); return M_RECORD_CORRUPT; } else { fprintf(stderr, "%s.%d: execution error while matching: %d\n", __FILE__, __LINE__, n); return M_RECORD_HARD_ERROR; } } if ((n = pcre_exec(conf->match_ipchains, conf->match_ipchains_extra, b->ptr, b->used - 1, 0, 0, ovector, 3 * N)) < 0) { if (n == PCRE_ERROR_NOMATCH) { if (ext_conf->debug_level > 3) fprintf(stderr, "%s.%d: string doesn't match: %s\n", __FILE__, __LINE__, b->ptr); return M_RECORD_IGNORED; } else { fprintf(stderr, "%s.%d: execution error while matching: %d\n", __FILE__, __LINE__, n); return M_RECORD_HARD_ERROR; } } if (n == 18) { pcre_get_substring_list(b->ptr, ovector, n, &list); /* 0: Jan 18 00:34:25 weigon kernel: Packet log: input ACCEPT ppp0 PROTO=6 134.2.170.93:4509 62.225.219.160:25 L=60 S=0x00 I=44540 F=0x4000 T=52 SYN (#48) 1: Jan 18 00:34:25 - Date without year 2: weigon - host 3: input - chain 4: ACCEPT - action 5: ppp0 -device 6: 6 - protocol 7: 134.2.170.93 - source ip 8: 4509 - source port 9: 62.225.219.160 - dest ip 10: 25 - dest port 11: 60 12: 0x00 13: 44540 14: 0x4000 15: 52 16: SYN - flags 17: 48 - rule */ switch (parse_timestamp(ext_conf, list[1], record)) { case M_RECORD_CORRUPT: free(list); return M_RECORD_CORRUPT; case M_RECORD_HARD_ERROR: free(list); return M_RECORD_HARD_ERROR; } rectrf->src = malloc(strlen(list[7])+1); strcpy(rectrf->src, list[7]); rectrf->dst = malloc(strlen(list[9])+1); strcpy(rectrf->dst, list[9]); recipc->chain = malloc(strlen(list[3])+1); strcpy(recipc->chain, list[3]); recipc->device = malloc(strlen(list[5])+1); strcpy(recipc->device, list[5]); recipc->host = malloc(strlen(list[2])+1); strcpy(recipc->host, list[2]); recipc->protocol = strtoul(list[6], NULL, 10); recipc->src_port = strtoul(list[8], NULL, 10); recipc->dst_port = strtoul(list[10], NULL, 10); recipc->rule = strtoul(list[17], NULL, 10); i = 0; while (action_map[i].string) { if (!strcmp(action_map[i].string, list[14])) break; i++; } recipc->action = (action_map[i].string) ? action_map[i].id : M_RECORD_IPCHAINS_ACTION_UNSET; #ifdef DEBUG_PCRE for (i = 0; i < n; i++) { printf("%d: %s\n", i, list[i]); } #endif free(list); } else { return M_RECORD_HARD_ERROR; } return M_RECORD_NO_ERROR; #undef N } int mplugins_input_ipchains_get_next_record(mconfig *ext_conf, mlogrec *record) { int ret = 0; config_input *conf = ext_conf->plugin_conf; if (record == NULL) return M_RECORD_HARD_ERROR; /* fill the line buffer */ if (NULL == mgets(&(conf->inputfile), conf->buf)) return M_RECORD_EOF; ret = parse_record_pcre (ext_conf, record, conf->buf); if (ret == M_RECORD_CORRUPT) { M_DEBUG1(ext_conf->debug_level, M_DEBUG_SECTION_PARSING, M_DEBUG_LEVEL_WARNINGS, "affected Record: %s\n", conf->buf->ptr ); } return ret; }