1 /* Copyright (C) 2014 Trend Micro Inc.
4 * This program is a free software; you can redistribute it
5 * and/or modify it under the terms of the GNU General Public
6 * License (version 2) as published by the FSF - Free Software
13 #include "../os_regex/os_regex.h"
14 #include "../os_regex/os_regex_internal.h"
16 Suite *test_suite(void);
19 START_TEST(test_success_match1)
23 const char *tests[][3] = {
29 {"test", "testa", ""},
30 {"test", "testest", ""},
31 {"lalaila", "lalalalaila", ""},
32 {"abc|cde", "cde", ""},
33 {"^aa|ee|ii|oo|uu", "dfgdsii", ""},
38 {"a|E", "abcdef", ""},
39 {"daniel", "daniel", ""},
40 {"DANIeL", "daNIel", ""},
41 {"^abc ", "abc ", ""},
42 {"ddd|eee|fff|ggg|ggg|hhh|iii", "iii", ""},
43 {"kwo|fe|fw|wfW|edW|dwDF|WdW|dw|d|^la", "la", ""},
47 {"c$", "lalalalac", ""},
48 {"^bin$|^shell$", "bin", ""},
49 {"^bin$|^shell$", "shell", ""},
50 {"^bin$|^shell$|^ftp$", "shell", ""},
51 {"^bin$|^shell$|^ftp$", "ftp", ""},
55 for (i = 0; tests[i][0] != NULL ; i++) {
56 ck_assert_msg(OS_Match2(tests[i][0], tests[i][1]),
57 "%s should have OS_Match2 true with %s: Ref: %s",
58 tests[i][0], tests[i][1], tests[i][1]);
63 START_TEST(test_fail_match1)
67 const char *tests[][3] = {
73 {"abbbbbbbb", "abbbbbbb", ""},
74 {"a|b|c| ", "def", ""},
75 {"lala$", "lalalalalal", ""},
77 {"zzzz$", "zzzzzzzzzzzz ", ""},
78 {"^bin$|^shell$", "bina", ""},
79 {"^bin$|^shell$", "shella", ""},
80 {"^bin$|^shell$", "ashell", ""},
84 for (i = 0; tests[i][0] != NULL ; i++) {
85 ck_assert_msg(!OS_Match2(tests[i][0], tests[i][1]),
86 "%s should have OS_Match2 false with %s: Ref: %s",
87 tests[i][0], tests[i][1], tests[i][2]);
92 START_TEST(test_success_regex1)
97 * Please note that all strings are \ escaped
99 const char *tests[][3] = {
101 {"abcd", "abcd", ""},
105 {"test", "testa", ""},
106 {"test", "testest", ""},
107 {"lalaila", "lalalalaila", ""},
108 {"abc|cde", "cde", ""},
109 {"^aa|ee|ii|oo|uu", "dfgdsii", ""},
114 {"a|E", "abcdef", ""},
115 {"daniel", "daniel", ""},
116 {"DANIeL", "daNIel", ""},
117 {"^abc ", "abc ", ""},
118 {"ddd|eee|fff|ggg|ggg|hhh|iii", "iii", ""},
119 {"kwo|fe|fw|wfW|edW|dwDF|WdW|dw|d|^la", "la", ""},
123 {"c$", "lalalalac", ""},
124 {"^bin$|^shell$", "bin", ""},
125 {"^bin$|^shell$", "shell", ""},
126 {"^bin$|^shell$|^ftp$", "shell", ""},
127 {"^bin$|^shell$|^ftp$", "ftp", ""},
128 {"\\s+123", " 123", ""},
129 {"\\s*123", "123", ""},
130 {"\\s123", " 123", ""},
131 {"\\w+\\s+\\w+", "a 1", ""},
132 {"\\w+\\d+\\w+\\s+", "ab12fb12fd12 ", ""},
133 {"^\\s*\\w\\s*\\w+", "a l a a", ""},
134 {"\\w+\\s+\\w+\\d+\\s$", "a aa11 ", ""},
135 {"^su\\S*: BAD su", "su: BAD SU dcid to root on /dev/ttyp0", ""},
136 {"^su\\s*: BAD su", "su: BAD SU dcid to root on /dev/ttyp0", ""},
137 {"^abc\\sabc", "abc abcd", ""},
138 {"^abc\\s\\s*abc", "abc abcd", ""},
139 {"^\\s+\\sl", " lala", ""},
140 {"^\\s*\\sl", " lala", ""},
141 {"^\\s\\s+l", " lala", ""},
142 {"^\\s+\\s l", " lala", ""},
143 {"^\\s*\\s lal\\w$", " lala", ""},
144 {"test123test\\d+$", "test123test123", ""},
145 {"^kernel: \\S+ \\.+ SRC=\\S+ DST=\\S+ \\.+ PROTO=\\w+ SPT=\\d+ DPT=\\d+ ", "kernel: IPTABLE IN=eth0 OUT= MAC=ff:ff:ff:ff:ff:ff:00:03:93:db:2e:b4:08:00 SRC=10.4.11.40 DST=255.255.255.255 LEN=180 TOS=0x00 PREC=0x00 TTL=64 ID=4753 PROTO=UDP SPT=49320 DPT=2222 LEN=160", ""},
146 {"test (\\w+)la", "test abclala", ""},
147 {"(\\w+) (\\w+)", "wofl wofl", ""},
148 {"^\\S+ [(\\d+:\\d+:\\d+)] \\.+ (\\d+.\\d+.\\d+.\\d+)\\p*\\d* -> (\\d+.\\d+.\\d+.\\d+)\\p*", "snort: [1:469:3] ICMP PING NMAP [Classification: Attempted Information Leak] [Priority: 2]: {ICMP} 10.4.12.26 -> 10.4.10.231", ""},
149 {"^\\S+ [(\\d+:\\d+:\\d+)] \\.+ (\\d+.\\d+.\\d+.\\d+)\\p*\\d* -> (\\d+.\\d+.\\d+.\\d+)\\p*", "snort: [1:408:5] ICMP Echo Reply [Classification: Misc Activity] [Priority: 3]: {ICMP} 10.4.10.231 -> 10.4.12.26", ""},
150 {"^\\S+ [(\\d+:\\d+:\\d+)] \\.+ (\\d+.\\d+.\\d+.\\d+)\\p*\\d* -> (\\d+.\\d+.\\d+.\\d+)\\p*", "snort: [1:1420:11] SNMP trap tcp [Classification: Attempted Information Leak] [Priority: 2]: {TCP} 10.4.12.26:37020 -> 10.4.10.231:162", ""},
151 {"^\\S+ [(\\d+:\\d+:\\d+)] \\.+ (\\d+.\\d+.\\d+.\\d+)\\p*\\d* -> (\\d+.\\d+.\\d+.\\d+)\\p*", "snort: [1:1420:11] SNMP trap tcp [Classification: Attempted Information Leak] [Priority: 2]: {TCP} 10.4.12.26:37021 -> 10.4.10.231:162", ""},
152 {"^\\S+ [(\\d+:\\d+:\\d+)] \\.+ (\\d+.\\d+.\\d+.\\d+)\\p*\\d* -> (\\d+.\\d+.\\d+.\\d+)\\p*", "snort: [1:590:12] RPC portmap ypserv request UDP [Classification: Decode of an RPC Query] [Priority: 2]: {UDP} 10.4.11.94:669 -> 10.4.3.20:111", ""},
153 {"^\\S+ [(\\d+:\\d+:\\d+)] \\.+ (\\d+.\\d+.\\d+.\\d+)\\p*\\d* -> (\\d+.\\d+.\\d+.\\d+)\\p*", "snort: [1:590:12] RPC portmap ypserv request UDP [Classification: Decode of an RPC Query] [Priority: 2]: {UDP} 10.4.11.94:670 -> 10.4.3.20:111", ""},
154 {"^\\S+ [(\\d+:\\d+:\\d+)] \\.+ (\\d+.\\d+.\\d+.\\d+)\\p*\\d* -> (\\d+.\\d+.\\d+.\\d+)\\p*", "snort: [1:1421:11] SNMP AgentX/tcp request [Classification: Attempted Information Leak] [Priority: 2]: {TCP} 10.4.12.26:37020 -> 10.4.10.231:705", ""},
158 for (i = 0; tests[i][0] != NULL ; i++) {
159 ck_assert_msg(OS_Regex(tests[i][0], tests[i][1]),
160 "%s should have OS_Regex true with %s: Ref: %s",
161 tests[i][0], tests[i][1], tests[i][2]);
166 START_TEST(test_fail_regex1)
171 * Please note that all strings are \ escaped
173 const char *tests[][3] = {
179 {"abbbbbbbb", "abbbbbbb", ""},
180 {"a|b|c| ", "def", ""},
181 {"lala$", "lalalalalal", ""},
183 {"zzzz$", "zzzzzzzzzzzz ", ""},
184 {"^bin$|^shell$", "bina", ""},
185 {"^bin$|^shell$", "shella", ""},
186 {"^bin$|^shell$", "ashell", ""},
187 {"\\w+\\s+\\w+\\d+\\s$", "a aa11 ", ""},
188 {"^\\s+\\s l", " lala", ""},
189 {"test123test\\d+", "test123test", ""},
190 {"test123test\\d+$", "test123test", ""},
191 {"(lalala", "lalala", ""},
192 {"test123(\\d)", "test123a", ""},
193 {"\\(test)", "test", ""},
194 {"(\\w+)(\\d+)", "1 1", ""},
198 for (i = 0; tests[i][0] != NULL ; i++) {
199 ck_assert_msg(!OS_Regex(tests[i][0], tests[i][1]),
200 "%s should have OS_Regex false with %s: Ref: %s",
201 tests[i][0], tests[i][1], tests[i][2]);
206 START_TEST(test_success_wordmatch)
211 * Please note that all strings are \ escaped
213 const char *tests[][2] = {
214 { "test", "this is a test" },
215 { "test", "thistestiswithoutspaces" },
216 { "test|not", "test" },
217 { "test|not", "not" },
218 { "^test", "test on start" },
222 for (i = 0; tests[i][0] != NULL ; i++) {
223 ck_assert_msg(OS_WordMatch(tests[i][0], tests[i][1]),
224 "%s should match positive with %s by OS_WordMatch",
225 tests[i][0], tests[i][1]);
231 START_TEST(test_fail_wordmatch)
236 * Please note that all strings are \ escaped
238 const char *tests[][2] = {
239 { "-test", "this is a test" },
241 { "test|not", "negative" },
243 { "^test", "starttest" },
247 for (i = 0; tests[i][0] != NULL ; i++) {
248 ck_assert_msg(!OS_WordMatch(tests[i][0], tests[i][1]),
249 "%s should not match positive with %s by OS_WordMatch",
250 tests[i][0], tests[i][1]);
256 START_TEST(test_success_strisnum)
261 * Please note that all strings are \ escaped
263 const char *tests[] = {
269 for (i = 0; tests[i] != NULL ; i++) {
270 ck_assert_msg(OS_StrIsNum(tests[i]),
271 "%s should match positive by OS_StrIsNum",
278 START_TEST(test_fail_strisnum)
283 * Please note that all strings are \ escaped
285 const char *tests[] = {
293 for (i = 0; tests[i] != NULL ; i++) {
294 ck_assert_msg(!OS_StrIsNum(tests[i]),
295 "%s should not match positive by OS_StrIsNum",
302 START_TEST(test_strhowclosedmatch)
307 * Please note that all strings are \ escaped
309 const char *tests[][3] = {
310 { "test", "test1234", "4" },
311 { "test1234", "test", "4" },
312 { "test", "test", "4" },
318 for (i = 0; tests[i][0] != NULL ; i++) {
319 ck_assert_uint_eq(OS_StrHowClosedMatch(tests[i][0], tests[i][1])
320 , (unsigned) atoi(tests[i][2]));
326 START_TEST(test_strbreak)
331 * Please note that all strings are \ escaped
333 const char *tests[][15] = {
334 { "X", "testX1234", "4", "test", "1234", NULL},
335 { "X", "XtestX1234X", "4", "", "test", "1234", "", NULL},
336 { "Y", "testX1234", "4", "testX1234", NULL},
337 { "X", "testXX1234", "4", "test", "", "1234", NULL},
338 { "X", "testX1234", "1", "testX1234", NULL},
339 { "X", "testX1234X5678", "2", "test", "1234X5678", NULL},
340 { "X", "testX1234", "0", NULL},
344 for (i = 0; tests[i][0] != NULL; i++) {
345 char **result = OS_StrBreak(tests[i][0][0], tests[i][1], (unsigned) atoi(tests[i][2]));
348 if (tests[i][j] == NULL) {
349 ck_assert_ptr_eq(result, NULL);
354 for (k = 0; tests[i][j] != NULL; j++, k++) {
355 ck_assert_ptr_ne(result[k], NULL);
356 ck_assert_str_eq(result[k], tests[i][j]);
358 ck_assert_ptr_eq(result[k], NULL);
370 START_TEST(test_regexextraction)
375 * Please note that all strings are \ escaped
377 const char *tests[][15] = {
378 { "123(\\w+\\s+)abc", "123sdf abc", "sdf ", NULL},
379 { "123(\\w+\\s+)abc", "abc123sdf abc", "sdf ", NULL},
380 { "123 (\\d+.\\d.\\d.\\d\\d*\\d*)", "123 45.6.5.567", "45.6.5.567", NULL},
381 { "from (\\S*\\d+.\\d+.\\d+.\\d\\d*\\d*)", "sshd[21576]: Illegal user web14 from ::ffff:212.227.60.55", "::ffff:212.227.60.55", NULL},
382 { "^sshd[\\d+]: Accepted \\S+ for (\\S+) from (\\S+) port ", "sshd[21405]: Accepted password for root from 192.1.1.1 port 6023", "root", "192.1.1.1", NULL},
383 { ": \\((\\S+)@(\\S+)\\) [", "pure-ftpd: (?@enigma.lab.ossec.net) [INFO] New connection from enigma.lab.ossec.net", "?", "enigma.lab.ossec.net", NULL},
387 for (i = 0; tests[i][0] != NULL; i++) {
389 ck_assert_int_eq(OSRegex_Compile(tests[i][0], ®, OS_RETURN_SUBSTRING), 1);
390 ck_assert_ptr_ne((void *)OSRegex_Execute(tests[i][1], ®), NULL);
394 char **result = reg.sub_strings;
398 for (j = 2, k = 0; tests[i][j] != NULL; j++, k++) {
399 ck_assert_ptr_ne(result[k], NULL);
400 ck_assert_str_eq(result[k], tests[i][j]);
402 ck_assert_ptr_eq(result[k], NULL);
404 OSRegex_FreePattern(®);
409 START_TEST(test_hostnamemap)
411 unsigned char test = 0;
414 if ((test >= 48 && test <= 57) // 0-9
415 || (test >= 65 && test <= 90) // A-Z
416 || (test >= 97 && test <= 122) // a-z
417 || test == '(' || test == ')' || test == '-'
418 || test == '.' || test == '@' || test == '/'
420 ck_assert_msg(isValidChar(test) == 1, "char %d should be a valid hostname char", test);
422 ck_assert_msg(isValidChar(test) != 1, "char %d should not be a valid hostname char", test);
436 START_TEST(test_caseinsensitivecharmap)
438 unsigned char test = 0;
441 if (test >= 65 && test <= 90) { // A-Z
442 ck_assert_msg(charmap[test] == test + 32, "char %d should resolve to lowercase version %d and not to %d", test, test + 32, charmap[test]);
444 ck_assert_msg(charmap[test] == test, "char %d should resolve to itself and not to %d", test, charmap[test]);
458 START_TEST(test_regexmap_digit)
460 unsigned char test = 0;
463 if (test >= '0' && test <= '9') {
464 ck_assert_msg(regexmap[1][test] == 1, "char %d should match", test);
466 ck_assert_msg(regexmap[1][test] != 1, "char %d should not match", test);
479 START_TEST(test_regexmap_word)
481 unsigned char test = 0;
484 if ((test >= 'a' && test <= 'z')
485 || (test >= 'A' && test <= 'Z')
486 || (test >= '0' && test <= '9')
487 || test == '-' || test == '@'
489 ck_assert_msg(regexmap[2][test] == 1, "char %d should match", test);
491 ck_assert_msg(regexmap[2][test] != 1, "char %d should not match", test);
504 START_TEST(test_regexmap_space)
506 unsigned char test = 0;
510 ck_assert_msg(regexmap[3][test] == 1, "char %d should match", test);
512 ck_assert_msg(regexmap[3][test] != 1, "char %d should not match", test);
525 START_TEST(test_regexmap_punctuation)
527 unsigned char test = 0;
530 if (test == '<' || test == '>' || test == '!' || test == '?'
531 || test == '"' || test == '\'' || test == '#'
532 || test == '$' || test == '%' || test == '&'
533 || test == '(' || test == ')' || test == '+'
534 || test == '*' || test == ',' || test == '-'
535 || test == '-' || test == ':' || test == '|'
536 || test == '.' || test == ';' || test == '='
537 || test == '[' || test == ']' || test == '{'
539 ck_assert_msg(regexmap[4][test] == 1, "char %d should match", test);
541 ck_assert_msg(regexmap[4][test] != 1, "char %d should not match", test);
554 START_TEST(test_regexmap_lparenthesis)
556 unsigned char test = 0;
560 ck_assert_msg(regexmap[5][test] == 1, "char %d should match", test);
562 ck_assert_msg(regexmap[5][test] != 1, "char %d should not match", test);
575 START_TEST(test_regexmap_rparenthesis)
577 unsigned char test = 0;
581 ck_assert_msg(regexmap[6][test] == 1, "char %d should match", test);
583 ck_assert_msg(regexmap[6][test] != 1, "char %d should not match", test);
596 START_TEST(test_regexmap_backslash)
598 unsigned char test = 0;
602 ck_assert_msg(regexmap[7][test] == 1, "char %d should match", test);
604 ck_assert_msg(regexmap[7][test] != 1, "char %d should not match", test);
618 START_TEST(test_regexmap_nondigit)
620 unsigned char test = 0;
623 if (!(test >= '0' && test <= '9')) {
624 ck_assert_msg(regexmap[8][test] == 1, "char %d should match", test);
626 ck_assert_msg(regexmap[8][test] != 1, "char %d should not match", test);
639 START_TEST(test_regexmap_nonword)
641 unsigned char test = 0;
644 if (!((test >= 'a' && test <= 'z')
645 || (test >= 'A' && test <= 'Z')
646 || (test >= '0' && test <= '9')
647 || test == '-' || test == '@'
649 ck_assert_msg(regexmap[9][test] == 1, "char %d should match", test);
651 ck_assert_msg(regexmap[9][test] != 1, "char %d should not match", test);
664 START_TEST(test_regexmap_nonspace)
666 unsigned char test = 0;
670 ck_assert_msg(regexmap[10][test] == 1, "char %d should match", test);
672 ck_assert_msg(regexmap[10][test] != 1, "char %d should not match", test);
685 START_TEST(test_regexmap_all)
687 unsigned char test = 0;
690 ck_assert_msg(regexmap[11][test] == 1, "char %d should match", test);
702 START_TEST(test_regexmap_tab)
704 unsigned char test = 0;
708 ck_assert_msg(regexmap[12][test] == 1, "char %d should match", test);
710 ck_assert_msg(regexmap[12][test] != 1, "char %d should not match", test);
723 START_TEST(test_regexmap_dollar)
725 unsigned char test = 0;
729 ck_assert_msg(regexmap[13][test] == 1, "char %d should match", test);
731 ck_assert_msg(regexmap[13][test] != 1, "char %d should not match", test);
744 START_TEST(test_regexmap_or)
746 unsigned char test = 0;
750 ck_assert_msg(regexmap[14][test] == 1, "char %d should match", test);
752 ck_assert_msg(regexmap[14][test] != 1, "char %d should not match", test);
765 START_TEST(test_regexmap_lt)
767 unsigned char test = 0;
771 ck_assert_msg(regexmap[15][test] == 1, "char %d should match", test);
773 ck_assert_msg(regexmap[15][test] != 1, "char %d should not match", test);
786 START_TEST(test_success_strstartswith)
791 * Please note that all strings are \ escaped
793 const char *tests[][2] = {
794 { "test1234", "test" },
801 for (i = 0; tests[i][0] != NULL ; i++) {
802 ck_assert_msg(OS_StrStartsWith(tests[i][0], tests[i][1]),
803 "%s should match positive with %s by OS_StrStartsWith",
804 tests[i][0], tests[i][1]);
810 START_TEST(test_fail_strstartswith)
815 * Please note that all strings are \ escaped
817 const char *tests[][2] = {
818 { "test", "test1234" },
823 for (i = 0; tests[i][0] != NULL ; i++) {
824 ck_assert_msg(!OS_StrStartsWith(tests[i][0], tests[i][1]),
825 "%s should not match positive with %s by OS_StrStartsWith",
826 tests[i][0], tests[i][1]);
832 Suite *test_suite(void)
834 Suite *s = suite_create("os_regex");
837 TCase *tc_match = tcase_create("Match");
838 TCase *tc_regex = tcase_create("Regex");
839 TCase *tc_wordmatch = tcase_create("WordMatch");
840 TCase *tc_strisnum = tcase_create("StrIsNum");
841 TCase *tc_strhowclosedmatch = tcase_create("StrHowClosedMatch");
842 TCase *tc_strbreak = tcase_create("StrBreak");
843 TCase *tc_regexextraction = tcase_create("RegexExtraction");
844 TCase *tc_hostnamemap = tcase_create("HostnameMap");
845 TCase *tc_caseinsensitivecharmap = tcase_create("CaseInsensitiveCharmap");
846 TCase *tc_regexmap = tcase_create("RegexMap");
847 TCase *tc_strstartswith = tcase_create("StrStartsWith");
849 tcase_add_test(tc_match, test_success_match1);
850 tcase_add_test(tc_match, test_fail_match1);
852 tcase_add_test(tc_regex, test_success_regex1);
853 tcase_add_test(tc_regex, test_fail_regex1);
855 tcase_add_test(tc_wordmatch, test_success_wordmatch);
856 tcase_add_test(tc_wordmatch, test_fail_wordmatch);
858 tcase_add_test(tc_strisnum, test_success_strisnum);
859 tcase_add_test(tc_strisnum, test_fail_strisnum);
861 tcase_add_test(tc_strhowclosedmatch, test_strhowclosedmatch);
863 tcase_add_test(tc_strbreak, test_strbreak);
865 tcase_add_test(tc_regexextraction, test_regexextraction);
867 tcase_add_test(tc_hostnamemap, test_hostnamemap);
869 tcase_add_test(tc_caseinsensitivecharmap, test_caseinsensitivecharmap);
871 tcase_add_test(tc_regexmap, test_regexmap_digit);
872 tcase_add_test(tc_regexmap, test_regexmap_word);
873 tcase_add_test(tc_regexmap, test_regexmap_space);
874 tcase_add_test(tc_regexmap, test_regexmap_punctuation);
875 tcase_add_test(tc_regexmap, test_regexmap_lparenthesis);
876 tcase_add_test(tc_regexmap, test_regexmap_rparenthesis);
877 tcase_add_test(tc_regexmap, test_regexmap_backslash);
878 tcase_add_test(tc_regexmap, test_regexmap_nondigit);
879 tcase_add_test(tc_regexmap, test_regexmap_nonword);
880 tcase_add_test(tc_regexmap, test_regexmap_nonspace);
881 tcase_add_test(tc_regexmap, test_regexmap_all);
882 tcase_add_test(tc_regexmap, test_regexmap_tab);
883 tcase_add_test(tc_regexmap, test_regexmap_dollar);
884 tcase_add_test(tc_regexmap, test_regexmap_or);
885 tcase_add_test(tc_regexmap, test_regexmap_lt);
887 tcase_add_test(tc_strstartswith, test_success_strstartswith);
888 tcase_add_test(tc_strstartswith, test_fail_strstartswith);
890 suite_add_tcase(s, tc_match);
891 suite_add_tcase(s, tc_regex);
892 suite_add_tcase(s, tc_wordmatch);
893 suite_add_tcase(s, tc_strisnum);
894 suite_add_tcase(s, tc_strhowclosedmatch);
895 suite_add_tcase(s, tc_strbreak);
896 suite_add_tcase(s, tc_regexextraction);
897 suite_add_tcase(s, tc_hostnamemap);
898 suite_add_tcase(s, tc_caseinsensitivecharmap);
899 suite_add_tcase(s, tc_regexmap);
900 suite_add_tcase(s, tc_strstartswith);
907 Suite *s = test_suite();
908 SRunner *sr = srunner_create(s);
909 srunner_run_all(sr, CK_NORMAL);
910 int number_failed = srunner_ntests_failed(sr);
913 return ((number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE);