1 /*
2  * Copyright (c) 2008-2018 Balabit
3  * Copyright (c) 2008-2015 Balázs Scheidler <balazs.scheidler@balabit.com>
4  * Copyright (c) 2009 Marton Illes
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License version 2 as published
8  * by the Free Software Foundation, or (at your option) any later version.
9  *
10  * This program 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
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; 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 "apphook.h"
26 #include "radix.h"
27 #include "messages.h"
28 
29 #include <stdio.h>
30 #include <sys/time.h>
31 #include <time.h>
32 #include <string.h>
33 #include <stdlib.h>
34 
35 #include <criterion/criterion.h>
36 #include <criterion/parameterized.h>
37 
38 #define RADIX_TEST_MAX_PATTERN 5
39 #define RADIX_TEST_MAX_NODE 5
40 
41 typedef struct _radix_test_param
42 {
43   const gchar *node_to_insert[RADIX_TEST_MAX_NODE];
44   const gchar *key;
45   const gchar *expected_pattern[RADIX_TEST_MAX_PATTERN];
46 } RadixTestParam;
47 
48 void
insert_node_with_value(RNode * root,const gchar * key,const gpointer value)49 insert_node_with_value(RNode *root, const gchar *key, const gpointer value)
50 {
51   gchar *dup;
52 
53   /* NOTE: we need to duplicate the key as r_insert_node modifies its input
54    * and it might be a read-only string literal */
55 
56   dup = g_strdup(key);
57   r_insert_node(root, dup, value ? : (gpointer)key, NULL, NULL);
58   g_free(dup);
59 }
60 
61 void
insert_node(RNode * root,const gchar * key)62 insert_node(RNode *root, const gchar *key)
63 {
64   insert_node_with_value(root, key, NULL);
65 }
66 
67 void
test_search_value(RNode * root,const gchar * key,const gchar * expected_value)68 test_search_value(RNode *root, const gchar *key, const gchar *expected_value)
69 {
70   RNode *ret = r_find_node(root, (gchar *)key, strlen(key), NULL);
71 
72   if (expected_value)
73     {
74       cr_assert(ret, "node not found. key=%s\n", key);
75       cr_expect_str_eq(ret->value, expected_value, "FAIL: returned value does not match expected: '%s' <> '%s'\n",
76                        (gchar *) ret->value, expected_value);
77     }
78   else
79     {
80       cr_assert_not(ret, "found unexpected: '%s' => '%s'\n", key, (gchar *) ret->value);
81     }
82 }
83 
84 void
test_search(RNode * root,const gchar * key,gboolean expect)85 test_search(RNode *root, const gchar *key, gboolean expect)
86 {
87   test_search_value(root, key, expect ? key : NULL);
88 }
89 
90 void
test_search_matches(RNode * root,const gchar * key,const gchar * search_pattern[])91 test_search_matches(RNode *root, const gchar *key, const gchar *search_pattern[])
92 {
93   GArray *matches = g_array_new(FALSE, TRUE, sizeof(RParserMatch));
94   g_array_set_size(matches, 1);
95 
96   RParserMatch *match;
97   const gchar *match_name;
98 
99   RNode *ret = r_find_node(root, (gchar *) key, strlen(key), matches);
100 
101   if (!search_pattern[0])
102     {
103       cr_expect_not(ret, "found unexpected: '%s' => '%s' matches: ", key, (gchar *) ret->value);
104     }
105   else
106     {
107       cr_assert(ret, "not found while expected: '%s' => none %s\n", key, search_pattern[0]);
108 
109       for (int i=0; search_pattern[i]; i+=2)
110         {
111           cr_assert_lt(i/2, matches->len, "not enough matches: %d => expecting %d", i, matches->len);
112 
113           const gchar *expected_name = search_pattern[i];
114           const gchar *expected_value = search_pattern[i+1];
115 
116           match = &g_array_index(matches, RParserMatch, (i/2)+1);
117           match_name = log_msg_get_value_name(match->handle, NULL);
118 
119           cr_expect_str_eq(match_name, expected_name,
120                            "name does not match (key=%s): '%s' => expecting '%s'\n",
121                            key, match_name, expected_name);
122 
123           if (!match->match)
124             {
125               cr_expect_eq(match->len, strlen(expected_value),
126                            "value length does not match (key=%s): %d => expecting %zu\n",
127                            key, match->len, strlen(expected_value));
128               cr_expect_eq(strncmp(&key[match->ofs], expected_value, match->len), 0,
129                            "value does not match (key=%s): %*s => expecting %s\n",
130                            key, match->len, &key[match->ofs], expected_value);
131             }
132           else
133             {
134               cr_expect_str_eq(match->match, expected_value,
135                                "value does not match (key=%s): '%s' => expecting '%s'\n",
136                                key, match->match, expected_value);
137             }
138         }
139     }
140 
141   for (gsize i = 0; i < matches->len; i++)
142     {
143       match = &g_array_index(matches, RParserMatch, i);
144       if (match->match)
145         {
146           g_free(match->match);
147         }
148     }
149   g_array_free(matches, TRUE);
150 }
151 
test_setup(void)152 void test_setup(void)
153 {
154   app_startup();
155   msg_init(TRUE);
156 }
157 
test_teardown(void)158 void test_teardown(void)
159 {
160   app_shutdown();
161 }
162 
163 Test(dbparser, test_literals, .init = test_setup, .fini = test_teardown)
164 {
165   RNode *root = r_new_node("", NULL);
166 
167   insert_node(root, "alma");
168   insert_node(root, "korte");
169   insert_node(root, "barack");
170   insert_node(root, "dinnye");
171   insert_node(root, "almafa");
172   insert_node(root, "almabor");
173   insert_node(root, "almafa2");
174   insert_node(root, "ko");
175   insert_node(root, "koros");
176   insert_node(root, "koro");
177   insert_node(root, "koromporkolt");
178   insert_node(root, "korom");
179   insert_node(root, "korozott");
180   insert_node(root, "al");
181   insert_node(root, "all");
182   insert_node(root, "uj\nsor");
183 
184   test_search(root, "alma", TRUE);
185   test_search(root, "korte", TRUE);
186   test_search(root, "barack", TRUE);
187   test_search(root, "dinnye", TRUE);
188   test_search(root, "almafa", TRUE);
189   test_search(root, "almabor", TRUE);
190   test_search(root, "almafa2", TRUE);
191   test_search(root, "ko", TRUE);
192   test_search(root, "koros", TRUE);
193   test_search(root, "koro", TRUE);
194   test_search(root, "koromporkolt", TRUE);
195   test_search(root, "korom", TRUE);
196   test_search(root, "korozott", TRUE);
197   test_search(root, "al", TRUE);
198   test_search(root, "all", TRUE);
199   test_search(root, "uj", FALSE);
200   test_search(root, "uj\nsor", TRUE);
201   test_search_value(root, "uj\r\nsor", "uj\nsor");
202 
203   test_search(root, "mmm", FALSE);
204   test_search_value(root, "kor", "ko");
205   test_search_value(root, "ko", "ko");
206   test_search_value(root, "kort", "ko");
207   test_search_value(root, "korti", "ko");
208   test_search_value(root, "korte", "korte");
209   test_search_value(root, "kortes", "korte");
210   test_search_value(root, "koromp", "korom");
211   test_search_value(root, "korompo", "korom");
212   test_search_value(root, "korompor", "korom");
213   test_search_value(root, "korompok", "korom");
214   test_search_value(root, "korompa", "korom");
215   test_search_value(root, "koromi", "korom");
216 
217   test_search(root, "qwqw", FALSE);
218 
219   r_free_node(root, NULL);
220 }
221 
222 Test(dbparser, test_parsers, .init = test_setup, .fini = test_teardown)
223 {
224   RNode *root = r_new_node("", NULL);
225 
226   /* FIXME: more parsers */
227   insert_node(root, "a@@NUMBER@@aa@@@@");
228   insert_node(root, "a@@ab");
229   insert_node(root, "a@@a@@");
230 
231   insert_node(root, "a@@@NUMBER:szam0@");
232   insert_node(root, "a@NUMBER:szamx@aaa");
233   insert_node(root, "a@NUMBER@");
234   insert_node(root, "a@NUMBER@aa");
235   insert_node(root, "a@NUMBER:szamx@@@");
236 
237   insert_node(root, "baa@NUMBER@");
238   insert_node(root, "bxa@NUMBER:szam5@");
239   insert_node(root, "baa@@");
240   insert_node(root, "baa@@@@");
241   insert_node(root, "ba@@a");
242   insert_node(root, "bc@@a");
243   insert_node(root, "@@a@NUMBER:szam4@@@");
244   insert_node(root, "@@a@NUMBER:szam4@b");
245   insert_node(root, "@@a");
246   insert_node(root, "@@");
247   insert_node(root, "@@@@");
248 
249   insert_node(root, "xxx@ESTRING@");
250   insert_node(root, "xxx@QSTRING@");
251   insert_node(root, "xxx@STRING@");
252   insert_node(root, "xxx@ANYSTRING@");
253   insert_node(root, "xxx@ESTRING@x");
254   insert_node(root, "xxx@QSTRING@x");
255   insert_node(root, "xxx@STRING@x");
256   insert_node(root, "xxx@ANYSTRING@x");
257   insert_node(root, "AAA@NUMBER:invalid=@AAA");
258   insert_node(root, "AAA@SET@AAA");
259   insert_node(root, "AAA@SET:set@AAA");
260   insert_node(root, "AAA@OPTIONALSET@AAA");
261   insert_node(root, "AAA@OPTIONALSET:set@AAA");
262   insert_node(root, "AAA@MACADDR@AAA");
263   insert_node(root, "newline@NUMBER@\n2ndline\n");
264   insert_node(root, "AAA@PCRE:set@AAA");
265 
266   test_search_value(root, "a@", NULL);
267   test_search_value(root, "a@NUMBER@aa@@", "a@@NUMBER@@aa@@@@");
268   test_search_value(root, "a@a", NULL);
269   test_search_value(root, "a@ab", "a@@ab");
270   test_search_value(root, "a@a@", "a@@a@@");
271   test_search_value(root, "a@ax", NULL);
272 
273   test_search_value(root, "a@15555", "a@@@NUMBER:szam0@");
274 
275   /* CRLF sequence immediately after a parser, e.g. in the initial position */
276   test_search_value(root, "newline123\r\n2ndline\n", "newline@NUMBER@\n2ndline\n");
277 
278   test_search_value(root, "a15555aaa", "a@NUMBER:szamx@aaa");
279   test_search_value(root, "@a", "@@a");
280   test_search_value(root, "@", "@@");
281   test_search_value(root, "@@", "@@@@");
282 
283   r_free_node(root, NULL);
284 }
285 
ParameterizedTestParameters(dbparser,test_radix_search_matches)286 ParameterizedTestParameters(dbparser, test_radix_search_matches)
287 {
288   static RadixTestParam parser_params[] =
289   {
290     /* test_ip_matches */
291     {
292       .node_to_insert = {"@IPvANY:ip@", NULL},
293       .key = "192.168.1.1 huhuhu",
294       .expected_pattern = {"ip", "192.168.1.1", NULL}
295     },
296     {
297       .node_to_insert = {"@IPvANY:ip@", NULL},
298       .key = "192.168.1.1. huhuhu",
299       .expected_pattern = {"ip", "192.168.1.1", NULL}
300     },
301     {
302       .node_to_insert = {"@IPvANY:ip@", NULL},
303       .key = "192.168.1huhuhu",
304       .expected_pattern = {NULL}
305     },
306     {
307       .node_to_insert = {"@IPvANY:ip@", NULL},
308       .key = "192.168.1.huhuhu",
309       .expected_pattern = {NULL}
310     },
311     {
312       .node_to_insert = {"@IPvANY:ip@", NULL},
313       .key = "192.168.1 huhuhu",
314       .expected_pattern = {NULL}
315     },
316     {
317       .node_to_insert = {"@IPvANY:ip@", NULL},
318       .key = "192.168.1. huhuhu",
319       .expected_pattern = {NULL}
320     },
321     {
322       .node_to_insert = {"@IPvANY:ip@", NULL},
323       .key = "192.168.1.1huhuhu",
324       .expected_pattern = {"ip", "192.168.1.1", NULL}
325     },
326     {
327       .node_to_insert = {"@IPvANY:ip@", NULL},
328       .key ="ABCD:EF01:2345:6789:ABCD:EF01:2345:6789 huhuhu",
329       .expected_pattern = {"ip", "ABCD:EF01:2345:6789:ABCD:EF01:2345:6789", NULL}
330     },
331     {
332       .node_to_insert = {"@IPvANY:ip@", NULL},
333       .key ="abcd:ef01:2345:6789:abcd:ef01:2345:6789 huhuhu",
334       .expected_pattern = {"ip", "abcd:ef01:2345:6789:abcd:ef01:2345:6789", NULL}
335     },
336     {
337       .node_to_insert = {"@IPvANY:ip@", NULL},
338       .key =":: huhuhu",
339       .expected_pattern = {"ip", "::", NULL}
340     },
341     {
342       .node_to_insert = {"@IPvANY:ip@", NULL},
343       .key ="0:0:0:0:0:0:13.1.68.3 huhuhu",
344       .expected_pattern = {"ip", "0:0:0:0:0:0:13.1.68.3", NULL}
345     },
346     {
347       .node_to_insert = {"@IPvANY:ip@", NULL},
348       .key ="::202.1.68.3 huhuhu",
349       .expected_pattern = {"ip", "::202.1.68.3", NULL}
350     },
351     {
352       .node_to_insert = {"@IPvANY:ip@", NULL},
353       .key ="2001:0DB8:0:CD30:: huhuhu",
354       .expected_pattern = {"ip", "2001:0DB8:0:CD30::", NULL}
355     },
356     {
357       .node_to_insert = {"@IPvANY:ip@", NULL},
358       .key ="ABCD:EF01:2345:6789:ABCD:EF01:2345:6789.huhuhu",
359       .expected_pattern = {"ip", "ABCD:EF01:2345:6789:ABCD:EF01:2345:6789", NULL}
360     },
361     {
362       .node_to_insert = {"@IPvANY:ip@", NULL},
363       .key ="abcd:ef01:2345:6789:abcd:ef01:2345:6789.huhuhu",
364       .expected_pattern = {"ip", "abcd:ef01:2345:6789:abcd:ef01:2345:6789", NULL}
365     },
366     {
367       .node_to_insert = {"@IPvANY:ip@", NULL},
368       .key ="::.huhuhu",
369       .expected_pattern = {"ip", "::", NULL}
370     },
371     {
372       .node_to_insert = {"@IPvANY:ip@", NULL},
373       .key ="0:0:0:0:0:0:13.1.68.3.huhuhu",
374       .expected_pattern = {"ip", "0:0:0:0:0:0:13.1.68.3", NULL}
375     },
376     {
377       .node_to_insert = {"@IPvANY:ip@", NULL},
378       .key ="::202.1.68.3.huhuhu",
379       .expected_pattern = {"ip", "::202.1.68.3", NULL}
380     },
381     {
382       .node_to_insert = {"@IPvANY:ip@", NULL},
383       .key ="2001:0DB8:0:CD30::.huhuhu",
384       .expected_pattern = {"ip", "2001:0DB8:0:CD30::", NULL}
385     },
386     {
387       .node_to_insert = {"@IPvANY:ip@", NULL},
388       .key ="1:2:3:4:5:6:7:8.huhuhu",
389       .expected_pattern = {"ip", "1:2:3:4:5:6:7:8", NULL}
390     },
391     {
392       .node_to_insert = {"@IPvANY:ip@", NULL},
393       .key ="1:2:3:4:5:6:7:8 huhuhu",
394       .expected_pattern = {"ip", "1:2:3:4:5:6:7:8", NULL}
395     },
396     {
397       .node_to_insert = {"@IPvANY:ip@", NULL},
398       .key ="1:2:3:4:5:6:7:8:huhuhu",
399       .expected_pattern = {"ip", "1:2:3:4:5:6:7:8", NULL}
400     },
401     {
402       .node_to_insert = {"@IPvANY:ip@", NULL},
403       .key ="1:2:3:4:5:6:7 huhu",
404       .expected_pattern = {NULL}
405     },
406     {
407       .node_to_insert = {"@IPvANY:ip@", NULL},
408       .key ="1:2:3:4:5:6:7.huhu",
409       .expected_pattern = {NULL}
410     },
411     {
412       .node_to_insert = {"@IPvANY:ip@", NULL},
413       .key ="1:2:3:4:5:6:7:huhu",
414       .expected_pattern = {NULL}
415     },
416     {
417       .node_to_insert = {"@IPvANY:ip@", NULL},
418       .key ="1:2:3:4:5:6:77777:8 huhu",
419       .expected_pattern = {NULL}
420     },
421     {
422       .node_to_insert = {"@IPvANY:ip@", NULL},
423       .key ="1:2:3:4:5:6:1.2.333.4 huhu",
424       .expected_pattern = {NULL}
425     },
426     {
427       .node_to_insert = {"@IPvANY:ip@", NULL},
428       .key ="v12345",
429       .expected_pattern = {NULL}
430     },
431     /* test_ipv4_matches */
432     {
433       .node_to_insert = {"@IPv4:ipv4@", NULL},
434       .key = "192.168.1.1 huhuhu",
435       .expected_pattern = {"ipv4", "192.168.1.1", NULL}
436     },
437     {
438       .node_to_insert = {"@IPv4:ipv4@", NULL},
439       .key = "192.168.1.1. huhuhu",
440       .expected_pattern = {"ipv4", "192.168.1.1", NULL}
441     },
442     {
443       .node_to_insert = {"@IPv4:ipv4@", NULL},
444       .key = "192.168.1.1.huhuhu",
445       .expected_pattern = {"ipv4", "192.168.1.1", NULL}
446     },
447     {
448       .node_to_insert = {"@IPv4:ipv4@", NULL},
449       .key = "192.168.1.1.. huhuhu",
450       .expected_pattern = {"ipv4", "192.168.1.1", NULL}
451     },
452     {
453       .node_to_insert = {"@IPv4:ipv4@", NULL},
454       .key = "192.168.1.1.2 huhuhu",
455       .expected_pattern = {"ipv4", "192.168.1.1", NULL}
456     },
457     {
458       .node_to_insert = {"@IPv4:ipv4@", NULL},
459       .key = "192.168.1.1..huhuhu",
460       .expected_pattern = {"ipv4", "192.168.1.1", NULL}
461     },
462     {
463       .node_to_insert = {"@IPv4:ipv4@", NULL},
464       .key = "192.168.1.1huhuhu",
465       .expected_pattern = {"ipv4", "192.168.1.1", NULL}
466     },
467     {
468       .node_to_insert = {"@IPv4:ipv4@", NULL},
469       .key = "192.168.1huhuhu",
470       .expected_pattern = {NULL}
471     },
472     {
473       .node_to_insert = {"@IPv4:ipv4@", NULL},
474       .key = "192.168.1.huhuhu",
475       .expected_pattern = {NULL}
476     },
477     {
478       .node_to_insert = {"@IPv4:ipv4@", NULL},
479       .key = "192.168.1 huhuhu",
480       .expected_pattern = {NULL}
481     },
482     {
483       .node_to_insert = {"@IPv4:ipv4@", NULL},
484       .key = "192.168.1. huhuhu",
485       .expected_pattern = {NULL}
486     },
487     {
488       .node_to_insert = {"@IPv4:ipv4@", NULL},
489       .key = "v12345",
490       .expected_pattern = {NULL}
491     },
492     /* test_ipv6_matches */
493     {
494       .node_to_insert = {"@IPv6:ipv6@", NULL},
495       .key = "1:2:3:4:5:6:7 huhu",
496       .expected_pattern = {NULL}
497     },
498     {
499       .node_to_insert = {"@IPv6:ipv6@", NULL},
500       .key = "1:2:3:4:5:6:7.huhu",
501       .expected_pattern = {NULL}
502     },
503     {
504       .node_to_insert = {"@IPv6:ipv6@", NULL},
505       .key = "1:2:3:4:5:6:7:huhu",
506       .expected_pattern = {NULL},
507     },
508     {
509       .node_to_insert = {"@IPv6:ipv6@", NULL},
510       .key = "v12345",
511       .expected_pattern = {NULL},
512     },
513     {
514       .node_to_insert = {"@IPv6:ipv6@", NULL},
515       .key = "ABCD:EF01:2345:6789:ABCD:EF01:2345:6789 huhuhu",
516       .expected_pattern = {"ipv6", "ABCD:EF01:2345:6789:ABCD:EF01:2345:6789", NULL}
517     },
518     {
519       .node_to_insert = {"@IPv6:ipv6@", NULL},
520       .key = "abcd:ef01:2345:6789:abcd:ef01:2345:6789 huhuhu",
521       .expected_pattern = {"ipv6", "abcd:ef01:2345:6789:abcd:ef01:2345:6789", NULL}
522     },
523     {
524       .node_to_insert = {"@IPv6:ipv6@", NULL},
525       .key = "0:0:0:0:0:0:0:0 huhuhu",
526       .expected_pattern = {"ipv6", "0:0:0:0:0:0:0:0", NULL}
527     },
528     {
529       .node_to_insert = {"@IPv6:ipv6@", NULL},
530       .key = "2001:DB8::8:800:200C:417A huhuhu",
531       .expected_pattern = {"ipv6", "2001:DB8::8:800:200C:417A", NULL}
532     },
533     {
534       .node_to_insert = {"@IPv6:ipv6@", NULL},
535       .key = "FF01::101 huhuhu",
536       .expected_pattern = {"ipv6", "FF01::101", NULL}
537     },
538     {
539       .node_to_insert = {"@IPv6:ipv6@", NULL},
540       .key = "::1 huhuhu",
541       .expected_pattern = {"ipv6", "::1", NULL}
542     },
543     {
544       .node_to_insert = {"@IPv6:ipv6@", NULL},
545       .key = ":: huhuhu",
546       .expected_pattern = {"ipv6", "::", NULL}
547     },
548     {
549       .node_to_insert = {"@IPv6:ipv6@", NULL},
550       .key = "0:0:0:0:0:0:13.1.68.3 huhuhu",
551       .expected_pattern = {"ipv6", "0:0:0:0:0:0:13.1.68.3", NULL}
552     },
553     {
554       .node_to_insert = {"@IPv6:ipv6@", NULL},
555       .key = "::202.1.68.3 huhuhu",
556       .expected_pattern = {"ipv6", "::202.1.68.3", NULL}
557     },
558     {
559       .node_to_insert = {"@IPv6:ipv6@", NULL},
560       .key = "2001:0DB8:0:CD30:: huhuhu",
561       .expected_pattern = {"ipv6", "2001:0DB8:0:CD30::", NULL}
562     },
563     {
564       .node_to_insert = {"@IPv6:ipv6@", NULL},
565       .key = "2001:0DB8:0:CD30::huhuhu",
566       .expected_pattern = {"ipv6", "2001:0DB8:0:CD30::", NULL}
567     },
568     {
569       .node_to_insert = {"@IPv6:ipv6@", NULL},
570       .key = "::ffff:200.200.200.200huhuhu",
571       .expected_pattern = {"ipv6", "::ffff:200.200.200.200", NULL}
572     },
573     {
574       .node_to_insert = {"@IPv6:ipv6@", NULL},
575       .key = "2001:0DB8:0:CD30::huhuhu",
576       .expected_pattern = {"ipv6", "2001:0DB8:0:CD30::", NULL}
577     },
578     {
579       .node_to_insert = {"@IPv6:ipv6@", NULL},
580       .key = "::ffff:200.200.200.200 :huhuhu",
581       .expected_pattern = {"ipv6", "::ffff:200.200.200.200", NULL}
582     },
583     {
584       .node_to_insert = {"@IPv6:ipv6@", NULL},
585       .key = "::ffff:200.200.200.200: huhuhu",
586       .expected_pattern = {"ipv6", "::ffff:200.200.200.200", NULL}
587     },
588     {
589       .node_to_insert = {"@IPv6:ipv6@", NULL},
590       .key = "::ffff:200.200.200.200. :huhuhu",
591       .expected_pattern = {"ipv6", "::ffff:200.200.200.200", NULL}
592     },
593     {
594       .node_to_insert = {"@IPv6:ipv6@", NULL},
595       .key = "::ffff:200.200.200.200.:huhuhu",
596       .expected_pattern = {"ipv6", "::ffff:200.200.200.200", NULL}
597     },
598     {
599       .node_to_insert = {"@IPv6:ipv6@", NULL},
600       .key = "::ffff:200.200.200.200.2:huhuhu",
601       .expected_pattern = {"ipv6", "::ffff:200.200.200.200", NULL}
602     },
603     {
604       .node_to_insert = {"@IPv6:ipv6@", NULL},
605       .key = "::0: huhuhu",
606       .expected_pattern = {"ipv6", "::0", NULL}
607     },
608     {
609       .node_to_insert = {"@IPv6:ipv6@", NULL},
610       .key = "0:0:0:0:0:0:0:0: huhuhu",
611       .expected_pattern = {"ipv6", "0:0:0:0:0:0:0:0", NULL}
612     },
613     {
614       .node_to_insert = {"@IPv6:ipv6@", NULL},
615       .key = "::129.144.52.38: huhuhu",
616       .expected_pattern = {"ipv6", "::129.144.52.38", NULL}
617     },
618     {
619       .node_to_insert = {"@IPv6:ipv6@", NULL},
620       .key = "::ffff:129.144.52.38: huhuhu",
621       .expected_pattern = {"ipv6", "::ffff:129.144.52.38", NULL}
622     },
623     {
624       .node_to_insert = {"@IPv6:ipv6@", NULL},
625       .key = "ABCD:EF01:2345:6789:ABCD:EF01:2345:6789.huhuhu",
626       .expected_pattern = {"ipv6", "ABCD:EF01:2345:6789:ABCD:EF01:2345:6789", NULL}
627     },
628     {
629       .node_to_insert = {"@IPv6:ipv6@", NULL},
630       .key = "abcd:ef01:2345:6789:abcd:ef01:2345:6789.huhuhu",
631       .expected_pattern = {"ipv6", "abcd:ef01:2345:6789:abcd:ef01:2345:6789", NULL}
632     },
633     {
634       .node_to_insert = {"@IPv6:ipv6@", NULL},
635       .key = "0:0:0:0:0:0:0:0.huhuhu",
636       .expected_pattern = {"ipv6", "0:0:0:0:0:0:0:0", NULL}
637     },
638     {
639       .node_to_insert = {"@IPv6:ipv6@", NULL},
640       .key = "2001:DB8::8:800:200C:417A.huhuhu",
641       .expected_pattern = {"ipv6", "2001:DB8::8:800:200C:417A", NULL}
642     },
643     {
644       .node_to_insert = {"@IPv6:ipv6@", NULL},
645       .key = "FF01::101.huhuhu",
646       .expected_pattern = {"ipv6", "FF01::101", NULL}
647     },
648     {
649       .node_to_insert = {"@IPv6:ipv6@", NULL},
650       .key = "::1.huhuhu",
651       .expected_pattern = {"ipv6", "::1", NULL}
652     },
653     {
654       .node_to_insert = {"@IPv6:ipv6@", NULL},
655       .key = "::.huhuhu",
656       .expected_pattern = {"ipv6", "::", NULL}
657     },
658     {
659       .node_to_insert = {"@IPv6:ipv6@", NULL},
660       .key = "0:0:0:0:0:0:13.1.68.3.huhuhu",
661       .expected_pattern = {"ipv6", "0:0:0:0:0:0:13.1.68.3", NULL}
662     },
663     {
664       .node_to_insert = {"@IPv6:ipv6@", NULL},
665       .key = "::202.1.68.3.huhuhu",
666       .expected_pattern = {"ipv6", "::202.1.68.3", NULL}
667     },
668     {
669       .node_to_insert = {"@IPv6:ipv6@", NULL},
670       .key = "2001:0DB8:0:CD30::.huhuhu",
671       .expected_pattern = {"ipv6", "2001:0DB8:0:CD30::", NULL}
672     },
673     /* test_number_matches */
674     {
675       .node_to_insert = {"@NUMBER:number@", NULL},
676       .key = "12345 hihihi",
677       .expected_pattern = {"number", "12345", NULL}
678     },
679     {
680       .node_to_insert = {"@NUMBER:number@", NULL},
681       .key = "12345 hihihi",
682       .expected_pattern = {"number", "12345", NULL}
683     },
684     {
685       .node_to_insert = {"@NUMBER:number@", NULL},
686       .key = "0xaf12345 hihihi",
687       .expected_pattern = {"number", "0xaf12345", NULL}
688     },
689     {
690       .node_to_insert = {"@NUMBER:number@", NULL},
691       .key = "0xAF12345 hihihi",
692       .expected_pattern = {"number", "0xAF12345", NULL}
693     },
694     {
695       .node_to_insert = {"@NUMBER:number@", NULL},
696       .key = "0x12345 hihihi",
697       .expected_pattern = {"number", "0x12345", NULL}
698     },
699     {
700       .node_to_insert = {"@NUMBER:number@", NULL},
701       .key = "0XABCDEF12345ABCDEF hihihi",
702       .expected_pattern = {"number", "0XABCDEF12345ABCDEF", NULL}
703     },
704     {
705       .node_to_insert = {"@NUMBER:number@", NULL},
706       .key = "-12345 hihihi",
707       .expected_pattern = {"number", "-12345", NULL}
708     },
709     {
710       .node_to_insert = {"@NUMBER:number@", NULL},
711       .key = "v12345",
712       .expected_pattern = {NULL}
713     },
714     /* test_qstring_matches */
715     {
716       .node_to_insert = {"@QSTRING:qstring:'@", NULL},
717       .key = "'quoted string' hehehe",
718       .expected_pattern = {"qstring", "quoted string", NULL}
719     },
720     {
721       .node_to_insert = {"@QSTRING:qstring:'@", NULL},
722       .key = "v12345",
723       .expected_pattern = {NULL}
724     },
725     /* test_estring_matches */
726     {
727       .node_to_insert = {"ddd @ESTRING:estring::@",
728         "dddd @ESTRING:estring::*@",
729         "dddd2 @ESTRING:estring::*@ d",
730         "zzz @ESTRING:test:gép@",
731         NULL
732       },
733       .key = "ddd estring: hehehe",
734       .expected_pattern = {"estring", "estring", NULL},
735     },
736     {
737       .node_to_insert = {"ddd @ESTRING:estring::@",
738         "dddd @ESTRING:estring::*@",
739         "dddd2 @ESTRING:estring::*@ d",
740         "zzz @ESTRING:test:gép@",
741         NULL
742       },
743       .key = "ddd v12345",
744       .expected_pattern = {NULL},
745     },
746     {
747       .node_to_insert = {"ddd @ESTRING:estring::@",
748         "dddd @ESTRING:estring::*@",
749         "dddd2 @ESTRING:estring::*@ d",
750         "zzz @ESTRING:test:gép@",
751         NULL
752       },
753       .key = "dddd estring:* hehehe",
754       .expected_pattern = {"estring", "estring", NULL},
755     },
756     {
757       .node_to_insert = {"ddd @ESTRING:estring::@",
758         "dddd @ESTRING:estring::*@",
759         "dddd2 @ESTRING:estring::*@ d",
760         "zzz @ESTRING:test:gép@",
761         NULL
762       },
763       .key = "dddd estring:estring:* hehehe",
764       .expected_pattern = {"estring", "estring:estring", NULL},
765     },
766     {
767       .node_to_insert = {"ddd @ESTRING:estring::@",
768         "dddd @ESTRING:estring::*@",
769         "dddd2 @ESTRING:estring::*@ d",
770         "zzz @ESTRING:test:gép@",
771         NULL
772       },
773       .key = "dddd estring:estring::* hehehe",
774       .expected_pattern = {"estring", "estring:estring:", NULL},
775     },
776     {
777       .node_to_insert = {"ddd @ESTRING:estring::@",
778         "dddd @ESTRING:estring::*@",
779         "dddd2 @ESTRING:estring::*@ d",
780         "zzz @ESTRING:test:gép@",
781         NULL
782       },
783       .key = "dddd2 estring:estring::* d",
784       .expected_pattern = {"estring", "estring:estring:", NULL}
785     },
786     {
787       .node_to_insert = {"ddd @ESTRING:estring::@",
788         "dddd @ESTRING:estring::*@",
789         "dddd2 @ESTRING:estring::*@ d",
790         "zzz @ESTRING:test:gép@",
791         NULL
792       },
793       .key = "dddd2 estring:estring::* ",
794       .expected_pattern = {NULL},
795     },
796     {
797       .node_to_insert = {"ddd @ESTRING:estring::@",
798         "dddd @ESTRING:estring::*@",
799         "dddd2 @ESTRING:estring::*@ d",
800         "zzz @ESTRING:test:gép@",
801         NULL
802       },
803       .key = "dddd2 estring:estring::*",
804       .expected_pattern = {NULL},
805     },
806     {
807       .node_to_insert = {"ddd @ESTRING:estring::@",
808         "dddd @ESTRING:estring::*@",
809         "dddd2 @ESTRING:estring::*@ d",
810         "zzz @ESTRING:test:gép@",
811         NULL
812       },
813       .key = "dddd2 estring:estring:*",
814       .expected_pattern = {NULL}
815     },
816     {
817       .node_to_insert = {"ddd @ESTRING:estring::@",
818         "dddd @ESTRING:estring::*@",
819         "dddd2 @ESTRING:estring::*@ d",
820         "zzz @ESTRING:test:gép@",
821         NULL
822       },
823       .key = "dddd2 estring:estring",
824       .expected_pattern = {NULL},
825     },
826     {
827       .node_to_insert = {"ddd @ESTRING:estring::@",
828         "dddd @ESTRING:estring::*@",
829         "dddd2 @ESTRING:estring::*@ d",
830         "zzz @ESTRING:test:gép@",
831         NULL
832       },
833       .key = "dddd v12345",
834       .expected_pattern = {NULL},
835     },
836     {
837       .node_to_insert = {"ddd @ESTRING:estring::@",
838         "dddd @ESTRING:estring::*@",
839         "dddd2 @ESTRING:estring::*@ d",
840         "zzz @ESTRING:test:gép@",
841         NULL
842       },
843       .key = "zzz árvíztűrőtükörfúrógép",
844       .expected_pattern = {"test", "árvíztűrőtükörfúró", NULL},
845     },
846     /* test_string_matches */
847     {
848       .node_to_insert = {"@STRING:string@", NULL},
849       .key = "string hehehe",
850       .expected_pattern = {"string", "string", NULL},
851     },
852     /* test_float_matches */
853     {
854       .node_to_insert = {"@FLOAT:float@", NULL},
855       .key = "12345 hihihi",
856       .expected_pattern = {"float", "12345", NULL},
857     },
858     {
859       .node_to_insert = {"@FLOAT:float@", NULL},
860       .key = "12345hihihi",
861       .expected_pattern = {"float", "12345", NULL},
862     },
863     {
864       .node_to_insert = {"@FLOAT:float@", NULL},
865       .key = "12.345hihihi",
866       .expected_pattern = {"float", "12.345", NULL},
867     },
868     {
869       .node_to_insert = {"@FLOAT:float@", NULL},
870       .key = "12.345.hihihi",
871       .expected_pattern = {"float", "12.345", NULL},
872     },
873     {
874       .node_to_insert = {"@FLOAT:float@", NULL},
875       .key = "12.345.6hihihi",
876       .expected_pattern = {"float", "12.345", NULL},
877     },
878     {
879       .node_to_insert = {"@FLOAT:float@", NULL},
880       .key = "12345.hihihi",
881       .expected_pattern = {"float", "12345.", NULL}
882     },
883     {
884       .node_to_insert = {"@FLOAT:float@", NULL},
885       .key = "-12.345 hihihi",
886       .expected_pattern = {"float", "-12.345", NULL},
887     },
888     {
889       .node_to_insert = {"@FLOAT:float@", NULL},
890       .key = "-12.345e12 hihihi",
891       .expected_pattern = {"float", "-12.345e12", NULL},
892     },
893     {
894       .node_to_insert = {"@FLOAT:float@", NULL},
895       .key = "-12.345e-12 hihihi",
896       .expected_pattern = {"float", "-12.345e-12", NULL},
897     },
898     {
899       .node_to_insert = {"@FLOAT:float@", NULL},
900       .key = "12.345e12 hihihi",
901       .expected_pattern = {"float", "12.345e12", NULL}
902     },
903     {
904       .node_to_insert = {"@FLOAT:float@", NULL},
905       .key = "12.345e-12 hihihi",
906       .expected_pattern = {"float", "12.345e-12", NULL},
907     },
908     {
909       .node_to_insert = {"@FLOAT:float@", NULL},
910       .key = "-12.345E12 hihihi",
911       .expected_pattern = {"float", "-12.345E12", NULL},
912     },
913     {
914       .node_to_insert = {"@FLOAT:float@", NULL},
915       .key = "-12.345E-12 hihihi",
916       .expected_pattern = {"float", "-12.345E-12", NULL},
917     },
918     {
919       .node_to_insert = {"@FLOAT:float@", NULL},
920       .key = "12.345E12 hihihi",
921       .expected_pattern = {"float", "12.345E12", NULL},
922     },
923     {
924       .node_to_insert = {"@FLOAT:float@", NULL},
925       .key = "12.345E-12 hihihi",
926       .expected_pattern = {"float", "12.345E-12", NULL},
927     },
928     {
929       .node_to_insert = {"@FLOAT:float@", NULL},
930       .key = "v12345",
931       .expected_pattern = {NULL},
932     },
933     {
934       .node_to_insert = {"@FLOAT:float@", NULL},
935       .key = "12345.hihihi",
936       .expected_pattern = {"float", "12345.", NULL},
937     },
938     /* test_set_matches */
939     {
940       .node_to_insert = {"@SET:set:  @", NULL},
941       .key = " aaa",
942       .expected_pattern = {"set", " ", NULL},
943     },
944     {
945       .node_to_insert = {"@SET:set:  @", NULL},
946       .key = "  aaa",
947       .expected_pattern = {"set", "  ", NULL},
948     },
949     {
950       .node_to_insert = {"@OPTIONALSET:set:  @", NULL},
951       .key = " aaa",
952       .expected_pattern = {"set", " ", NULL},
953     },
954     {
955       .node_to_insert = {"@OPTIONALSET:set:  @", NULL},
956       .key = "  aaa",
957       .expected_pattern = {"set", "  ", NULL},
958     },
959     {
960       .node_to_insert = {"@OPTIONALSET:set:  @", NULL},
961       .key = "aaa",
962       .expected_pattern = {"set", "", NULL},
963     },
964     /* test_mcaddr_matches */
965     {
966       .node_to_insert = {"@MACADDR:macaddr@", NULL},
967       .key = "82:63:25:93:eb:51.iii",
968       .expected_pattern = {"macaddr", "82:63:25:93:eb:51", NULL},
969     },
970     {
971       .node_to_insert = {"@MACADDR:macaddr@", NULL},
972       .key = "82:63:25:93:EB:51.iii",
973       .expected_pattern = {"macaddr", "82:63:25:93:EB:51", NULL},
974     },
975     /* test_email_matches */
976     {
977       .node_to_insert = {"@EMAIL:email:[<]>@", NULL },
978       .key = "blint@balabit.hu",
979       .expected_pattern = {"email", "blint@balabit.hu", NULL},
980     },
981     {
982       .node_to_insert = {"@EMAIL:email:[<]>@", NULL },
983       .key = "<blint@balabit.hu>",
984       .expected_pattern = {"email", "blint@balabit.hu", NULL},
985     },
986     {
987       .node_to_insert = {"@EMAIL:email:[<]>@", NULL },
988       .key = "[blint@balabit.hu]",
989       .expected_pattern = {"email", "blint@balabit.hu", NULL},
990     },
991     /* test_hostname_matches */
992     {
993       .node_to_insert = {"@HOSTNAME:hostname@", NULL},
994       .key = "www.example.org",
995       .expected_pattern = {"hostname", "www.example.org", NULL},
996     },
997     {
998       .node_to_insert = {"@HOSTNAME:hostname@", NULL},
999       .key = "www.example.org. kkk",
1000       .expected_pattern = {"hostname", "www.example.org.", NULL},
1001     },
1002     /* test_lladdr_matches */
1003     {
1004       .node_to_insert = {"@LLADDR:lladdr6:6@", NULL},
1005       .key = "83:63:25:93:eb:51:aa:bb.iii",
1006       .expected_pattern = {"lladdr6", "83:63:25:93:eb:51", NULL},
1007     },
1008     {
1009       .node_to_insert = {"@LLADDR:lladdr6:6@", NULL},
1010       .key = "83:63:25:93:EB:51:aa:bb.iii",
1011       .expected_pattern = {"lladdr6", "83:63:25:93:EB:51", NULL},
1012     },
1013     /* test_pcre_matches */
1014     {
1015       .node_to_insert = {"jjj @PCRE:regexp:[abc]+@", "jjjj @PCRE:regexp:[abc]+@d foobar", NULL},
1016       .key = "jjj abcabcd",
1017       .expected_pattern = {"regexp", "abcabc", NULL},
1018     },
1019     {
1020       .node_to_insert = {"jjj @PCRE:regexp:[abc]+@", "jjjj @PCRE:regexp:[abc]+@d foobar", NULL},
1021       .key = "jjjj abcabcd foobar",
1022       .expected_pattern = {"regexp", "abcabc", NULL},
1023     },
1024     {
1025       .node_to_insert = {"@PCRE:regexp:(foo|bar)@", NULL},
1026       .key = "foo",
1027       .expected_pattern = {"regexp", "foo", NULL},
1028     },
1029     {
1030       .node_to_insert = {"@PCRE:regexp:(?:foo|bar)@", NULL},
1031       .key = "foo",
1032       .expected_pattern = {"regexp", "foo", NULL},
1033     },
1034     /* test_nlstring_matches */
1035     {
1036       .node_to_insert = {"@NLSTRING:nlstring@\n", NULL},
1037       .key = "foobar\r\nbaz",
1038       .expected_pattern = {"nlstring", "foobar", NULL},
1039     },
1040     {
1041       .node_to_insert = {"@NLSTRING:nlstring@\n", NULL},
1042       .key = "foobar\nbaz",
1043       .expected_pattern = {"nlstring", "foobar", NULL},
1044     },
1045     {
1046       .node_to_insert = {"@NLSTRING:nlstring@\n", NULL},
1047       .key = "\nbaz",
1048       .expected_pattern = {"nlstring", "", NULL},
1049     },
1050     {
1051       .node_to_insert = {"@NLSTRING:nlstring@\n", NULL},
1052       .key = "\r\nbaz",
1053       .expected_pattern = {"nlstring", "", NULL},
1054     }
1055   };
1056   return cr_make_param_array(RadixTestParam, parser_params, G_N_ELEMENTS(parser_params));
1057 }
1058 
1059 ParameterizedTest(RadixTestParam *param, dbparser, test_radix_search_matches, .init = test_setup, .fini = test_teardown)
1060 {
1061   RNode *root = r_new_node("", NULL);
1062 
1063   for (int i=0; param->node_to_insert[i]; i++)
1064     insert_node(root, param->node_to_insert[i]);
1065 
1066   test_search_matches(root, param->key, param->expected_pattern);
1067   r_free_node(root, NULL);
1068 }
1069 
1070 Test(dbparser, test_radix_zorp_log, .init = test_setup, .fini = test_teardown)
1071 {
1072   RNode *root = r_new_node("", NULL);
1073 
1074   /* these are conflicting logs */
1075   insert_node_with_value(root,
1076                          "core.error(2): (svc/@STRING:service:._@:@NUMBER:instance_id@/plug): Connection to remote end failed; local='AF_INET(@IPv4:local_ip@:@NUMBER:local_port@)', remote='AF_INET(@IPv4:remote_ip@:@NUMBER:remote_port@)', error=@QSTRING:errormsg:'@",
1077                          "ZORP");
1078   insert_node_with_value(root,
1079                          "core.error(2): (svc/@STRING:service:._@:@NUMBER:instance_id@/plug): Connection to remote end failed; local=@QSTRING:p:'@, remote=@QSTRING:p:'@, error=@QSTRING:p:'@",
1080                          "ZORP1");
1081   insert_node_with_value(root,
1082                          "Deny@QSTRING:FIREWALL.DENY_PROTO: @src@QSTRING:FIREWALL.DENY_O_INT: :@@IPv4:FIREWALL.DENY_SRCIP@/@NUMBER:FIREWALL.DENY_SRCPORT@ dst",
1083                          "CISCO");
1084   insert_node_with_value(root, "@NUMBER:Seq@, @ESTRING:DateTime:,@@ESTRING:Severity:,@@ESTRING:Comp:,@", "3com");
1085 
1086   test_search_value(root,
1087                     "core.error(2): (svc/intra.servers.alef_SSH_dmz.zajin:111/plug): Connection to remote end failed; local='AF_INET(172.16.0.1:56867)', remote='AF_INET(172.18.0.1:22)', error='No route to host'PAS",
1088                     "ZORP");
1089   test_search_value(root,
1090                     "Deny udp src OUTSIDE:10.0.0.0/1234 dst INSIDE:192.168.0.0/5678 by access-group \"OUTSIDE\" [0xb74026ad, 0x0]",
1091                     "CISCO");
1092 
1093   const gchar *search_pattern[] = {"Seq", "1", "DateTime", "2006-08-22 16:31:39", "Severity", "INFO", "Comp", "BLK", NULL};
1094   test_search_matches(root, "1, 2006-08-22 16:31:39,INFO,BLK,", search_pattern);
1095 
1096   r_free_node(root, NULL);
1097 }
1098