]> git.ipfire.org Git - people/ms/suricata.git/blame - src/detect-engine-uint.c
detect/analyzer: fix mpm display on payload only rules
[people/ms/suricata.git] / src / detect-engine-uint.c
CommitLineData
75ec5283
PA
1/* Copyright (C) 2020 Open Information Security Foundation
2 *
3 * You can copy, redistribute or modify this Program under the terms of
4 * the GNU General Public License version 2 as published by the Free
5 * Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * version 2 along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18/**
19 * \file
20 *
21 * \author Philippe Antoine <p.antoine@catenacyber.fr>
22 *
23 */
24
25#include "suricata-common.h"
26
27#include "util-byte.h"
28#include "detect-parse.h"
29#include "detect-engine-uint.h"
30
31/**
32 * \brief Regex for parsing our options
33 */
34#define PARSE_REGEX "^\\s*([0-9]*)?\\s*([<>=-]+)?\\s*([0-9]+)?\\s*$"
35
4b0085b0 36static DetectParseRegex uint_pcre;
75ec5283
PA
37
38
39int DetectU32Match(const uint32_t parg, const DetectU32Data *du32)
40{
41 switch (du32->mode) {
42 case DETECT_UINT_EQ:
43 if (parg == du32->arg1) {
44 return 1;
45 }
46 return 0;
47 case DETECT_UINT_LT:
48 if (parg < du32->arg1) {
49 return 1;
50 }
51 return 0;
52 case DETECT_UINT_GT:
53 if (parg > du32->arg1) {
54 return 1;
55 }
56 return 0;
57 case DETECT_UINT_RA:
58 if (parg > du32->arg1 && parg < du32->arg2) {
59 return 1;
60 }
61 return 0;
62 default:
63 BUG_ON("unknown mode");
64 }
65 return 0;
66}
67
68
69/**
70 * \brief This function is used to parse u32 options passed via some u32 keyword
71 *
72 * \param u32str Pointer to the user provided u32 options
73 *
74 * \retval DetectU32Data pointer to DetectU32Data on success
75 * \retval NULL on failure
76 */
77
78DetectU32Data *DetectU32Parse (const char *u32str)
79{
5dc21b0e
SS
80 /* We initialize these to please static checkers, these values will
81 either be updated or not used later on */
82 DetectU32Data u32da = {0, 0, 0};
75ec5283
PA
83 DetectU32Data *u32d = NULL;
84 char arg1[16] = "";
85 char arg2[16] = "";
86 char arg3[16] = "";
87
75ec5283
PA
88 int ret = 0, res = 0;
89 int ov[MAX_SUBSTRINGS];
90
4b0085b0 91 ret = DetectParsePcreExec(&uint_pcre, u32str, 0, 0, ov, MAX_SUBSTRINGS);
75ec5283
PA
92 if (ret < 2 || ret > 4) {
93 SCLogError(SC_ERR_PCRE_MATCH, "parse error, ret %" PRId32 "", ret);
94 return NULL;
95 }
96
97 res = pcre_copy_substring((char *) u32str, ov, MAX_SUBSTRINGS, 1, arg1, sizeof(arg1));
98 if (res < 0) {
99 SCLogError(SC_ERR_PCRE_COPY_SUBSTRING, "pcre_copy_substring failed");
100 return NULL;
101 }
102 SCLogDebug("Arg1 \"%s\"", arg1);
103
104 if (ret >= 3) {
105 res = pcre_copy_substring((char *) u32str, ov, MAX_SUBSTRINGS, 2, arg2, sizeof(arg2));
106 if (res < 0) {
107 SCLogError(SC_ERR_PCRE_COPY_SUBSTRING, "pcre_copy_substring failed");
108 return NULL;
109 }
110 SCLogDebug("Arg2 \"%s\"", arg2);
111
112 if (ret >= 4) {
113 res = pcre_copy_substring((char *) u32str, ov, MAX_SUBSTRINGS, 3, arg3, sizeof(arg3));
114 if (res < 0) {
115 SCLogError(SC_ERR_PCRE_COPY_SUBSTRING, "pcre_copy_substring failed");
116 return NULL;
117 }
118 SCLogDebug("Arg3 \"%s\"", arg3);
119 }
120 }
121
122 if (strlen(arg2) > 0) {
123 /*set the values*/
124 switch(arg2[0]) {
125 case '<':
126 case '>':
127 if (strlen(arg3) == 0)
128 return NULL;
129
130 if (ByteExtractStringUint32(&u32da.arg1, 10, strlen(arg3), arg3) < 0) {
131 SCLogError(SC_ERR_BYTE_EXTRACT_FAILED, "ByteExtractStringUint32 failed");
132 return NULL;
133 }
134
135 SCLogDebug("u32 is %"PRIu32"",u32da.arg1);
136 if (strlen(arg1) > 0)
137 return NULL;
138
139 if (arg2[0] == '<') {
140 u32da.mode = DETECT_UINT_LT;
141 } else { // arg2[0] == '>'
142 u32da.mode = DETECT_UINT_GT;
143 }
144 break;
145 case '-':
146 if (strlen(arg1)== 0)
147 return NULL;
148 if (strlen(arg3)== 0)
149 return NULL;
150
151 u32da.mode = DETECT_UINT_RA;
152 if (ByteExtractStringUint32(&u32da.arg1, 10, strlen(arg1), arg1) < 0) {
153 SCLogError(SC_ERR_BYTE_EXTRACT_FAILED, "ByteExtractStringUint32 failed");
154 return NULL;
155 }
156 if (ByteExtractStringUint32(&u32da.arg2, 10, strlen(arg3), arg3) < 0) {
157 SCLogError(SC_ERR_BYTE_EXTRACT_FAILED, "ByteExtractStringUint32 failed");
158 return NULL;
159 }
160
161 SCLogDebug("u32 is %"PRIu32" to %"PRIu32"", u32da.arg1, u32da.arg2);
162 if (u32da.arg1 >= u32da.arg2) {
163 SCLogError(SC_ERR_INVALID_SIGNATURE, "Invalid u32 range. ");
164 return NULL;
165 }
166 break;
167 default:
168 u32da.mode = DETECT_UINT_EQ;
169
170 if (strlen(arg2) > 0 ||
171 strlen(arg3) > 0 ||
172 strlen(arg1) == 0)
173 return NULL;
174
175 if (ByteExtractStringUint32(&u32da.arg1, 10, strlen(arg1), arg1) < 0) {
176 SCLogError(SC_ERR_BYTE_EXTRACT_FAILED, "ByteExtractStringUint32 failed");
177 return NULL;
178 }
179 }
180 } else {
181 u32da.mode = DETECT_UINT_EQ;
182
183 if (strlen(arg3) > 0 ||
184 strlen(arg1) == 0)
185 return NULL;
186
187 if (ByteExtractStringUint32(&u32da.arg1, 10, strlen(arg1), arg1) < 0) {
188 SCLogError(SC_ERR_BYTE_EXTRACT_FAILED, "ByteExtractStringUint32 failed");
189 return NULL;
190 }
191 }
192 u32d = SCCalloc(1, sizeof (DetectU32Data));
193 if (unlikely(u32d == NULL))
194 return NULL;
195 u32d->arg1 = u32da.arg1;
196 u32d->arg2 = u32da.arg2;
197 u32d->mode = u32da.mode;
198
199 return u32d;
200}
201
202void
203PrefilterPacketU32Set(PrefilterPacketHeaderValue *v, void *smctx)
204{
205 const DetectU32Data *a = smctx;
206 v->u8[0] = a->mode;
207 v->u32[1] = a->arg1;
208 v->u32[2] = a->arg2;
209}
210
211bool
212PrefilterPacketU32Compare(PrefilterPacketHeaderValue v, void *smctx)
213{
214 const DetectU32Data *a = smctx;
215 if (v.u8[0] == a->mode &&
216 v.u32[1] == a->arg1 &&
217 v.u32[2] == a->arg2)
218 return true;
219 return false;
220}
221
a5572890 222static bool g_detect_uint_registered = false;
75ec5283 223
a5572890 224void DetectUintRegister(void)
75ec5283 225{
a5572890 226 if (g_detect_uint_registered == false) {
75ec5283 227 // register only once
4b0085b0 228 DetectSetupParseRegexes(PARSE_REGEX, &uint_pcre);
a5572890 229 g_detect_uint_registered = true;
75ec5283
PA
230 }
231}
a5572890
PA
232
233//same as u32 but with u8
234int DetectU8Match(const uint8_t parg, const DetectU8Data *du8)
235{
236 switch (du8->mode) {
237 case DETECT_UINT_EQ:
238 if (parg == du8->arg1) {
239 return 1;
240 }
241 return 0;
242 case DETECT_UINT_LT:
243 if (parg < du8->arg1) {
244 return 1;
245 }
246 return 0;
247 case DETECT_UINT_GT:
248 if (parg > du8->arg1) {
249 return 1;
250 }
251 return 0;
252 case DETECT_UINT_RA:
253 if (parg > du8->arg1 && parg < du8->arg2) {
254 return 1;
255 }
256 return 0;
257 default:
258 BUG_ON("unknown mode");
259 }
260 return 0;
261}
262
263/**
264 * \brief This function is used to parse u8 options passed via some u8 keyword
265 *
266 * \param u8str Pointer to the user provided u8 options
267 *
268 * \retval DetectU8Data pointer to DetectU8Data on success
269 * \retval NULL on failure
270 */
271
272DetectU8Data *DetectU8Parse (const char *u8str)
273{
5dc21b0e
SS
274 /* We initialize these to please static checkers, these values will
275 either be updated or not used later on */
276 DetectU8Data u8da = {0, 0, 0};
a5572890
PA
277 DetectU8Data *u8d = NULL;
278 char arg1[16] = "";
279 char arg2[16] = "";
280 char arg3[16] = "";
281
282 int ret = 0, res = 0;
283 int ov[MAX_SUBSTRINGS];
284
285 ret = DetectParsePcreExec(&uint_pcre, u8str, 0, 0, ov, MAX_SUBSTRINGS);
286 if (ret < 2 || ret > 4) {
287 SCLogError(SC_ERR_PCRE_MATCH, "parse error, ret %" PRId32 "", ret);
288 return NULL;
289 }
290
291 res = pcre_copy_substring((char *) u8str, ov, MAX_SUBSTRINGS, 1, arg1, sizeof(arg1));
292 if (res < 0) {
293 SCLogError(SC_ERR_PCRE_COPY_SUBSTRING, "pcre_copy_substring failed");
294 return NULL;
295 }
296 SCLogDebug("Arg1 \"%s\"", arg1);
297
298 if (ret >= 3) {
299 res = pcre_copy_substring((char *) u8str, ov, MAX_SUBSTRINGS, 2, arg2, sizeof(arg2));
300 if (res < 0) {
301 SCLogError(SC_ERR_PCRE_COPY_SUBSTRING, "pcre_copy_substring failed");
302 return NULL;
303 }
304 SCLogDebug("Arg2 \"%s\"", arg2);
305
306 if (ret >= 4) {
307 res = pcre_copy_substring((char *) u8str, ov, MAX_SUBSTRINGS, 3, arg3, sizeof(arg3));
308 if (res < 0) {
309 SCLogError(SC_ERR_PCRE_COPY_SUBSTRING, "pcre_copy_substring failed");
310 return NULL;
311 }
312 SCLogDebug("Arg3 \"%s\"", arg3);
313 }
314 }
315
316 if (strlen(arg2) > 0) {
317 /*set the values*/
318 switch(arg2[0]) {
319 case '<':
320 case '>':
321 if (StringParseUint8(&u8da.arg1, 10, strlen(arg3), arg3) < 0) {
322 SCLogError(SC_ERR_BYTE_EXTRACT_FAILED, "ByteExtractStringUint8 failed");
323 return NULL;
324 }
325
326 SCLogDebug("u8 is %"PRIu8"",u8da.arg1);
327 if (strlen(arg1) > 0)
328 return NULL;
329
330 if (arg2[0] == '<') {
331 u8da.mode = DETECT_UINT_LT;
332 } else { // arg2[0] == '>'
333 u8da.mode = DETECT_UINT_GT;
334 }
335 break;
336 case '-':
337 u8da.mode = DETECT_UINT_RA;
338 if (StringParseUint8(&u8da.arg1, 10, strlen(arg1), arg1) < 0) {
339 SCLogError(SC_ERR_BYTE_EXTRACT_FAILED, "ByteExtractStringUint8 failed");
340 return NULL;
341 }
342 if (StringParseUint8(&u8da.arg2, 10, strlen(arg3), arg3) < 0) {
343 SCLogError(SC_ERR_BYTE_EXTRACT_FAILED, "ByteExtractStringUint8 failed");
344 return NULL;
345 }
346
347 SCLogDebug("u8 is %"PRIu8" to %"PRIu8"", u8da.arg1, u8da.arg2);
348 if (u8da.arg1 >= u8da.arg2) {
349 SCLogError(SC_ERR_INVALID_SIGNATURE, "Invalid u8 range. ");
350 return NULL;
351 }
352 break;
353 default:
354 u8da.mode = DETECT_UINT_EQ;
355
356 if (strlen(arg2) > 0 ||
357 strlen(arg3) > 0)
358 return NULL;
359
360 if (StringParseUint8(&u8da.arg1, 10, strlen(arg1), arg1) < 0) {
361 SCLogError(SC_ERR_BYTE_EXTRACT_FAILED, "ByteExtractStringUint8 failed");
362 return NULL;
363 }
364 }
365 } else {
366 u8da.mode = DETECT_UINT_EQ;
367
368 if (strlen(arg3) > 0)
369 return NULL;
370
371 if (StringParseUint8(&u8da.arg1, 10, strlen(arg1), arg1) < 0) {
372 SCLogError(SC_ERR_BYTE_EXTRACT_FAILED, "ByteExtractStringUint8 failed");
373 return NULL;
374 }
375 }
376 u8d = SCCalloc(1, sizeof (DetectU8Data));
377 if (unlikely(u8d == NULL))
378 return NULL;
379 u8d->arg1 = u8da.arg1;
380 u8d->arg2 = u8da.arg2;
381 u8d->mode = u8da.mode;
382
383 return u8d;
384}