1 /*
2 * Copyright (c) 2002-2013 Balabit
3 * Copyright (c) 1998-2013 Balázs Scheidler
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 * As an additional exemption you are allowed to compile & link against the
20 * OpenSSL libraries as published by the OpenSSL project. See the file
21 * COPYING for details.
22 *
23 */
24
25 #include "filter-re.h"
26 #include "str-utils.h"
27 #include "messages.h"
28 #include "scratch-buffers.h"
29 #include <string.h>
30
31 typedef struct _FilterRE
32 {
33 FilterExprNode super;
34 NVHandle value_handle;
35 LogMatcherOptions matcher_options;
36 LogMatcher *matcher;
37 } FilterRE;
38
39
40 static gboolean
filter_re_eval_string(FilterExprNode * s,LogMessage * msg,gint value_handle,const gchar * str,gssize str_len)41 filter_re_eval_string(FilterExprNode *s, LogMessage *msg, gint value_handle, const gchar *str, gssize str_len)
42 {
43 FilterRE *self = (FilterRE *) s;
44 gboolean result;
45
46 if (str_len < 0)
47 str_len = strlen(str);
48 msg_trace("match() evaluation started",
49 evt_tag_str("input", str),
50 evt_tag_str("pattern", self->matcher->pattern),
51 evt_tag_str("value", log_msg_get_value_name(value_handle, NULL)),
52 evt_tag_printf("msg", "%p", msg));
53 result = log_matcher_match(self->matcher, msg, value_handle, str, str_len);
54 return result ^ s->comp;
55 }
56
57 static gboolean
filter_re_eval(FilterExprNode * s,LogMessage ** msgs,gint num_msg,LogTemplateEvalOptions * options)58 filter_re_eval(FilterExprNode *s, LogMessage **msgs, gint num_msg, LogTemplateEvalOptions *options)
59 {
60 FilterRE *self = (FilterRE *) s;
61 NVTable *payload;
62 const gchar *value;
63 LogMessage *msg = msgs[num_msg - 1];
64 gssize len = 0;
65 gboolean rc;
66
67 payload = nv_table_ref(msg->payload);
68 value = log_msg_get_value(msg, self->value_handle, &len);
69 APPEND_ZERO(value, value, len);
70
71 rc = filter_re_eval_string(s, msg, self->value_handle, value, len);
72
73 nv_table_unref(payload);
74 return rc;
75 }
76
77 static void
filter_re_free(FilterExprNode * s)78 filter_re_free(FilterExprNode *s)
79 {
80 FilterRE *self = (FilterRE *) s;
81
82 log_matcher_unref(self->matcher);
83 log_matcher_options_destroy(&self->matcher_options);
84 }
85
86 static gboolean
filter_re_init(FilterExprNode * s,GlobalConfig * cfg)87 filter_re_init(FilterExprNode *s, GlobalConfig *cfg)
88 {
89 FilterRE *self = (FilterRE *) s;
90
91 if (self->matcher_options.flags & LMF_STORE_MATCHES)
92 self->super.modify = TRUE;
93
94 return TRUE;
95 }
96
97 LogMatcherOptions *
filter_re_get_matcher_options(FilterExprNode * s)98 filter_re_get_matcher_options(FilterExprNode *s)
99 {
100 FilterRE *self = (FilterRE *) s;
101
102 return &self->matcher_options;
103 }
104
105 gboolean
filter_re_compile_pattern(FilterExprNode * s,const gchar * re,GError ** error)106 filter_re_compile_pattern(FilterExprNode *s, const gchar *re, GError **error)
107 {
108 FilterRE *self = (FilterRE *) s;
109
110 log_matcher_options_init(&self->matcher_options);
111 self->matcher = log_matcher_new(&self->matcher_options);
112 return log_matcher_compile(self->matcher, re, error);
113 }
114
115 static void
filter_re_init_instance(FilterRE * self,NVHandle value_handle)116 filter_re_init_instance(FilterRE *self, NVHandle value_handle)
117 {
118 filter_expr_node_init_instance(&self->super);
119 self->value_handle = value_handle;
120 self->super.init = filter_re_init;
121 self->super.eval = filter_re_eval;
122 self->super.free_fn = filter_re_free;
123 self->super.type = "regexp";
124 log_matcher_options_defaults(&self->matcher_options);
125 self->matcher_options.flags |= LMF_MATCH_ONLY;
126 }
127
128 FilterExprNode *
filter_re_new(NVHandle value_handle)129 filter_re_new(NVHandle value_handle)
130 {
131 FilterRE *self = g_new0(FilterRE, 1);
132
133 filter_re_init_instance(self, value_handle);
134 return &self->super;
135 }
136
137 FilterExprNode *
filter_source_new(void)138 filter_source_new(void)
139 {
140 FilterRE *self = (FilterRE *) filter_re_new(LM_V_SOURCE);
141
142 if (!log_matcher_options_set_type(&self->matcher_options, "string"))
143 {
144 /* this can only happen if the plain text string matcher will cease to exist */
145 g_assert_not_reached();
146 }
147 return &self->super;
148 }
149
150 typedef struct _FilterMatch
151 {
152 FilterRE super;
153 LogTemplate *template;
154 } FilterMatch;
155
156 gboolean
filter_match_is_usage_obsolete(FilterExprNode * s)157 filter_match_is_usage_obsolete(FilterExprNode *s)
158 {
159 FilterMatch *self = (FilterMatch *) s;
160
161 return self->super.value_handle == 0 && self->template == NULL;
162 }
163
164 void
filter_match_set_value_handle(FilterExprNode * s,NVHandle value_handle)165 filter_match_set_value_handle(FilterExprNode *s, NVHandle value_handle)
166 {
167 FilterMatch *self = (FilterMatch *) s;
168
169 self->super.value_handle = value_handle;
170 }
171
172 void
filter_match_set_template_ref(FilterExprNode * s,LogTemplate * template)173 filter_match_set_template_ref(FilterExprNode *s, LogTemplate *template)
174 {
175 FilterMatch *self = (FilterMatch *) s;
176
177 log_template_unref(self->template);
178 self->template = template;
179 }
180
181 static gboolean
filter_match_eval_against_program_pid_msg(FilterExprNode * s,LogMessage ** msgs,gint num_msg,LogTemplateEvalOptions * options)182 filter_match_eval_against_program_pid_msg(FilterExprNode *s, LogMessage **msgs, gint num_msg,
183 LogTemplateEvalOptions *options)
184 {
185 FilterMatch *self = (FilterMatch *) s;
186
187 const gchar *pid;
188 gssize pid_len;
189 gchar *str;
190 gboolean res;
191 LogMessage *msg = msgs[num_msg - 1];
192
193 pid = log_msg_get_value(msg, LM_V_PID, &pid_len);
194
195 /* compatibility mode */
196 str = g_strdup_printf("%s%s%s%s: %s",
197 log_msg_get_value(msg, LM_V_PROGRAM, NULL),
198 pid_len > 0 ? "[" : "",
199 pid,
200 pid_len > 0 ? "]" : "",
201 log_msg_get_value(msg, LM_V_MESSAGE, NULL));
202 res = filter_re_eval_string(&self->super.super, msg, LM_V_NONE, str, -1);
203 g_free(str);
204 return res;
205 }
206
207 static gboolean
filter_match_eval_against_template(FilterExprNode * s,LogMessage ** msgs,gint num_msg,LogTemplateEvalOptions * options)208 filter_match_eval_against_template(FilterExprNode *s, LogMessage **msgs, gint num_msg, LogTemplateEvalOptions *options)
209 {
210 FilterMatch *self = (FilterMatch *) s;
211
212 LogMessage *msg = msgs[num_msg - 1];
213 GString *buffer;
214
215 buffer = scratch_buffers_alloc();
216
217 log_template_format(self->template, msg, options, buffer);
218 return filter_re_eval_string(&self->super.super, msg, LM_V_NONE, buffer->str, buffer->len);
219 }
220
221 static gboolean
filter_match_eval_against_trivial_template(FilterExprNode * s,LogMessage ** msgs,gint num_msg,LogTemplateEvalOptions * options)222 filter_match_eval_against_trivial_template(FilterExprNode *s, LogMessage **msgs, gint num_msg,
223 LogTemplateEvalOptions *options)
224 {
225 FilterMatch *self = (FilterMatch *) s;
226
227 LogMessage *msg = msgs[num_msg - 1];
228 NVTable *payload;
229 const gchar *value;
230 gssize len = 0;
231 gboolean rc;
232
233 payload = nv_table_ref(msg->payload);
234 value = log_template_get_trivial_value(self->template, msg, &len);
235 APPEND_ZERO(value, value, len);
236
237 rc = filter_re_eval_string(&self->super.super, msg, LM_V_NONE, value, len);
238
239 nv_table_unref(payload);
240 return rc;
241 }
242
243 static void
filter_match_determine_eval_function(FilterMatch * self)244 filter_match_determine_eval_function(FilterMatch *self)
245 {
246 if (self->super.value_handle)
247 self->super.super.eval = filter_re_eval;
248 else if (self->template && log_template_is_trivial(self->template))
249 self->super.super.eval = filter_match_eval_against_trivial_template;
250 else if (self->template)
251 self->super.super.eval = filter_match_eval_against_template;
252 else
253 self->super.super.eval = filter_match_eval_against_program_pid_msg;
254 }
255
256 static gboolean
filter_match_init(FilterExprNode * s,GlobalConfig * cfg)257 filter_match_init(FilterExprNode *s, GlobalConfig *cfg)
258 {
259 FilterMatch *self = (FilterMatch *) s;
260
261 if (!filter_re_init(s, cfg))
262 return FALSE;
263
264 filter_match_determine_eval_function(self);
265
266 return TRUE;
267 }
268
269 static void
filter_match_free(FilterExprNode * s)270 filter_match_free(FilterExprNode *s)
271 {
272 FilterMatch *self = (FilterMatch *) s;
273
274 log_template_unref(self->template);
275 filter_re_free(&self->super.super);
276 }
277
278 FilterExprNode *
filter_match_new(void)279 filter_match_new(void)
280 {
281 FilterMatch *self = g_new0(FilterMatch, 1);
282
283 filter_re_init_instance(&self->super, 0);
284 self->super.super.init = filter_match_init;
285 self->super.super.free_fn = filter_match_free;
286 return &self->super.super;
287 }
288