1 /* Copyright (C) 2020 Open Information Security Foundation
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
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.
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
21 * \author Philippe Antoine <p.antoine@catenacyber.fr>
25 #include "suricata-common.h"
27 #include "util-byte.h"
28 #include "detect-parse.h"
29 #include "detect-engine-uint.h"
32 * \brief Regex for parsing our options
34 #define PARSE_REGEX "^\\s*([0-9]*)?\\s*([<>=-]+)?\\s*([0-9]+)?\\s*$"
36 static DetectParseRegex uint_pcre
;
39 int DetectU32Match(const uint32_t parg
, const DetectU32Data
*du32
)
43 if (parg
== du32
->arg1
) {
48 if (parg
< du32
->arg1
) {
53 if (parg
<= du32
->arg1
) {
58 if (parg
> du32
->arg1
) {
63 if (parg
>= du32
->arg1
) {
68 if (parg
> du32
->arg1
&& parg
< du32
->arg2
) {
73 BUG_ON("unknown mode");
80 * \brief This function is used to parse u32 options passed via some u32 keyword
82 * \param u32str Pointer to the user provided u32 options
84 * \retval DetectU32Data pointer to DetectU32Data on success
85 * \retval NULL on failure
88 DetectU32Data
*DetectU32Parse (const char *u32str
)
90 /* We initialize these to please static checkers, these values will
91 either be updated or not used later on */
92 DetectU32Data u32da
= {0, 0, 0};
93 DetectU32Data
*u32d
= NULL
;
101 ret
= DetectParsePcreExec(&uint_pcre
, u32str
, 0, 0);
102 if (ret
< 2 || ret
> 4) {
103 SCLogError(SC_ERR_PCRE_MATCH
, "parse error, ret %" PRId32
"", ret
);
107 pcre2len
= sizeof(arg1
);
108 res
= pcre2_substring_copy_bynumber(uint_pcre
.match
, 1, (PCRE2_UCHAR8
*)arg1
, &pcre2len
);
110 SCLogError(SC_ERR_PCRE_COPY_SUBSTRING
, "pcre2_substring_copy_bynumber failed");
113 SCLogDebug("Arg1 \"%s\"", arg1
);
116 pcre2len
= sizeof(arg2
);
117 res
= pcre2_substring_copy_bynumber(uint_pcre
.match
, 2, (PCRE2_UCHAR8
*)arg2
, &pcre2len
);
119 SCLogError(SC_ERR_PCRE_COPY_SUBSTRING
, "pcre2_substring_copy_bynumber failed");
122 SCLogDebug("Arg2 \"%s\"", arg2
);
125 pcre2len
= sizeof(arg3
);
126 res
= pcre2_substring_copy_bynumber(
127 uint_pcre
.match
, 3, (PCRE2_UCHAR8
*)arg3
, &pcre2len
);
129 SCLogError(SC_ERR_PCRE_COPY_SUBSTRING
, "pcre2_substring_copy_bynumber failed");
132 SCLogDebug("Arg3 \"%s\"", arg3
);
136 if (strlen(arg2
) > 0) {
141 if (strlen(arg3
) == 0)
144 if (ByteExtractStringUint32(&u32da
.arg1
, 10, strlen(arg3
), arg3
) < 0) {
145 SCLogError(SC_ERR_BYTE_EXTRACT_FAILED
, "ByteExtractStringUint32 failed");
149 SCLogDebug("u32 is %"PRIu32
"",u32da
.arg1
);
150 if (strlen(arg1
) > 0)
153 if (arg2
[0] == '<') {
154 if (arg2
[1] == '=') {
155 u32da
.mode
= DETECT_UINT_LTE
;
157 u32da
.mode
= DETECT_UINT_LT
;
159 } else { // arg2[0] == '>'
160 if (arg2
[1] == '=') {
161 u32da
.mode
= DETECT_UINT_GTE
;
163 u32da
.mode
= DETECT_UINT_GT
;
168 if (strlen(arg1
)== 0)
170 if (strlen(arg3
)== 0)
173 u32da
.mode
= DETECT_UINT_RA
;
174 if (ByteExtractStringUint32(&u32da
.arg1
, 10, strlen(arg1
), arg1
) < 0) {
175 SCLogError(SC_ERR_BYTE_EXTRACT_FAILED
, "ByteExtractStringUint32 failed");
178 if (ByteExtractStringUint32(&u32da
.arg2
, 10, strlen(arg3
), arg3
) < 0) {
179 SCLogError(SC_ERR_BYTE_EXTRACT_FAILED
, "ByteExtractStringUint32 failed");
183 SCLogDebug("u32 is %"PRIu32
" to %"PRIu32
"", u32da
.arg1
, u32da
.arg2
);
184 if (u32da
.arg1
>= u32da
.arg2
) {
185 SCLogError(SC_ERR_INVALID_SIGNATURE
, "Invalid u32 range. ");
190 u32da
.mode
= DETECT_UINT_EQ
;
192 if (strlen(arg2
) > 0 ||
197 if (ByteExtractStringUint32(&u32da
.arg1
, 10, strlen(arg1
), arg1
) < 0) {
198 SCLogError(SC_ERR_BYTE_EXTRACT_FAILED
, "ByteExtractStringUint32 failed");
203 u32da
.mode
= DETECT_UINT_EQ
;
205 if (strlen(arg3
) > 0 ||
209 if (ByteExtractStringUint32(&u32da
.arg1
, 10, strlen(arg1
), arg1
) < 0) {
210 SCLogError(SC_ERR_BYTE_EXTRACT_FAILED
, "ByteExtractStringUint32 failed");
214 u32d
= SCCalloc(1, sizeof (DetectU32Data
));
215 if (unlikely(u32d
== NULL
))
217 u32d
->arg1
= u32da
.arg1
;
218 u32d
->arg2
= u32da
.arg2
;
219 u32d
->mode
= u32da
.mode
;
225 PrefilterPacketU32Set(PrefilterPacketHeaderValue
*v
, void *smctx
)
227 const DetectU32Data
*a
= smctx
;
234 PrefilterPacketU32Compare(PrefilterPacketHeaderValue v
, void *smctx
)
236 const DetectU32Data
*a
= smctx
;
237 if (v
.u8
[0] == a
->mode
&&
238 v
.u32
[1] == a
->arg1
&&
244 static bool g_detect_uint_registered
= false;
246 void DetectUintRegister(void)
248 if (g_detect_uint_registered
== false) {
249 // register only once
250 DetectSetupParseRegexes(PARSE_REGEX
, &uint_pcre
);
251 g_detect_uint_registered
= true;
255 //same as u32 but with u8
256 int DetectU8Match(const uint8_t parg
, const DetectU8Data
*du8
)
260 if (parg
== du8
->arg1
) {
265 if (parg
< du8
->arg1
) {
269 case DETECT_UINT_LTE
:
270 if (parg
<= du8
->arg1
) {
275 if (parg
> du8
->arg1
) {
279 case DETECT_UINT_GTE
:
280 if (parg
>= du8
->arg1
) {
285 if (parg
> du8
->arg1
&& parg
< du8
->arg2
) {
290 BUG_ON("unknown mode");
296 * \brief This function is used to parse u8 options passed via some u8 keyword
298 * \param u8str Pointer to the user provided u8 options
300 * \retval DetectU8Data pointer to DetectU8Data on success
301 * \retval NULL on failure
304 DetectU8Data
*DetectU8Parse (const char *u8str
)
306 /* We initialize these to please static checkers, these values will
307 either be updated or not used later on */
308 DetectU8Data u8da
= {0, 0, 0};
309 DetectU8Data
*u8d
= NULL
;
314 int ret
= 0, res
= 0;
317 ret
= DetectParsePcreExec(&uint_pcre
, u8str
, 0, 0);
318 if (ret
< 2 || ret
> 4) {
319 SCLogError(SC_ERR_PCRE_MATCH
, "parse error, ret %" PRId32
"", ret
);
323 pcre2len
= sizeof(arg1
);
324 res
= pcre2_substring_copy_bynumber(uint_pcre
.match
, 1, (PCRE2_UCHAR8
*)arg1
, &pcre2len
);
326 SCLogError(SC_ERR_PCRE_COPY_SUBSTRING
, "pcre2_substring_copy_bynumber failed");
329 SCLogDebug("Arg1 \"%s\"", arg1
);
332 pcre2len
= sizeof(arg2
);
333 res
= pcre2_substring_copy_bynumber(uint_pcre
.match
, 2, (PCRE2_UCHAR8
*)arg2
, &pcre2len
);
335 SCLogError(SC_ERR_PCRE_COPY_SUBSTRING
, "pcre2_substring_copy_bynumber failed");
338 SCLogDebug("Arg2 \"%s\"", arg2
);
341 pcre2len
= sizeof(arg3
);
342 res
= pcre2_substring_copy_bynumber(
343 uint_pcre
.match
, 3, (PCRE2_UCHAR8
*)arg3
, &pcre2len
);
345 SCLogError(SC_ERR_PCRE_COPY_SUBSTRING
, "pcre2_substring_copy_bynumber failed");
348 SCLogDebug("Arg3 \"%s\"", arg3
);
352 if (strlen(arg2
) > 0) {
357 if (StringParseUint8(&u8da
.arg1
, 10, strlen(arg3
), arg3
) < 0) {
358 SCLogError(SC_ERR_BYTE_EXTRACT_FAILED
, "ByteExtractStringUint8 failed");
362 SCLogDebug("u8 is %"PRIu8
"",u8da
.arg1
);
363 if (strlen(arg1
) > 0)
366 if (arg2
[0] == '<') {
367 if (arg2
[1] == '=') {
368 u8da
.mode
= DETECT_UINT_LTE
;
370 u8da
.mode
= DETECT_UINT_LT
;
372 } else { // arg2[0] == '>'
373 if (arg2
[1] == '=') {
374 u8da
.mode
= DETECT_UINT_GTE
;
376 u8da
.mode
= DETECT_UINT_GT
;
381 u8da
.mode
= DETECT_UINT_RA
;
382 if (StringParseUint8(&u8da
.arg1
, 10, strlen(arg1
), arg1
) < 0) {
383 SCLogError(SC_ERR_BYTE_EXTRACT_FAILED
, "ByteExtractStringUint8 failed");
386 if (StringParseUint8(&u8da
.arg2
, 10, strlen(arg3
), arg3
) < 0) {
387 SCLogError(SC_ERR_BYTE_EXTRACT_FAILED
, "ByteExtractStringUint8 failed");
391 SCLogDebug("u8 is %"PRIu8
" to %"PRIu8
"", u8da
.arg1
, u8da
.arg2
);
392 if (u8da
.arg1
>= u8da
.arg2
) {
393 SCLogError(SC_ERR_INVALID_SIGNATURE
, "Invalid u8 range. ");
398 u8da
.mode
= DETECT_UINT_EQ
;
400 if (strlen(arg2
) > 0 ||
404 if (StringParseUint8(&u8da
.arg1
, 10, strlen(arg1
), arg1
) < 0) {
405 SCLogError(SC_ERR_BYTE_EXTRACT_FAILED
, "ByteExtractStringUint8 failed");
410 u8da
.mode
= DETECT_UINT_EQ
;
412 if (strlen(arg3
) > 0)
415 if (StringParseUint8(&u8da
.arg1
, 10, strlen(arg1
), arg1
) < 0) {
416 SCLogError(SC_ERR_BYTE_EXTRACT_FAILED
, "ByteExtractStringUint8 failed");
420 u8d
= SCCalloc(1, sizeof (DetectU8Data
));
421 if (unlikely(u8d
== NULL
))
423 u8d
->arg1
= u8da
.arg1
;
424 u8d
->arg2
= u8da
.arg2
;
425 u8d
->mode
= u8da
.mode
;