/* ** 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.8 2003/07/08 10:23:50 miham 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 #define DEBUG_TS #endif mlogrec_traffic_ippl *mrecord_init_traffic_ippl(); int parse_icmp_record_pcre(mconfig *ext_conf, mlogrec *record, buffer *b); int parse_tcp_record_pcre(mconfig *ext_conf, mlogrec *record, buffer *b); int parse_udp_record_pcre(mconfig *ext_conf, mlogrec *record, buffer *b); int parse_repeating_record_pcre(mconfig *ext_conf, mlogrec *record, buffer *b); int parse_ipmon_record_pcre(mconfig *ext_conf, mlogrec *record, buffer *b); // Added 06/09/03 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; } const char *short_month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL}; int check_ignores(mconfig *ext_conf, const char *src, const char *dst, const int src_port, const int dst_port) { config_input *conf = ext_conf->plugin_conf; if (!conf) return -1; if ((!mlist_is_empty(conf->ignored_shosts) && mlist_in_list(conf->ignored_shosts, src)) || (!mlist_is_empty(conf->ignored_dhosts) && mlist_in_list(conf->ignored_dhosts, dst))) return 1; if (src_port && !mlist_is_empty(conf->ignored_sports)) { char *spstr = malloc(6); sprintf(spstr, "%d", src_port); if (mlist_in_list(conf->ignored_sports, spstr)) { free(spstr); return 1; } free(spstr); } if (dst_port && !mlist_is_empty(conf->ignored_dports)) { char *dpstr = malloc(6); sprintf(dpstr, "%d", dst_port); if (mlist_in_list(conf->ignored_dports, dpstr)) { free(dpstr); return 1; } free(dpstr); } return 0; } 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)); if (n != 6 ) return -1; /* 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); #ifdef DEBUG_TS fprintf( stderr, "Day: %s, ", buf ); #endif 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; break; } } #ifdef DEBUG_TS fprintf( stderr, "month: %d, ", i ); #endif /* no year provided :( */ tm.tm_year = 2003 - 1900; pcre_copy_substring(str, ovector, n, 3, buf, sizeof(buf)); tm.tm_hour = strtol(buf, NULL, 10); #ifdef DEBUG_TS fprintf( stderr, "hour: %s, ", buf ); #endif pcre_copy_substring(str, ovector, n, 4, buf, sizeof(buf)); tm.tm_min = strtol(buf, NULL, 10); #ifdef DEBUG_TS fprintf( stderr, "min: %s, ", buf ); #endif pcre_copy_substring(str, ovector, n, 5, buf, sizeof(buf)); tm.tm_sec = strtol(buf, NULL, 10); #ifdef DEBUG_TS fprintf( stderr, "sec: %s, ", buf ); #endif record->timestamp = mktime (&tm); #ifdef DEBUG_TS fprintf(stderr, "timestamp: %10ld\n", record->timestamp); #endif 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; config_input *conf = ext_conf->plugin_conf; mlogrec_traffic *rectrf = NULL; mlogrec_traffic_ippl *recipl = NULL; if (record->ext_type != M_RECORD_TYPE_TRAFFIC) { if (record->ext_type != M_RECORD_TYPE_UNSET) { mrecord_free_ext(record); } 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_ippl(); rectrf->ext_type = M_RECORD_TYPE_TRAFFIC_IPPL; recipl = rectrf->ext; if (recipl == NULL) return M_RECORD_HARD_ERROR; if ((n = pcre_exec(conf->match_timestamp, 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_linetype, conf->match_linetype_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 ( (!conf->loglevel && n != 2 ) || (conf->loglevel && n != 3 ) ) { fprintf(stderr, "%s.%d: unable to determine line-type!\nProbably bad loglevel (current: %d)?\nLine was: %s\n\n", __FILE__, __LINE__, conf->loglevel, b->ptr ); return M_RECORD_HARD_ERROR; } pcre_get_substring_list(b->ptr, ovector, n, &list); if (!conf->loglevel) { switch (*list[1] ) { case 'I': if (ext_conf->debug_level > 3) fprintf(stderr, "%s.%d: chosen linetype is ICMP for line: '%s'\n", __FILE__, __LINE__, b->ptr); pcre_free_substring_list(list); return parse_icmp_record_pcre( ext_conf, record, b ); case 'T': if (ext_conf->debug_level > 3) fprintf(stderr, "%s.%d: chosen linetype is TCP for line: '%s'\n", __FILE__, __LINE__, b->ptr); #ifdef DEBUG_PCRE fprintf(stderr, "Is to be calling parse_tcp_record_pcre()!\n" ); #endif pcre_free_substring_list(list); return parse_tcp_record_pcre( ext_conf, record, b ); case 'U': if (ext_conf->debug_level > 3) fprintf(stderr, "%s.%d: chosen linetype is UDP for line: '%s'\n", __FILE__, __LINE__, b->ptr); pcre_free_substring_list(list); return parse_udp_record_pcre( ext_conf, record, b ); case 'l': if (ext_conf->debug_level > 3) fprintf(stderr, "%s.%d: chosen linetype is repeat for line: '%s'\n", __FILE__, __LINE__, b->ptr); pcre_free_substring_list(list); return parse_repeating_record_pcre( ext_conf, record, b ); default: if (ext_conf->debug_level > 3) fprintf(stderr, "%s.%d: unable to choose linetype for line: '%s' - line ignored!\n", __FILE__, __LINE__, b->ptr); pcre_free_substring_list(list); return M_RECORD_IGNORED; } } else { switch (*list[1] ) { case 'I': if (ext_conf->debug_level > 3) fprintf(stderr, "%s.%d: chosen linetype is ICMP for line: '%s'\n", __FILE__, __LINE__, b->ptr); pcre_free_substring_list(list); return parse_icmp_record_pcre( ext_conf, record, b ); case 'l': if (ext_conf->debug_level > 3) fprintf(stderr, "%s.%d: chosen linetype is repeat for line: '%s'\n", __FILE__, __LINE__, b->ptr); pcre_free_substring_list(list); return parse_repeating_record_pcre( ext_conf, record, b ); default: switch (*list[2] ) { /*** Added 06/09/03 -- parses ipmon lines ***/ case 'i': if (ext_conf->debug_level > 3) fprintf(stderr, "%s.%d: chosen linetype is ipmon for line: '%s'\n", __FILE__, __LINE__, b->ptr); pcre_free_substring_list(list); return parse_ipmon_record_pcre( ext_conf, record, b ); case 'U': if (ext_conf->debug_level > 3) fprintf(stderr, "%s.%d: chosen linetype is UDP for line: '%s'\n", __FILE__, __LINE__, b->ptr); pcre_free_substring_list(list); return parse_udp_record_pcre( ext_conf, record, b ); case 'c': if (ext_conf->debug_level > 3) fprintf(stderr, "%s.%d: chosen linetype is TCP for line: '%s'\n", __FILE__, __LINE__, b->ptr); #ifdef DEBUG_PCRE fprintf(stderr, "Is to be calling parse_tcp_record_pcre()!\n" ); #endif pcre_free_substring_list(list); return parse_tcp_record_pcre( ext_conf, record, b ); default: if (ext_conf->debug_level > 3) fprintf(stderr, "%s.%d: unable to choose linetype for line: '%s' - line ignored!\n", __FILE__, __LINE__, b->ptr); pcre_free_substring_list(list); return M_RECORD_IGNORED; } } } pcre_free_substring_list(list); /* Never reached .. */ return M_RECORD_IGNORED; } int parse_repeating_record_pcre( mconfig *ext_conf, mlogrec *record, buffer *b ) { #define N 20 + 1 const char **list; int ovector[3 * N], n; config_input *conf = ext_conf->plugin_conf; int repnum; /* We did't want to repeat the previos line, * if that was ignored for some reason.. * * And we don't want to toggle the ignoredline switch, * because of the multiple, repeated 'Last line repeated...' message */ if (conf->lastignored) return M_RECORD_IGNORED; /* Ok, let's start it.. */ if ((n = pcre_exec(conf->match_repline, conf->match_rep_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 != 2) { if (ext_conf->debug_level > 3) fprintf(stderr, "%s.%d: string doesn't match: %s\n", __FILE__, __LINE__, b->ptr); return M_RECORD_IGNORED; } pcre_get_substring_list(b->ptr, ovector, n, &list); /* the meaning of the different fields */ /* * 0: May 6 08:03:54 last message repeated 2 time(s) * 1: 2 */ if( conf->internal_copy != NULL && conf->internal_copy->ext_type == M_RECORD_TYPE_TRAFFIC ) { mrecord_reset( record ); #ifdef DEBUG_PCRE fprintf( stderr, "%s.%d: Debug: trying to run mrecord_copy()\n", __FILE__, __LINE__ ); #endif mrecord_copy( record, conf->internal_copy ); } else { pcre_free_substring_list(list); return M_RECORD_IGNORED; } if( (repnum = strtoul(list[1], NULL, 10)) != 1 ) { conf->repeatnum = repnum-1; } pcre_free_substring_list(list); return M_RECORD_NO_ERROR; } int parse_tcp_record_pcre( mconfig *ext_conf, mlogrec *record, buffer *b ) { #define N 20 + 1 const char **list; char *atsign; int ovector[3 * N], n; config_input *conf = ext_conf->plugin_conf; mlogrec_traffic *rectrf = NULL; mlogrec_traffic_ippl *recipl = NULL; if (record->ext_type != M_RECORD_TYPE_TRAFFIC) { if (record->ext_type != M_RECORD_TYPE_UNSET) { mrecord_free_ext(record); } 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_ippl(); rectrf->ext_type = M_RECORD_TYPE_TRAFFIC_IPPL; recipl = rectrf->ext; if (recipl == NULL) return M_RECORD_HARD_ERROR; #ifdef DEBUG_PCRE fprintf( stderr, "%s.%d: debug: about to call pcre_exec()!\n", __FILE__, __LINE__ ); #endif if ((n = pcre_exec(conf->match_tcpline, conf->match_tcp_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; } } #ifdef DEBUG_PCRE fprintf( stderr, "%s.%d: debug: about to check paramlist!\n", __FILE__, __LINE__ ); #endif /* 6 + 4*(conf->loglevel/2) results 10 for detailed loglevel and 6 for others */ if (n != 6 + 4 * (conf->loglevel/2)) { if (ext_conf->debug_level > 3) fprintf(stderr, "%s.%d: string had only %d match: %s\n", __FILE__, __LINE__, n, b->ptr); return M_RECORD_IGNORED; } #ifdef DEBUG_PCRE fprintf( stderr, "%s.%d: debug: about to get paramlist!\n", __FILE__, __LINE__ ); #endif pcre_get_substring_list(b->ptr, ovector, n, &list); /* the meaning of the different fields */ /* * 0 - May 15 18:02:07 port 34437 connection closed from 160.114.120.249 (160.114.120.249:25->160.114.48.30:34437) * 1 - May 15 18:02:07 * 2 - port 34437 * 3 - closed * 4 - (empty) * 5 - 160.114.120.249 * (6-9 is only for detailed loglevel) * 6 - 160.114.120.249 * 7 - 25 * 8 - 160.114.48.30 * 9 - 34437 */ #ifdef DEBUG_PCRE fprintf( stderr, "%s.%d: debug: parse_timestamp() will be called!\n", __FILE__, __LINE__ ); #endif switch (parse_timestamp(ext_conf, list[1], record)) { case M_RECORD_CORRUPT: conf->lastignored = 1; pcre_free_substring_list(list); return M_RECORD_CORRUPT; case M_RECORD_HARD_ERROR: pcre_free_substring_list(list); return M_RECORD_HARD_ERROR; } /* traffic datas (unknown) */ rectrf->xfer_incoming = 0; rectrf->xfer_outgoing = 0; /* protocoll type */ recipl->prototype = M_RECORD_IPPL_PROTOCOL_TCP; #ifdef DEBUG_PCRE fprintf( stderr, "%s.%d: debug: protoname member will be filled!\n", __FILE__, __LINE__ ); #endif /* protocoll name */ recipl->protoname = strdup(list[2]); #ifdef DEBUG_PCRE fprintf( stderr, "%s.%d: debug: conn_state member will be filled!\n", __FILE__, __LINE__ ); #endif /* connection state */ switch( *list[3] ) { case 'a': recipl->conn_state = M_RECORD_IPPL_CONNATTEMPT; break; case 'c': recipl->conn_state = M_RECORD_IPPL_CONNCLOSED; break; default: recipl->conn_state = M_RECORD_IPPL_CONNSTATE_UNSET; break; } #ifdef DEBUG_PCRE fprintf( stderr, "%s.%d: debug: has_ipopts member will be filled!\n", __FILE__, __LINE__ ); #endif /* ip opts */ recipl->has_ipopts = strlen(list[4]) ? 1 : 0; #ifdef DEBUG_PCRE fprintf( stderr, "%s.%d: debug: remhost, remident members will be filled!\n", __FILE__, __LINE__ ); #endif if( (atsign = strchr( list[5], '@' )) == NULL ) { recipl->remhost = strdup(list[5]); recipl->remident = NULL; } else { int idl = strlen(list[5]) - strlen(atsign); recipl->remhost = strdup(atsign); recipl->remident = malloc(idl); strncpy( recipl->remident, list[5], idl-1 ); recipl->remident[idl] = '\0'; } #ifdef DEBUG_PCRE fprintf( stderr, "%s.%d: debug: parsing detailed log-stuff!\n", __FILE__, __LINE__ ); #endif if( conf->loglevel == 2 ) { int retc; /* source address */ rectrf->src = strdup(list[6]); /* source port */ recipl->src_port = strtoul( list[7], NULL, 10 ); /* destination address */ rectrf->dst = strdup(list[8]); /* destination port */ recipl->dst_port = strtoul( list[9], NULL, 10 ); /* Checking ignores, as well */ if ((retc=check_ignores(ext_conf, list[6], list[8], strtoul(list[7], NULL, 10), strtoul(list[9], NULL, 10))) != 0 ) { if (retc==1) { conf->lastignored=1; return M_RECORD_IGNORED; } return -1; } } else { int retc; rectrf->src = strdup(recipl->remhost); rectrf->dst = strdup(conf->self_host); recipl->src_port = 0; recipl->dst_port = 0; /* Checking ignores, as well */ if ((retc=check_ignores(ext_conf, recipl->remhost, conf->self_host, 0, 0)) != 0 ) { if (retc==1) { conf->lastignored=1; return M_RECORD_IGNORED; } return -1; } } #ifdef DEBUG_PCRE fprintf( stderr, "%s.%d: debug: conserving this record!\n", __FILE__, __LINE__ ); #endif /* Keep the last record .. */ conf->lastignored = 0; mrecord_reset(conf->internal_copy); #ifdef DEBUG_PCRE fprintf( stderr, "%s.%d: Debug: trying to run mrecord_copy()\n", __FILE__, __LINE__ ); #endif mrecord_copy(conf->internal_copy, record); #ifdef DEBUG_PCRE fprintf( stderr, "%s.%d: debug: conserved this record!\n", __FILE__, __LINE__ ); #endif pcre_free_substring_list(list); return M_RECORD_NO_ERROR; #undef N } int parse_udp_record_pcre( mconfig *ext_conf, mlogrec *record, buffer *b ) { #define N 20 + 1 const char **list; int ovector[3 * N], n; config_input *conf = ext_conf->plugin_conf; mlogrec_traffic *rectrf = NULL; mlogrec_traffic_ippl *recipl = NULL; if (record->ext_type != M_RECORD_TYPE_TRAFFIC) { if (record->ext_type != M_RECORD_TYPE_UNSET) { mrecord_free_ext(record); } 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_ippl(); rectrf->ext_type = M_RECORD_TYPE_TRAFFIC_IPPL; recipl = rectrf->ext; if (recipl == NULL) return M_RECORD_HARD_ERROR; if ((n = pcre_exec(conf->match_udpline, conf->match_udp_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; } } /* 5 + 4*(conf->loglevel/2) results 9 for detailed loglevel and 5 for others */ if (n != 5 + 4 * (conf->loglevel/2)) { if (ext_conf->debug_level > 3) fprintf(stderr, "%s.%d: string doesn't match: %s\n", __FILE__, __LINE__, b->ptr); return M_RECORD_IGNORED; } pcre_get_substring_list(b->ptr, ovector, n, &list); /* the meaning of the different fields */ /* * 0 - May 11 15:19:08 who UDP datagram from 212.108.197.43 (212.108.197.43:513->212.108.197.255:513) * 1 - May 15 18:02:07 * 2 - who * 3 - (empty) * 4 - 212.108.197.43 * (5-8 is only for detailed loglevel) * 5 - 212.108.197.43 * 6 - 513 * 7 - 212.108.297.255 * 8 - 513 */ switch (parse_timestamp(ext_conf, list[1], record)) { case M_RECORD_CORRUPT: conf->lastignored = 1; pcre_free_substring_list(list); return M_RECORD_CORRUPT; case M_RECORD_HARD_ERROR: pcre_free_substring_list(list); return M_RECORD_HARD_ERROR; } /* traffic datas (unknown) */ rectrf->xfer_incoming = 0; rectrf->xfer_outgoing = 0; /* protocoll type */ recipl->prototype = M_RECORD_IPPL_PROTOCOL_UDP; /* protocoll name */ recipl->protoname = strdup(list[2]); /* ip opts */ recipl->has_ipopts = strlen(list[3]) ? 1 : 0; /* remhost */ recipl->remhost = strdup(list[4]); /* remident */ recipl->remident = NULL; if( conf->loglevel == 2 ) { int retc; /* source address */ rectrf->src = strdup(list[5]); /* source port */ recipl->src_port = strtoul( list[6], NULL, 10 ); /* destination address */ rectrf->dst = strdup(list[7]); /* destination port */ recipl->dst_port = strtoul( list[8], NULL, 10 ); /* Checking ignores, as well */ if ((retc=check_ignores(ext_conf, list[5], list[7], strtoul(list[6], NULL, 10), strtoul(list[8], NULL, 10))) != 0 ) { if (retc==1) { conf->lastignored=1; return M_RECORD_IGNORED; } return -1; } } else { int retc; rectrf->src = strdup(list[5]); rectrf->dst = strdup(conf->self_host); recipl->src_port = 0; recipl->dst_port = 0; /* Checking ignores, as well */ if ((retc=check_ignores(ext_conf, list[5], list[7], strtoul(list[6], NULL, 10), strtoul(list[8], NULL, 10))) != 0 ) { if (retc==1) { conf->lastignored = 1; return M_RECORD_IGNORED; } return -1; } } /* Keep the last record .. */ conf->lastignored = 0; mrecord_reset(conf->internal_copy); #ifdef DEBUG_PCRE fprintf( stderr, "%s.%d: Debug: trying to run mrecord_copy()\n", __FILE__, __LINE__ ); #endif mrecord_copy(conf->internal_copy, record); pcre_free_substring_list(list); return M_RECORD_NO_ERROR; #undef N } int parse_icmp_record_pcre( mconfig *ext_conf, mlogrec *record, buffer *b ) { #define N 20 + 1 const char **list; int ovector[3 * N], n; config_input *conf = ext_conf->plugin_conf; int retc; mlogrec_traffic *rectrf = NULL; mlogrec_traffic_ippl *recipl = NULL; if (record->ext_type != M_RECORD_TYPE_TRAFFIC) { if (record->ext_type != M_RECORD_TYPE_UNSET) { mrecord_free_ext(record); } 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_ippl(); rectrf->ext_type = M_RECORD_TYPE_TRAFFIC_IPPL; recipl = rectrf->ext; if (recipl == NULL) return M_RECORD_HARD_ERROR; if ((n = pcre_exec(conf->match_icmpline, conf->match_icmp_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; } } /* 6 + 2*(conf->loglevel/2) results 8 for detailed loglevel and 6 for others */ if (n != 6 + 2 * (conf->loglevel/2)) { if (ext_conf->debug_level > 3) fprintf(stderr, "%s.%d: string doesn't match: %s\n", __FILE__, __LINE__, b->ptr); return M_RECORD_IGNORED; } pcre_get_substring_list(b->ptr, ovector, n, &list); /* the meaning of the different fields */ /* * 0 - May 11 15:19:08 ICMP message type echo request from 160.114.48.188 (160.114.48.188->160.114.48.30) * 1 - May 11 15:19:08 * 2 - echo request * 3 - (empty) * 4 - (empty) * 5 - 160.114.48.188 * (6-7 is only for detailed loglevel) * 6 - 160.114.48.188 * 7 - 160.114.48.30 */ switch (parse_timestamp(ext_conf, list[1], record)) { case M_RECORD_CORRUPT: conf->lastignored = 1; pcre_free_substring_list(list); return M_RECORD_CORRUPT; case M_RECORD_HARD_ERROR: pcre_free_substring_list(list); return M_RECORD_HARD_ERROR; } /* traffic datas (unknown) */ rectrf->xfer_incoming = 0; rectrf->xfer_outgoing = 0; /* protocoll type */ recipl->prototype = M_RECORD_IPPL_PROTOCOL_ICMP; if( !strlen( list[3]) ) { /* protocoll name */ recipl->protoname = strdup(list[2]); } else { /* protocoll name with subtype name */ recipl->protoname = malloc(strlen(list[2])+strlen(list[3])+1); strcpy( recipl->protoname, list[2] ); strcat( recipl->protoname, list[3] ); } /* ip opts */ recipl->has_ipopts = strlen(list[4]) ? 1 : 0; /* remhost */ recipl->remhost = strdup(list[5]); /* remident */ recipl->remident = NULL; if( conf->loglevel == 2 ) { /* source address */ rectrf->src = strdup(list[6]); /* source port */ recipl->src_port = 0; /* destination address */ rectrf->dst = strdup(list[7]); /* destination port */ recipl->dst_port = 0; } else { rectrf->src = strdup(list[5]); rectrf->dst = strdup(conf->self_host); recipl->src_port = 0; recipl->dst_port = 0; M_WP(); pcre_free_substring_list(list); return M_RECORD_IGNORED; } /* Checking ignores, as well */ if ((retc=check_ignores(ext_conf, rectrf->src, rectrf->dst, 0, 0)) != 0 ) { if (retc==1) { conf->lastignored = 1; return M_RECORD_IGNORED; } return -1; } /* Keep the last record .. */ conf->lastignored = 0; mrecord_reset(conf->internal_copy); #ifdef DEBUG_PCRE fprintf( stderr, "%s.%d: Debug: trying to run mrecord_copy()\n", __FILE__, __LINE__ ); #endif mrecord_copy(conf->internal_copy, record); pcre_free_substring_list(list); return M_RECORD_NO_ERROR; #undef N } /* ADDED 06/09/03 -- IMPON RECORDS */ int parse_ipmon_record_pcre( mconfig *ext_conf, mlogrec *record, buffer *b ) { #define N 20 + 1 const char **list; char *atsign; int ovector[3 * N], n; config_input *conf = ext_conf->plugin_conf; mlogrec_traffic *rectrf = NULL; mlogrec_traffic_ippl *recipl = NULL; if (record->ext_type != M_RECORD_TYPE_TRAFFIC) { if (record->ext_type != M_RECORD_TYPE_UNSET) { mrecord_free_ext(record); } 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_ippl(); rectrf->ext_type = M_RECORD_TYPE_TRAFFIC_IPPL; recipl = rectrf->ext; if (recipl == NULL) return M_RECORD_HARD_ERROR; #ifdef DEBUG_PCRE fprintf( stderr, "%s.%d: debug: about to call pcre_exec()!\n", __FILE__, __LINE__ ); #endif if ((n = pcre_exec(conf->match_ipmon, conf->match_ipmon_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; } } #ifdef DEBUG_PCRE fprintf( stderr, "%s.%d: debug: about to check paramlist!\n", __FILE__, __LINE__ ); #endif /* should be 19 elements in an ipmon line */ if (n != 19) { if (ext_conf->debug_level > 3) fprintf(stderr, "%s.%d: string had only %d match: %s\n", __FILE__, __LINE__, n, b->ptr); return M_RECORD_IGNORED; } #ifdef DEBUG_PCRE fprintf( stderr, "%s.%d: debug: about to get paramlist!\n", __FILE__, __LINE__ ); #endif pcre_get_substring_list(b->ptr, ovector, n, &list); /* the meaning of the different fields */ /* 0: Apr 16 17:00:30 hostname ipmon[106]: 17:00:30.181282 2x fxp0 @10:4 b 123.123.123.1,1234 -> 121.212.12.1,1111 PR tcp len 20 40 -AF IN 1: Apr 16 17:00:30 - Date without year 2: hostname - host 3: ipmon[106] - device 4: 17:00:30.181282 - start time 5: 2x fxp0 -2x + fxp# 6: @10:4 - group:rule 7: b - action 8: 123.123.123.1 - source ip 9: 1234 - source port 10: -> - arrow (ignore) 11: 121.212.12.1 - dest ip 12: 1111 - dest port 13: PR - ??? 14: tcp - protocol 15: len - "len" (ignore) 16: 20 - header length 17: 40 - total length 18: -AF IN - options, IN */ #ifdef DEBUG_PCRE fprintf( stderr, "%s.%d: debug: parse_timestamp() will be called!\n", __FILE__, __LINE__ ); #endif switch (parse_timestamp(ext_conf, list[1], record)) { case M_RECORD_CORRUPT: pcre_free_substring_list(list); return M_RECORD_CORRUPT; case M_RECORD_HARD_ERROR: pcre_free_substring_list(list); return M_RECORD_HARD_ERROR; } /* traffic datas (unknown) */ rectrf->xfer_incoming = 0; rectrf->xfer_outgoing = 0; /* protocoll type */ recipl->prototype = M_RECORD_IPPL_PROTOCOL_TCP; #ifdef DEBUG_PCRE fprintf( stderr, "%s.%d: debug: protoname member will be filled!\n", __FILE__, __LINE__ ); #endif /* protocoll name */ recipl->protoname = strdup(list[14]); #ifdef DEBUG_PCRE fprintf( stderr, "%s.%d: debug: conn_state member will be filled!\n", __FILE__, __LINE__ ); #endif /* connection state (ie: IPMON 'action') */ switch( *list[7] ) { case 'p': recipl->conn_state = M_RECORD_IPPL_PASSED; break; case 'b': recipl->conn_state = M_RECORD_IPPL_BLOCKED; break; case 'S': recipl->conn_state = M_RECORD_IPPL_SHORT_PACKET; break; case 'n': recipl->conn_state = M_RECORD_IPPL_NO_MATCH; break; case 'L': recipl->conn_state = M_RECORD_IPPL_LOG_RULE; break; case 'P': recipl->conn_state = M_RECORD_IPPL_GLOBAL_LOGGING; break; case 'B': recipl->conn_state = M_RECORD_IPPL_GLOBAL_LOGGING; break; default: recipl->conn_state = M_RECORD_IPPL_NO_MATCH; break; } #ifdef DEBUG_PCRE fprintf( stderr, "%s.%d: debug: remhost, remident members will be filled!\n", __FILE__, __LINE__ ); #endif if( (atsign = strchr( list[2], '@' )) == NULL ) { recipl->remhost = strdup(list[2]); recipl->remident = NULL; } else { int idl = strlen(list[2]) - strlen(atsign); recipl->remhost = strdup(atsign); recipl->remident = malloc(idl); strncpy( recipl->remident, list[2], idl-1 ); recipl->remident[idl] = '\0'; } #ifdef DEBUG_PCRE fprintf( stderr, "%s.%d: debug: parsing detailed log-stuff!\n", __FILE__, __LINE__ ); #endif if( conf->loglevel == 2 ) { /* source address */ rectrf->src = strdup(list[8]); /* source port */ recipl->src_port = strtoul( list[9], NULL, 10 ); /* destination address */ rectrf->dst = strdup(list[11]); /* destination port */ recipl->dst_port = strtoul( list[12], NULL, 10 ); } else { rectrf->src = NULL; rectrf->dst = NULL; recipl->src_port = 0; recipl->dst_port = 0; M_WP(); pcre_free_substring_list(list); return M_RECORD_IGNORED; } #ifdef DEBUG_PCRE fprintf( stderr, "%s.%d: debug: conserving this record!\n", __FILE__, __LINE__ ); #endif /* Keep the last record .. */ mrecord_reset(conf->internal_copy); #ifdef DEBUG_PCRE fprintf( stderr, "%s.%d: Debug: trying to run mrecord_copy()\n", __FILE__, __LINE__ ); #endif mrecord_copy(conf->internal_copy, record); #ifdef DEBUG_PCRE fprintf( stderr, "%s.%d: debug: conserved this record!\n", __FILE__, __LINE__ ); #endif pcre_free_substring_list(list); return M_RECORD_NO_ERROR; #undef N }// END IPMON RECORDS int mplugins_input_ippl_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; if (conf->repeatnum > 0) { mrecord_reset(record ); #ifdef DEBUG_PCRE fprintf( stderr, "%s.%d: Debug: trying to run mrecord_copy()\n", __FILE__, __LINE__ ); #endif mrecord_copy(record, conf->internal_copy); conf->repeatnum--; return M_RECORD_NO_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; }