prelude-lml/master: Ability to provides static IDMEF template from defined log format
[email protected] Thu, 16 Jul 2009 15:42:29 +0200 (CEST)
| Newsgroups | gmane.comp.security.ids.prelude.cvs |
|---|---|
| Message-ID | <[email protected]> |
commit 866f11f23991556cad40926d3aa2c84219ed39c0 Author: Yoann Vandoorselaere <[email protected]> Date: Wed Jul 15 16:50:14 2009 +0200 Ability to provides static IDMEF template from defined log format Implement the 'idmef-alter' and 'idmef-alter-force' option, that can be used to put specific values in generated IDMEF events from a given log format. Example: idmef-alter = alert.analyzer(-1).node.location = My Location 'idmef-alter' will not overwrite an IDMEF path that is already set. Use 'idmef-alter-force' if this is what you intend to do. ======================================== prelude-lml.conf.in | 50 ++++++++++++++++---------- src/include/log-entry.h | 2 + src/include/log-source.h | 4 ++ src/lml-alert.c | 3 ++ src/lml-options.c | 20 ++++++++++ src/log-entry.c | 12 ++++++- src/log-source.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 158 insertions(+), 20 deletions(-) ======================================== diff --git a/prelude-lml.conf.in b/prelude-lml.conf.in index 7c1d0a5..b904f77 100644 --- a/prelude-lml.conf.in +++ b/prelude-lml.conf.in @@ -9,9 +9,9 @@ include = @LIBPRELUDE_CONFIG_PREFIX@/default/idmef-client.conf # if value is "127.0.0.1", the connection will occur throught # an UNIX socket. # -# This entry is disabled. The default is to use the entry -# located in the Prelude system wide clients.conf. You may -# overwrite the default address for this sensor by uncommenting +# This entry is disabled. The default is to use the entry +# located in the Prelude system wide clients.conf. You may +# overwrite the default address for this sensor by uncommenting # this entry. # # [prelude] @@ -21,8 +21,9 @@ include = @LIBPRELUDE_CONFIG_PREFIX@/default/idmef-client.conf # # Files to monitor # -# You should define the log message prefix-regex and time-format within a -# [format] section. If not specified, the default syslog format will be used. +# You should define the log message prefix-regex and time-format within +# a [format] section. If not specified, the default syslog format will +# be used. # # The prefix-regex should contain PCRE named subpatterns to pick out the # information available in your syslog's prefix. @@ -34,26 +35,37 @@ include = @LIBPRELUDE_CONFIG_PREFIX@/default/idmef-client.conf # - timestamp # # Please see pcrepattern(3) manpage for help writing the prefix-regex -# In order to set the time-format, please have a look at the strptime(3) manpage. +# In order to set the time-format, please have a look at the strptime(3) +# manpage. # # Example configuration for syslog output: # # Each [format] section might have several file entry. # Each [format] section might have several udp-server entry. # -# The same file or udp-server entry might be duplicated accross -# differents formats. +# If a file or udp-server entry might is listed accross differents +# formats, then the first matching format for a given log entry will be +# used. # -# Additionally, you can specify a pattern in a file entry. LML will then searches -# for all the pathnames matching pattern according to the rules used by the shell -# (see glob(7)). +# Additionally, you can specify a pattern in a file entry. LML will then +# searches for all the pathnames matching pattern according to the rules +# used by the shell (see glob(7)). # # Example: file = /var/log/*/*.log - +# +# +# Within each format, you might use the 'idmef-alter' option to modify +# generated events: +# +# Example: idmef-alter = alert.analyzer(-1).node.location = MyLocation; +# +# Note that 'idmef-alter' will never overwrite an IDMEF path that is +# already set. Use 'idmef-alter-force' if this is what you intend to do. +# [format=syslog] -time-format = "%b %d %H:%M:%S" +time-format = "%b %d %H:%M:%S" prefix-regex = "^(?P<timestamp>.{15}) (?P<hostname>\S+) (?:(?P<process>\S+?)(?:\[(?P<pid>[0-9]+)\])?: )?" file = /var/log/messages # udp-server = 0.0.0.0 @@ -64,7 +76,7 @@ file = /var/log/messages # [format=metalog] prefix-regex = "^(?P<timestamp>.{15}) \[(?P<process>\S+)\] " -time-format = "%b %d %H:%M:%S" +time-format = "%b %d %H:%M:%S" file = /var/log/everything/current # udp-server = 0.0.0.0 @@ -97,7 +109,7 @@ file = /var/log/apache2/error_log # # Specifies the maximum difference, in seconds, between -# the interval of two logfiles' rotation. If this difference +# the interval of two logfiles' rotation. If this difference # is reached, a high severity alert will be emited # #max-rotation-size-offset = 1024 @@ -105,11 +117,11 @@ file = /var/log/apache2/error_log # -# Maximum number of warning a given source should emit in case it can not -# parse log entry with the provided prefix_regex and time_format. +# Maximum number of warning a given source should emit in case it can +# not parse log entry with the provided prefix_regex and time_format. # # -1 == unlimited number of warning -# 0 == no warning at all +# 0 == no warning at all # X == print at most X warnings. # # warning-limit = -1 @@ -128,7 +140,7 @@ ruleset=@configdir@/ruleset/pcre.rules # # This plugin issue an alert for each packet. # Carefull to the loging activity it generate. -# +# # Triger Report to the console. # stderr diff --git a/src/include/log-entry.h b/src/include/log-entry.h index d849d76..9bdaa1e 100644 --- a/src/include/log-entry.h +++ b/src/include/log-entry.h @@ -33,4 +33,6 @@ int lml_log_entry_set_log(lml_log_entry_t *lc, lml_log_source_t *ls, const char void lml_log_entry_destroy(lml_log_entry_t *lc); +const lml_log_format_t *lml_log_entry_get_format(const lml_log_entry_t *log); + #endif /* _LOG_ENTRY_H */ diff --git a/src/include/log-source.h b/src/include/log-source.h index 624becf..4677abb 100644 --- a/src/include/log-source.h +++ b/src/include/log-source.h @@ -49,6 +49,10 @@ int lml_log_format_set_ts_fmt(lml_log_format_t *lf, const char *fmt); const char *lml_log_format_get_ts_fmt(const lml_log_format_t *ls); +int lml_log_format_set_idmef(lml_log_format_t *format, const char *idmef_s, prelude_bool_t force); + +void lml_log_format_apply_idmef(const lml_log_format_t *format, idmef_message_t *idmef); + /* * */ diff --git a/src/lml-alert.c b/src/lml-alert.c index ed5fbdc..02ea661 100644 --- a/src/lml-alert.c +++ b/src/lml-alert.c @@ -319,6 +319,9 @@ int lml_alert_prepare(idmef_message_t *message, const lml_log_source_t *ls, cons return -1; } + if ( lml_log_entry_get_format(log) ) + lml_log_format_apply_idmef(lml_log_entry_get_format(log), message); + return 0; } diff --git a/src/lml-options.c b/src/lml-options.c index dc6ab2e..d2992bf 100644 --- a/src/lml-options.c +++ b/src/lml-options.c @@ -486,6 +486,18 @@ static int set_format(prelude_option_t *opt, const char *arg, prelude_string_t * } +static int set_idmef_alter_force(prelude_option_t *opt, const char *arg, prelude_string_t *err, void *context) +{ + return lml_log_format_set_idmef(context, arg, TRUE); +} + + +static int set_idmef_alter(prelude_option_t *opt, const char *arg, prelude_string_t *err, void *context) +{ + return lml_log_format_set_idmef(context, arg, FALSE); +} + + #if !((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__) static int set_user(prelude_option_t *opt, const char *optarg, prelude_string_t *err, void *context) @@ -658,6 +670,14 @@ int lml_options_init(prelude_option_t *ropt, int argc, char **argv) "address:port pair to listen to syslog to UDP messages (default port 514)", PRELUDE_OPTION_ARGUMENT_OPTIONAL, set_udp_server, NULL); + prelude_option_add(opt, NULL, PRELUDE_OPTION_TYPE_CLI|PRELUDE_OPTION_TYPE_CFG, + 0, "idmef-alter", "Assign specific IDMEF path/value to matching log entry", + PRELUDE_OPTION_ARGUMENT_REQUIRED, set_idmef_alter, NULL); + + prelude_option_add(opt, NULL, PRELUDE_OPTION_TYPE_CLI|PRELUDE_OPTION_TYPE_CFG, + 0, "idmef-alter-force", "Assign specific IDMEF path/value to matching log entry, even if path is already used", + PRELUDE_OPTION_ARGUMENT_REQUIRED, set_idmef_alter_force, NULL); + ret = prelude_option_read(ropt, &config_file, &argc, argv, &err, NULL); if ( ret < 0 ) { if ( prelude_error_get_code(ret) == PRELUDE_ERROR_EOF ) diff --git a/src/log-entry.c b/src/log-entry.c index c16d7a7..e37e056 100644 --- a/src/log-entry.c +++ b/src/log-entry.c @@ -58,6 +58,8 @@ struct lml_log_entry { char *target_hostname; char *target_process; char *target_process_pid; + + lml_log_format_t *format; }; @@ -281,8 +283,10 @@ int lml_log_entry_set_log(lml_log_entry_t *log_entry, lml_log_source_t *ls, cons fc = prelude_linked_object_get_object(tmp); ret = parse_prefix(lml_log_format_container_get_format(fc), ls, log_entry); - if ( ret == 0 ) + if ( ret == 0 ) { + log_entry->format = lml_log_format_container_get_format(fc); break; + } lml_log_entry_destroy_substring(log_entry); } @@ -311,3 +315,9 @@ void lml_log_entry_destroy(lml_log_entry_t *log_entry) free(log_entry); } + + +const lml_log_format_t *lml_log_entry_get_format(const lml_log_entry_t *log_entry) +{ + return log_entry->format; +} diff --git a/src/log-source.c b/src/log-source.c index d210254..000b20c 100644 --- a/src/log-source.c +++ b/src/log-source.c @@ -54,12 +54,22 @@ +typedef struct { + prelude_list_t list; + prelude_bool_t force; + idmef_path_t *path; + idmef_value_t *value; +} lml_format_idmef_t; + + struct lml_log_format { int refcount; char *name; char *ts_fmt; pcre *prefix_regex; pcre_extra *prefix_regex_extra; + + prelude_list_t idmef_list; }; @@ -140,6 +150,7 @@ lml_log_format_t *lml_log_format_new(const char *name) return NULL; } + prelude_list_init(&new->idmef_list); return new; } @@ -195,6 +206,81 @@ int lml_log_format_set_ts_fmt(lml_log_format_t *ls, const char *fmt) + +int lml_log_format_set_idmef(lml_log_format_t *format, const char *idmef_s, prelude_bool_t force) +{ + int ret; + size_t len; + char *idmef, tmp; + lml_format_idmef_t *entry; + + len = strcspn(idmef_s, " ="); + if ( len == 0 ) + return -1; + + idmef = strdup(idmef_s); + if ( ! idmef ) + return -1; + + entry = malloc(sizeof(*entry)); + if ( ! entry ) { + free(idmef); + return -1; + } + + entry->force = force; + + tmp = idmef[len]; + idmef[len] = 0; + + ret = idmef_path_new_fast(&entry->path, idmef); + if ( ret < 0 ) { + free(idmef); + free(entry); + return ret; + } + + idmef[len] = tmp; + + ret = idmef_value_new_from_path(&entry->value, entry->path, idmef + len + strspn(idmef + len, " =")); + if ( ret < 0 ) { + free(idmef); + idmef_path_destroy(entry->path); + free(entry); + return ret; + } + + free(idmef); + prelude_list_add_tail(&format->idmef_list, &entry->list); + + return 0; +} + + + +void lml_log_format_apply_idmef(const lml_log_format_t *format, idmef_message_t *idmef) +{ + int ret; + prelude_list_t *tmp; + idmef_value_t *value; + lml_format_idmef_t *entry; + + prelude_list_for_each(&format->idmef_list, tmp) { + entry = prelude_list_entry(tmp, lml_format_idmef_t, list); + + if ( ! entry->force ) { + ret = idmef_path_get(entry->path, idmef, &value); + if ( ret > 0 ) { + idmef_value_destroy(value); + continue; + } + } + + idmef_path_set(entry->path, idmef, entry->value); + } +} + + const char *lml_log_format_get_ts_fmt(const lml_log_format_t *source) { return source->ts_fmt; @@ -387,3 +473,4 @@ prelude_list_t *lml_log_source_get_format_list(lml_log_source_t *source) { return &source->format_list; } + _______________________________________________ Prelude-cvslog site list [email protected] http://lists.prelude-ids.org/mailman/listinfo/prelude-cvslog