9 #define OSREGEX_TO_PCRE2_FIX \
10 ("(?<!\\\\)" /* not preceed by a '\' */ \
11 "([+*]) \\?" /* '+' or '*' (capture group 1) followed by '?' */ \
12 "(" /* start capture group 2 the */ \
13 "\\)*" /* Any number of closing parenthese ')' */ \
14 "(?: [|$] | $)" /* Either '|', '$', or end of string */ \
15 ")" /* end of capture group 2 */ \
18 /* determine the length of an array */
19 #define ARRAY_LENGTH(_A) (sizeof(_A) / sizeof(_A[0]))
21 /* definition of a remplacement pattern */
22 typedef struct _replacement_pattern {
27 } replacement_pattern;
29 /* macro to define an entry in a replacement map */
30 #define REPLACEMENT_ENTRY(_old, _new) \
31 { .old = _old, .new = _new, .new_sz = sizeof(_new) - 1, .old_sz = sizeof(_old) - 1 }
33 /* replacement map for ossec regex to perl6 expressions */
34 const replacement_pattern _replacement_map_regex[] = {
35 REPLACEMENT_ENTRY("\\p", "[()*+,.:;\\<=>?\\[\\]!\"'#%&$|{}-]"),
36 REPLACEMENT_ENTRY("\\s", "[ ]"),
37 REPLACEMENT_ENTRY("\\W", "[^A-Za-z0-9@_-]"),
38 REPLACEMENT_ENTRY("\\w", "[A-Za-z0-9@_-]"),
39 REPLACEMENT_ENTRY("\\d", "[0-9]"),
40 REPLACEMENT_ENTRY("\\D", "[^0-9]"),
41 REPLACEMENT_ENTRY("\\S", "[^ ]"),
42 REPLACEMENT_ENTRY("\\.", "(?s:.)"),
43 REPLACEMENT_ENTRY("$", "(?!\\n)$"),
44 REPLACEMENT_ENTRY(".", "\\."),
45 REPLACEMENT_ENTRY("[", "\\["),
46 REPLACEMENT_ENTRY("]", "\\]"),
47 REPLACEMENT_ENTRY("{", "\\{"),
48 REPLACEMENT_ENTRY("}", "\\}"),
49 REPLACEMENT_ENTRY("+", "\\+"),
50 REPLACEMENT_ENTRY("?", "\\?"),
51 REPLACEMENT_ENTRY("*", "\\*")};
53 /* replacement map for match expressions */
54 const replacement_pattern _replacement_map_match[] = {
55 REPLACEMENT_ENTRY(".", "\\."), REPLACEMENT_ENTRY("[", "\\["), REPLACEMENT_ENTRY("]", "\\]"),
56 REPLACEMENT_ENTRY("{", "\\{"), REPLACEMENT_ENTRY("}", "\\}"), REPLACEMENT_ENTRY("+", "\\+"),
57 REPLACEMENT_ENTRY("?", "\\?"), REPLACEMENT_ENTRY("*", "\\*"), REPLACEMENT_ENTRY("(", "\\("),
58 REPLACEMENT_ENTRY(")", "\\)"), REPLACEMENT_ENTRY("\\", "\\\\")};
60 int OSRegex_ConvertRegex(const char *pattern, char **converted_pattern_ptr);
61 int OSRegex_ConvertMatch(const char *pattern, char **converted_pattern_ptr);
63 int OSRegex_Convert(const char *pattern, char **converted_pattern_ptr, uint32_t map)
65 *converted_pattern_ptr = NULL;
67 case OS_CONVERT_REGEX:
68 return OSRegex_ConvertRegex(pattern, converted_pattern_ptr);
69 case OS_CONVERT_MATCH:
70 return OSRegex_ConvertMatch(pattern, converted_pattern_ptr);
77 int OSRegex_ConvertRegex(const char *pattern, char **converted_pattern_ptr)
79 char *converted_pattern = NULL;
80 size_t converted_pattern_size = 0UL;
81 size_t converted_pattern_offset = 0UL;
82 size_t pattern_offset = 0UL;
83 size_t pattern_size = strlen(pattern);
84 const char *replacement = NULL;
85 size_t replacement_size = 0UL;
86 const size_t map_size = ARRAY_LENGTH(_replacement_map_regex);
87 const replacement_pattern *map = _replacement_map_regex;
90 const char *star_ungreedy = "*?";
91 const char *plus_ungreedy = "+?";
92 pcre2_code *preg = NULL;
94 PCRE2_SIZE erroroffset = 0;
95 PCRE2_UCHAR *final_converted_pattern = NULL;
96 PCRE2_SIZE final_converted_pattern_len = 0;
98 for (pattern_offset = 0UL; pattern_offset < pattern_size; pattern_offset++) {
99 p = &pattern[pattern_offset];
101 replacement_size = 0UL;
103 if (pattern_offset >= 2 && pattern[pattern_offset - 2] == '\\') {
106 replacement = star_ungreedy;
107 replacement_size = 2UL;
110 replacement = plus_ungreedy;
111 replacement_size = 2UL;
119 for (i = 0; i < map_size; i++) {
120 if (map[i].old_sz + pattern_offset <= pattern_size &&
121 strncmp(map[i].old, p, map[i].old_sz) == 0) {
122 replacement = map[i].new;
123 replacement_size = map[i].new_sz;
124 pattern_offset += map[i].old_sz - 1;
131 /* If it is a special class for ossec */
132 if (p[0] == '\\' && pattern_offset + 1 < pattern_size) {
145 /* case '>': Only the '<' can be escaped, possibly to not interfer
146 * with XML parsing if nothing to backslash we copy the two current
147 * input pattern characters and move the cursor to the next next char
151 replacement_size = 2UL;
154 goto conversion_error;
158 replacement_size = 1UL;
162 if (converted_pattern_offset + replacement_size >= converted_pattern_size) {
163 converted_pattern_size += OS_PATTERN_MAXSIZE;
164 converted_pattern = (char *)realloc(converted_pattern, converted_pattern_size);
165 if (!converted_pattern) {
170 converted_pattern_offset += sprintf(&converted_pattern[converted_pattern_offset], "%.*s",
171 (int)replacement_size, replacement);
175 * We should remove the '?' for non-greediness when it is the last one => m/([+*])\?(\)*[|]?)$/
176 * Because Ossec is only greedy with the last occurencies modifier
178 preg = pcre2_compile((PCRE2_SPTR)OSREGEX_TO_PCRE2_FIX, PCRE2_ZERO_TERMINATED, PCRE2_EXTENDED,
179 &error, &erroroffset, NULL);
181 goto conversion_error;
183 final_converted_pattern_len = converted_pattern_size;
184 final_converted_pattern = malloc(final_converted_pattern_len);
185 if (pcre2_substitute(preg, (PCRE2_SPTR)converted_pattern, converted_pattern_offset, 0,
186 PCRE2_SUBSTITUTE_GLOBAL, NULL, NULL, (PCRE2_SPTR) "$1$2", 4,
187 final_converted_pattern, &final_converted_pattern_len) > 0) {
188 free(converted_pattern);
189 *converted_pattern_ptr = (char *)final_converted_pattern;
191 free(final_converted_pattern);
192 *converted_pattern_ptr = converted_pattern;
194 pcre2_code_free(preg);
199 if (converted_pattern) {
200 free(converted_pattern);
204 pcre2_code_free(preg);
210 int OSRegex_ConvertMatch(const char *pattern, char **converted_pattern_ptr)
212 char *converted_pattern = NULL;
213 size_t converted_pattern_size = 0UL;
214 size_t converted_pattern_offset = 0UL;
215 size_t pattern_offset = 0UL;
216 size_t pattern_size = strlen(pattern);
217 const char *replacement = NULL;
218 size_t replacement_size = 0UL;
219 const size_t map_size = ARRAY_LENGTH(_replacement_map_match);
220 const replacement_pattern *map = _replacement_map_match;
222 const char *p = NULL;
224 for (pattern_offset = 0UL; pattern_offset < pattern_size; pattern_offset++) {
225 p = &pattern[pattern_offset];
227 replacement_size = 0UL;
228 for (i = 0; i < map_size; i++) {
229 if (map[i].old_sz + pattern_offset <= pattern_size &&
230 strncmp(map[i].old, p, map[i].old_sz) == 0) {
231 replacement = map[i].new;
232 replacement_size = map[i].new_sz;
233 pattern_offset += map[i].old_sz - 1;
239 replacement_size = 1UL;
242 if (converted_pattern_offset + replacement_size >= converted_pattern_size) {
243 converted_pattern_size += OS_PATTERN_MAXSIZE;
244 converted_pattern = (char *)realloc(converted_pattern, converted_pattern_size);
245 if (!converted_pattern) {
250 converted_pattern_offset += sprintf(&converted_pattern[converted_pattern_offset], "%.*s",
251 (int)replacement_size, replacement);
254 *converted_pattern_ptr = converted_pattern;