1 /*
2  * Copyright (c) 2008-2016 Balabit
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License version 2 as published
6  * by the Free Software Foundation, or (at your option) any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
16  *
17  * As an additional exemption you are allowed to compile & link against the
18  * OpenSSL libraries as published by the OpenSSL project. See the file
19  * COPYING for details.
20  *
21  */
22 
23 #include <criterion/criterion.h>
24 
25 #include "logmatcher.h"
26 #include "apphook.h"
27 #include "plugin.h"
28 #include "cfg.h"
29 #include "msg_parse_lib.h"
30 
31 #include <stdlib.h>
32 #include <string.h>
33 
34 MsgFormatOptions parse_options;
35 
36 static LogMessage *
_create_log_message(const gchar * log)37 _create_log_message(const gchar *log)
38 {
39   LogMessage *msg;
40   gchar buf[1024];
41   NVHandle nonasciiz = log_msg_get_value_handle("NON-ASCIIZ");
42   gssize msglen;
43 
44   msg = log_msg_new(log, strlen(log), &parse_options);
45 
46   /* NOTE: we test how our matchers cope with non-zero terminated values. We don't change message_len, only the value */
47   g_snprintf(buf, sizeof(buf), "%sAAAAAAAAAAAA", log_msg_get_value(msg, LM_V_MESSAGE, &msglen));
48   log_msg_set_value_by_name(msg, "MESSAGE2", buf, -1);
49 
50   /* add a non-zero terminated indirect value which contains the whole message */
51   log_msg_set_value_indirect(msg, nonasciiz, log_msg_get_value_handle("MESSAGE2"), 0, 0, msglen);
52 
53   return msg;
54 }
55 
56 static LogMatcher *
_construct_matcher(gint matcher_flags,LogMatcher * (* construct)(const LogMatcherOptions * options))57 _construct_matcher(gint matcher_flags, LogMatcher *(*construct)(const LogMatcherOptions *options))
58 {
59   LogMatcherOptions matcher_options;
60 
61   log_matcher_options_defaults(&matcher_options);
62   matcher_options.flags = matcher_flags;
63 
64   return construct(&matcher_options);
65 }
66 
67 
68 void
testcase_match(const gchar * log,const gchar * pattern,gboolean expected_result,LogMatcher * m)69 testcase_match(const gchar *log, const gchar *pattern, gboolean expected_result, LogMatcher *m)
70 {
71   LogMessage *msg;
72   gboolean result;
73   NVHandle nonasciiz = log_msg_get_value_handle("NON-ASCIIZ");
74   gssize msglen;
75   const gchar *value;
76 
77   msg = _create_log_message(log);
78   log_matcher_compile(m, pattern, NULL);
79 
80   value = log_msg_get_value(msg, nonasciiz, &msglen);
81   result = log_matcher_match(m, msg, nonasciiz, value, msglen);
82 
83   cr_assert_eq(result, expected_result,
84                "pattern=%s, result=%d, expected=%d\n",
85                pattern, result, expected_result);
86 
87   log_matcher_unref(m);
88   log_msg_unref(msg);
89 }
90 
91 void
testcase_replace(const gchar * log,const gchar * re,gchar * replacement,const gchar * expected_result,LogMatcher * m)92 testcase_replace(const gchar *log, const gchar *re, gchar *replacement, const gchar *expected_result, LogMatcher *m)
93 {
94   LogMessage *msg;
95   LogTemplate *r;
96   gchar *result;
97   gssize length;
98   gssize msglen;
99   NVHandle nonasciiz = log_msg_get_value_handle("NON-ASCIIZ");
100   const gchar *value;
101 
102   msg = _create_log_message(log);
103   log_matcher_compile(m, re, NULL);
104 
105   r = log_template_new(configuration, NULL);
106   cr_assert(log_template_compile(r, replacement, NULL));
107 
108   NVTable *nv_table = nv_table_ref(msg->payload);
109   value = log_msg_get_value(msg, nonasciiz, &msglen);
110   result = log_matcher_replace(m, msg, nonasciiz, value, msglen, r, &length);
111   value = log_msg_get_value(msg, nonasciiz, &msglen);
112   nv_table_unref(nv_table);
113 
114   cr_assert_arr_eq((result ? result : value), expected_result, (result ? length : msglen),
115                    "pattern=%s, result=%.*s, expected=%s\n",
116                    re, (int) length, (result ? result : value), expected_result);
117 
118   g_free(result);
119 
120   log_template_unref(r);
121   log_matcher_unref(m);
122   log_msg_unref(msg);
123 }
124 
125 
126 void
setup(void)127 setup(void)
128 {
129   app_startup();
130   init_parse_options_and_load_syslogformat(&parse_options);
131 }
132 
133 void
teardown(void)134 teardown(void)
135 {
136   deinit_syslogformat_module();
137   app_shutdown();
138 }
139 
140 TestSuite(matcher, .init = setup, .fini = teardown);
141 
142 Test(matcher, pcre_regexp, .description = "PCRE regexp")
143 {
144   testcase_replace("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: árvíztűrőtükörfúrógép", "árvíz",
145                    "favíz", "favíztűrőtükörfúrógép", _construct_matcher(0, log_matcher_pcre_re_new));
146   testcase_replace("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: árvíztűrőtükörfúrógép", "^tűrő",
147                    "faró", "árvíztűrőtükörfúrógép", _construct_matcher(0, log_matcher_pcre_re_new));
148   testcase_replace("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: árvíztűrőtükörfúrógép", "tűrő", "",
149                    "árvíztükörfúrógép", _construct_matcher(0, log_matcher_pcre_re_new));
150   testcase_replace("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: wikiwiki", "wi", "", "kiki",
151                    _construct_matcher(LMF_GLOBAL, log_matcher_pcre_re_new));
152   testcase_replace("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: wikiwiki", "wi", "kuku", "kukukikukuki",
153                    _construct_matcher(LMF_GLOBAL, log_matcher_pcre_re_new));
154 }
155 
Test(matcher,back_ref)156 Test(matcher, back_ref)
157 {
158   testcase_replace("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: wikiwiki", "(wiki)\\1", "", "",
159                    _construct_matcher(LMF_STORE_MATCHES, log_matcher_pcre_re_new));
160 }
161 
162 Test(matcher, empty_global, .description = "empty match with global flag")
163 {
164   testcase_replace("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: aa bb", "c*", "#", "#a#a# #b#b#",
165                    _construct_matcher(LMF_GLOBAL, log_matcher_pcre_re_new));
166   testcase_replace("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: aa bb", "a*", "#", "## #b#b#",
167                    _construct_matcher(LMF_GLOBAL, log_matcher_pcre_re_new));
168 
169   testcase_replace("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: aa bb", "c*", "#", "#a#a# #b#b#",
170                    _construct_matcher(LMF_GLOBAL, log_matcher_pcre_re_new));
171   testcase_replace("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: aa bb", "a*", "?", "?? ?b?b?",
172                    _construct_matcher(LMF_GLOBAL, log_matcher_pcre_re_new));
173   testcase_replace("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: aa", "aa|b*", "@", "@@",
174                    _construct_matcher(LMF_GLOBAL, log_matcher_pcre_re_new));
175   testcase_replace("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: aa", "aa|b*", "@", "@", _construct_matcher(0,
176                    log_matcher_pcre_re_new));
177   testcase_replace("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: aa", "b*|aa", "@", "@@@",
178                    _construct_matcher(LMF_GLOBAL, log_matcher_pcre_re_new));
179   testcase_replace("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: aa", "b*|aa", "@", "@aa", _construct_matcher(0,
180                    log_matcher_pcre_re_new));
181 
182   testcase_replace("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: wikiwiki", "wi", "", "kiki",
183                    _construct_matcher(LMF_GLOBAL, log_matcher_pcre_re_new));
184   testcase_replace("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: wikiwiki", "wi", "kuku", "kukukikukuki",
185                    _construct_matcher(LMF_GLOBAL, log_matcher_pcre_re_new));
186 }
187 
Test(matcher,disable_jit)188 Test(matcher, disable_jit)
189 {
190   testcase_replace("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: árvíztűrőtükörfúrógép", "árvíz",
191                    "favíz", "favíztűrőtükörfúrógép", _construct_matcher(LMF_DISABLE_JIT, log_matcher_pcre_re_new));
192 }
193 
Test(matcher,string_match)194 Test(matcher, string_match)
195 {
196   testcase_replace("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: árvíztűrőtükörfúrógép", "árvíz",
197                    "favíz", "favíztűrőtükörfúrógép", _construct_matcher(LMF_PREFIX, log_matcher_string_new));
198   testcase_replace("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: árvíztűrőtükörfúrógép", "tűrő",
199                    "faró", "árvízfarótükörfúrógép", _construct_matcher(LMF_SUBSTRING, log_matcher_string_new));
200   testcase_replace("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: árvíztűrőtükörfúrógép", "tűrő", "",
201                    "árvíztükörfúrógép", _construct_matcher(LMF_SUBSTRING, log_matcher_string_new));
202   testcase_replace("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: árvíztűrőtükörfúrógép",
203                    "árvíztűrőtükörfúrógép", "almafa", "almafa", _construct_matcher(0, log_matcher_string_new));
204   testcase_replace("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: ", "valami-amivel-nem-szabadna-matchelni",
205                    "almafa", "", _construct_matcher(0, log_matcher_string_new));
206 
207 
208   testcase_match("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: val", "valami-amivel-nem-szabadna-matchelni",
209                  FALSE, _construct_matcher(0, log_matcher_string_new));
210   testcase_match("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: ", "valami-amivel-nem-szabadna-matchelni", FALSE,
211                  _construct_matcher(0, log_matcher_string_new));
212   testcase_match("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: ", "valami-amivel-nem-szabadna-matchelni", 0,
213                  _construct_matcher(LMF_PREFIX, log_matcher_string_new));
214   testcase_match("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: ", "valami-amivel-nem-szabadna-matchelni", 0,
215                  _construct_matcher(LMF_SUBSTRING, log_matcher_string_new));
216 
217   testcase_match("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: match", "match", TRUE, _construct_matcher(0,
218                  log_matcher_string_new));
219   testcase_match("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: match", "ma", TRUE,
220                  _construct_matcher(LMF_PREFIX, log_matcher_string_new));
221   testcase_match("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: match", "tch", TRUE,
222                  _construct_matcher(LMF_SUBSTRING, log_matcher_string_new));
223 
224   testcase_replace("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: abcdef", "ABCDEF", "qwerty", "qwerty",
225                    _construct_matcher(LMF_PREFIX | LMF_ICASE, log_matcher_string_new));
226   testcase_replace("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: abcdef", "BCD", "qwerty", "aqwertyef",
227                    _construct_matcher(LMF_SUBSTRING | LMF_ICASE, log_matcher_string_new));
228 }
229 
Test(matcher,glob_match)230 Test(matcher, glob_match)
231 {
232   testcase_match("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: árvíztűrőtükörfúrógép", "árvíz*",
233                  TRUE, _construct_matcher(0, log_matcher_glob_new));
234   testcase_match("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: árvíztűrőtükörfúrógép", "*fúrógép",
235                  TRUE, _construct_matcher(0, log_matcher_glob_new));
236   testcase_match("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: árvíztűrőtükörfúrógép", "*fúró*",
237                  TRUE, _construct_matcher(0, log_matcher_glob_new));
238   testcase_match("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: árvíztűrőtükörfúrógép", "tükör",
239                  FALSE, _construct_matcher(0, log_matcher_glob_new));
240   testcase_match("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: árvíztűrőtükörfúrógép", "viziló",
241                  FALSE, _construct_matcher(0, log_matcher_glob_new));
242 }
243 
244 Test(matcher, iso88592_never, .description = "match in iso-8859-2 never matches")
245 {
246   testcase_match("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: \xe1rv\xedzt\xfbr\xf5t\xfck\xf6rf\xfar\xf3g\xe9p",
247                  "\xe1rv\xed*", FALSE, _construct_matcher(0, log_matcher_glob_new));
248 }
249 
Test(matcher,replace)250 Test(matcher, replace)
251 {
252   testcase_replace("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: árvíztűrőtükörfúrógép", "árvíz",
253                    "favíz", "favíztűrőtükörfúrógép", _construct_matcher(0, log_matcher_pcre_re_new));
254   testcase_replace("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: árvíztűrőtükörfúrógép", "^tűrő",
255                    "faró", "árvíztűrőtükörfúrógép", _construct_matcher(0, log_matcher_pcre_re_new));
256   testcase_replace("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: árvíztűrőtükörfúrógép", "tűrő", "",
257                    "árvíztükörfúrógép", _construct_matcher(0, log_matcher_pcre_re_new));
258   testcase_replace("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: wikiwiki", "(wiki)\\1", "", "",
259                    _construct_matcher(0, log_matcher_pcre_re_new));
260   /* back ref with perl style $1 */
261   testcase_replace("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: wikiwiki", "(wiki).+", "#$1#", "#wiki#",
262                    _construct_matcher(0, log_matcher_pcre_re_new));
263 }
264 
265 Test(matcher, pcre812_incompatibility, .description = "tests a pcre 8.12 incompatibility")
266 {
267   testcase_replace("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: wikiwiki",
268                    "([[:digit:]]{1,3}\\.){3}[[:digit:]]{1,3}", "foo", "wikiwiki", _construct_matcher(LMF_GLOBAL, log_matcher_pcre_re_new));
269 }
270