# HG changeset patch # User Tero Marttila # Date 1239568035 -10800 # Node ID a716c621cb9002fc46c7fee663aa0b5ce89459a6 # Parent c607c357c48604c34a0fbf507667b853488cc885 implement blackhole filters for logwatch, and stop applying filters after the first hit diff -r c607c357c486 -r a716c621cb90 config.lua --- a/config.lua Sun Apr 12 22:19:54 2009 +0300 +++ b/config.lua Sun Apr 12 23:27:15 2009 +0300 @@ -4,28 +4,57 @@ -- -- match all lines and output them as-is -local function logwatch_filter_all () - return { pat=nil, fmt=nil } +local function logwatch_filter_all (name) + return { name=name } end -- match using a regex pattern, but output the full line -local function logwatch_filter_raw (pat) - return { pat=pat, fmt=nil } +local function logwatch_filter_raw (name, pat) + return { name=name, pat=pat } end -- match using a regexp pattern, and output a formatted line -local function logwatch_filter (pat, fmt) - return { pat=pat, fmt=fmt } +local function logwatch_filter (name, pat, fmt) + return { name=name, pat=pat, fmt=fmt } end +-- match using a regexp pattern, and do *not* output +local function logwatch_filter_blackhole (name, pat) + return { name=name, pat=pat, channel_is_null=true } +end + +logwatch_timestamp_pat = "\\w{3} [0-9 ]\\d \\d{2}:\\d{2}:\\d{2}" + -- match auth.log sudo entries -local function logwatch_filter_sudo () - return logwatch_filter( - "(?P\\S+)\\s+sudo:\\s*(?P\\S+) : TTY=(?P\\S+) ; PWD=(?P.+?) ; USER=(?P\\S+) ; COMMAND=(?P.*)", +local function logwatch_filter_sudo (name) + return logwatch_filter(name, + "^" .. logwatch_timestamp_pat .. " (?P\\S+)\\s+sudo:\\s*(?P\\S+) : TTY=(?P\\S+) ; PWD=(?P.+?) ; USER=(?P\\S+) ; COMMAND=(?P.*)$", "{username}:{tty} - {target_user}@{hostname}:{pwd} - {command:r}" ) end +-- filter out the prefixed timestamp from lines +local function logwatch_filter_strip_timestamp (name) + return logwatch_filter(name, + "^" .. logwatch_timestamp_pat .. " (?P.+)$", + "{line}" + ) +end + +-- filter out auth.log cron messages +local function logwatch_filter_no_cron (name) + return logwatch_filter_blackhole(name, + "^" .. logwatch_timestamp_pat .. " \\S+\\s+(CRON|su)\\[\\d+\\]: pam_unix\\(\\w+:\\w+\\): session (opened|closed) for user \\w+( by \\(uid=\\d+\\))?$" + ) +end + +-- filter out auth.log 'su for nobody by root' messages +local function logwatch_filter_no_su_nobody (name) + return logwatch_filter_blackhole(name, + "^" .. logwatch_timestamp_pat .. " \\S+\\s+su\\[\\d+\\]: (Successful su for nobody by root|\\+ \\?\\?\\? root:nobody)$" + ) +end + -- -- Procedural config -- @@ -71,8 +100,14 @@ module:conf("source_fifo", fifo_path) source_name = fifo_path - for filter_name, filter in pairs(settings.filters) do - module:conf("filter", filter_name, source_name, filter.pat, filter.fmt, settings.channel) + for i, filter in ipairs(settings.filters) do + if filter.channel_is_null then + channel = nil + else + channel = settings.channel + end + + module:conf("filter", filter.name, source_name, filter.pat, filter.fmt, channel) end end end @@ -116,11 +151,13 @@ channel = "PVLNet/#test", filters = { - ["test.foo"] = logwatch_filter_raw("foo"), - ["test.sudo"] = logwatch_filter_sudo(), + logwatch_filter_raw ("test.foo", "foo" ), + logwatch_filter_sudo ("test.sudo" ), + logwatch_filter_no_cron ("test.no_cron" ), + logwatch_filter_no_su_nobody ("test.no_cron_su" ), + logwatch_filter_strip_timestamp ("test.all" ) } }, }, } - diff -r c607c357c486 -r a716c621cb90 src/error.c --- a/src/error.c Sun Apr 12 22:19:54 2009 +0300 +++ b/src/error.c Sun Apr 12 23:27:15 2009 +0300 @@ -86,6 +86,10 @@ { ERR_LUA_ERR, "lua: error handling error", ERR_EXTRA_STR }, { ERR_LUA_FILE, "lua: error loading file", ERR_EXTRA_STR }, { _ERR_INVALID, NULL, 0 } +}, _pcre_error_desc[] = { + { ERR_PCRE_COMPILE, "pcre_compile", ERR_EXTRA_STR }, + { ERR_PCRE_EXEC, "pcre_exec", ERR_EXTRA_STR }, + { _ERR_INVALID, NULL, 0 } }; /** @@ -99,6 +103,7 @@ _config_error_desc, _module_error_desc, _lua_error_desc, + _pcre_error_desc, NULL }; diff -r c607c357c486 -r a716c621cb90 src/irc_chan.c --- a/src/irc_chan.c Sun Apr 12 22:19:54 2009 +0300 +++ b/src/irc_chan.c Sun Apr 12 23:27:15 2009 +0300 @@ -8,7 +8,7 @@ const char* irc_chan_name (struct irc_chan *chan) { - return chan->info.channel; + return chan ? chan->info.channel : "NULL"; } /** diff -r c607c357c486 -r a716c621cb90 src/irc_net.c --- a/src/irc_net.c Sun Apr 12 22:19:54 2009 +0300 +++ b/src/irc_net.c Sun Apr 12 23:27:15 2009 +0300 @@ -7,7 +7,7 @@ const char* irc_net_name (struct irc_net *net) { - return net->info.network; + return net ? net->info.network : NULL; } /** diff -r c607c357c486 -r a716c621cb90 src/module.c --- a/src/module.c Sun Apr 12 22:19:54 2009 +0300 +++ b/src/module.c Sun Apr 12 23:27:15 2009 +0300 @@ -102,7 +102,7 @@ const char* module_name (struct module *module) { - return module->info.name; + return module ? module->info.name : NULL; } /** diff -r c607c357c486 -r a716c621cb90 src/modules/logwatch.c --- a/src/modules/logwatch.c Sun Apr 12 22:19:54 2009 +0300 +++ b/src/modules/logwatch.c Sun Apr 12 23:27:15 2009 +0300 @@ -50,11 +50,17 @@ { const struct logwatch_filter *filter; struct error_info err; + int ret; // apply each filter TAILQ_FOREACH(filter, &ctx->filters, logwatch_filters) { - if (logwatch_filter_apply(filter, source, line, &err)) + // apply it + if ((ret = logwatch_filter_apply(filter, source, line, &err)) < 0) log_warn("logwatch_filter_apply(%s, %s, %s): %s", filter->name, source->name, line, error_msg(&err)); + + // blackhole? + if (ret > 0) + break; } } @@ -101,7 +107,7 @@ struct logwatch_filter *filter; const struct logwatch_source *source = NULL; - struct logwatch_chan *chan; + struct logwatch_chan *chan = NULL; const char *name, *source_name, *pattern, *format; struct irc_chan *irc_chan; @@ -123,7 +129,7 @@ RETURN_SET_ERROR_STR(err, ERR_MODULE_CONF, "unknown logwatch_source name"); // lookup channel - if ((chan = logwatch_get_chan(ctx, irc_chan)) == NULL) + if (irc_chan && (chan = logwatch_get_chan(ctx, irc_chan)) == NULL) RETURN_SET_ERROR_STR(err, ERR_MODULE_CONF, "logwatch_get_chan failed"); log_info("add filter: name=%s, source=%s, pattern=%s, format=%s, chan=%s", @@ -155,11 +161,11 @@ "using the given format expression (or pass through directly), and finally send the output to the given channel. " "If a filter with the same name already exists, it will be replaced.", - CONFIG_PARAM( "name", CONFIG_STRING, "filter name", false ), - CONFIG_PARAM( "source", CONFIG_STRING, "optional logwatch_source to use", true ), - CONFIG_PARAM( "pattern", CONFIG_STRING, "optional regular expression pattern", true ), - CONFIG_PARAM( "format", CONFIG_STRING, "optional output format", true ), - CONFIG_PARAM( "chan", CONFIG_IRC_CHAN, "channel to send output to", false ) + CONFIG_PARAM( "name", CONFIG_STRING, "filter name", false ), + CONFIG_PARAM( "source", CONFIG_STRING, "optional logwatch_source to use", true ), + CONFIG_PARAM( "pattern", CONFIG_STRING, "optional regular expression pattern", true ), + CONFIG_PARAM( "format", CONFIG_STRING, "optional output format", true ), + CONFIG_PARAM( "chan", CONFIG_IRC_CHAN, "channel to send output to, or NULL to blackhole", true) ) ); diff -r c607c357c486 -r a716c621cb90 src/modules/logwatch.h --- a/src/modules/logwatch.h Sun Apr 12 22:19:54 2009 +0300 +++ b/src/modules/logwatch.h Sun Apr 12 23:27:15 2009 +0300 @@ -194,9 +194,11 @@ void logwatch_filter_destroy (struct logwatch_filter *filter); /** - * Pass the given line (from the given source) through the given filter + * Pass the given line (from the given source) through the given filter. + * + * Returns 0 if the next filter should be tried, >0 if no more filters should be processed, and -err_t on error. */ -err_t logwatch_filter_apply (const struct logwatch_filter *filter, const struct logwatch_source *source, const char *line, struct error_info *err); +int logwatch_filter_apply (const struct logwatch_filter *filter, const struct logwatch_source *source, const char *line, struct error_info *err); /** * Remove any filters registered with the given source diff -r c607c357c486 -r a716c621cb90 src/modules/logwatch_filter.c --- a/src/modules/logwatch_filter.c Sun Apr 12 22:19:54 2009 +0300 +++ b/src/modules/logwatch_filter.c Sun Apr 12 23:27:15 2009 +0300 @@ -69,16 +69,17 @@ void logwatch_filter_destroy (struct logwatch_filter *filter) { - // remove it if it's registered if (filter->ctx) + // unreigster TAILQ_REMOVE(&filter->ctx->filters, filter, logwatch_filters); // this if is probably not needed if (filter->regexp) pcre_free(filter->regexp); - // release the logwatch_chan ref - logwatch_chan_put(filter->chan); + if (filter->chan) + // release the logwatch_chan ref + logwatch_chan_put(filter->chan); // free misc free(filter->format); @@ -151,7 +152,7 @@ // length of output line prefix #define LOGWATCH_FILTER_OUT_PREFIX_LEN 16 -err_t logwatch_filter_apply (const struct logwatch_filter *filter, const struct logwatch_source *source, const char *line, struct error_info *err) +int logwatch_filter_apply (const struct logwatch_filter *filter, const struct logwatch_source *source, const char *line, struct error_info *err) { int ovec[LOGWATCH_FILTER_OVEC_ITEMS], ret; char buf[LOGWATCH_FILTER_OUT_MAX + 1], *buf_ptr = buf; @@ -161,23 +162,24 @@ // discard based on source? if (filter->source && source != filter->source) - return SUCCESS; + return 0; // match against the regexp? if (filter->regexp && (ret = pcre_exec(filter->regexp, NULL, line, strlen(line), 0, 0, ovec, LOGWATCH_FILTER_OVEC_ITEMS)) <= 0) { if (ret == PCRE_ERROR_NOMATCH) // no match, ignore - return SUCCESS; - - else if (ret == 0) - // too many match groups - return SET_ERROR(err, -1); + return 0; else // misc. error - RETURN_SET_ERROR_EXTRA(err, ERR_PCRE_EXEC, ret); + // XXX: might be 0 for too many groups + JUMP_SET_ERROR_EXTRA(err, ERR_PCRE_EXEC, ret); } + // blackhole? + if (!filter->chan) + return 1; + // format? if (filter->format) { // setup the ctx @@ -206,10 +208,10 @@ if ((ERROR_CODE(err) = logwatch_chan_msg(filter->chan, "[%s] %s", filter->name, buf))) goto error; - // ok - return SUCCESS; + // ok, stop here + return 1; error: - return ERROR_CODE(err); + return -ERROR_CODE(err); }