/src/suricata7/src/detect-priority.c
Line | Count | Source |
1 | | /* Copyright (C) 2007-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 Victor Julien <victor@inliniac.net> |
22 | | * \author Anoop Saldanha <anoopsaldanha@gmail.com> |
23 | | * |
24 | | * Implements the priority keyword |
25 | | */ |
26 | | |
27 | | #include "suricata-common.h" |
28 | | #include "detect.h" |
29 | | #include "detect-parse.h" |
30 | | #include "detect-priority.h" |
31 | | #include "detect-engine.h" |
32 | | #include "detect-engine-mpm.h" |
33 | | #include "util-error.h" |
34 | | #include "util-debug.h" |
35 | | #include "util-unittest.h" |
36 | | |
37 | 73 | #define PARSE_REGEX "^\\s*(\\d+|\"\\d+\")\\s*$" |
38 | | |
39 | | static DetectParseRegex parse_regex; |
40 | | |
41 | | static int DetectPrioritySetup (DetectEngineCtx *, Signature *, const char *); |
42 | | #ifdef UNITTESTS |
43 | | static void PriorityRegisterTests(void); |
44 | | #endif |
45 | | |
46 | | /** |
47 | | * \brief Registers the handler functions for the "priority" keyword |
48 | | */ |
49 | | void DetectPriorityRegister (void) |
50 | 73 | { |
51 | 73 | sigmatch_table[DETECT_PRIORITY].name = "priority"; |
52 | 73 | sigmatch_table[DETECT_PRIORITY].desc = "rules with a higher priority will be examined first"; |
53 | 73 | sigmatch_table[DETECT_PRIORITY].url = "/rules/meta.html#priority"; |
54 | 73 | sigmatch_table[DETECT_PRIORITY].Setup = DetectPrioritySetup; |
55 | | #ifdef UNITTESTS |
56 | | sigmatch_table[DETECT_PRIORITY].RegisterTests = PriorityRegisterTests; |
57 | | #endif |
58 | 73 | DetectSetupParseRegexes(PARSE_REGEX, &parse_regex); |
59 | 73 | } |
60 | | |
61 | | static int DetectPrioritySetup (DetectEngineCtx *de_ctx, Signature *s, const char *rawstr) |
62 | 11.3k | { |
63 | 11.3k | char copy_str[128] = ""; |
64 | 11.3k | size_t pcre2len; |
65 | | |
66 | 11.3k | pcre2_match_data *match = NULL; |
67 | 11.3k | int ret = DetectParsePcreExec(&parse_regex, &match, rawstr, 0, 0); |
68 | 11.3k | if (ret < 0) { |
69 | 238 | SCLogError("Invalid Priority in Signature " |
70 | 238 | "- %s", |
71 | 238 | rawstr); |
72 | 238 | if (match) |
73 | 238 | pcre2_match_data_free(match); |
74 | 238 | return -1; |
75 | 238 | } |
76 | | |
77 | 11.0k | pcre2len = sizeof(copy_str); |
78 | 11.0k | ret = pcre2_substring_copy_bynumber(match, 1, (PCRE2_UCHAR8 *)copy_str, &pcre2len); |
79 | 11.0k | if (ret < 0) { |
80 | 144 | SCLogError("pcre2_substring_copy_bynumber failed"); |
81 | 144 | pcre2_match_data_free(match); |
82 | 144 | return -1; |
83 | 144 | } |
84 | | |
85 | 11.0k | pcre2_match_data_free(match); |
86 | 10.9k | char *endptr = NULL; |
87 | 10.9k | long prio = strtol(copy_str, &endptr, 10); |
88 | 10.9k | if (endptr == NULL || *endptr != '\0') { |
89 | 0 | SCLogError("Saw an invalid character as arg " |
90 | 0 | "to priority keyword"); |
91 | 0 | return -1; |
92 | 0 | } |
93 | | |
94 | 10.9k | if (s->init_data->init_flags & SIG_FLAG_INIT_PRIO_EXPLICIT) { |
95 | 3.87k | SCLogWarning("duplicate priority " |
96 | 3.87k | "keyword. Using highest priority in the rule"); |
97 | 3.87k | s->prio = MIN(s->prio, prio); |
98 | 7.05k | } else { |
99 | 7.05k | s->prio = prio; |
100 | 7.05k | s->init_data->init_flags |= SIG_FLAG_INIT_PRIO_EXPLICIT; |
101 | 7.05k | } |
102 | 10.9k | return 0; |
103 | 10.9k | } |
104 | | |
105 | | /*------------------------------Unittests-------------------------------------*/ |
106 | | |
107 | | #ifdef UNITTESTS |
108 | | |
109 | | static int DetectPriorityTest01(void) |
110 | | { |
111 | | DetectEngineCtx *de_ctx = DetectEngineCtxInit(); |
112 | | FAIL_IF_NULL(de_ctx); |
113 | | |
114 | | de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " |
115 | | "(msg:\"Priority test\"; priority:2; sid:1;)"); |
116 | | FAIL_IF_NULL(de_ctx->sig_list); |
117 | | |
118 | | FAIL_IF_NOT(de_ctx->sig_list->prio == 2); |
119 | | |
120 | | DetectEngineCtxFree(de_ctx); |
121 | | PASS; |
122 | | } |
123 | | |
124 | | static int DetectPriorityTest02(void) |
125 | | { |
126 | | DetectEngineCtx *de_ctx = DetectEngineCtxInit(); |
127 | | FAIL_IF_NULL(de_ctx); |
128 | | |
129 | | Signature *sig = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any " |
130 | | "(msg:\"Priority test\"; priority:1; sid:1;)"); |
131 | | FAIL_IF_NULL(sig); |
132 | | FAIL_IF_NOT(sig->prio == 1); |
133 | | |
134 | | sig = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any " |
135 | | "(msg:\"Priority test\"; priority:boo; sid:2;)"); |
136 | | FAIL_IF_NOT_NULL(sig); |
137 | | |
138 | | sig = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any " |
139 | | "(msg:\"Priority test\"; priority:10boo; sid:3;)"); |
140 | | FAIL_IF_NOT_NULL(sig); |
141 | | |
142 | | sig = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any " |
143 | | "(msg:\"Priority test\"; priority:b10oo; sid:4;)"); |
144 | | FAIL_IF_NOT_NULL(sig); |
145 | | |
146 | | sig = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any " |
147 | | "(msg:\"Priority test\"; priority:boo10; sid:5;)"); |
148 | | FAIL_IF_NOT_NULL(sig); |
149 | | |
150 | | sig = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any " |
151 | | "(msg:\"Priority test\"; priority:-1; sid:6;)"); |
152 | | FAIL_IF_NOT_NULL(sig); |
153 | | |
154 | | sig = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any " |
155 | | "(msg:\"Priority test\"; sid:7;)"); |
156 | | FAIL_IF_NULL(sig); |
157 | | FAIL_IF_NOT(sig->prio == 3); |
158 | | |
159 | | sig = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any " |
160 | | "(msg:\"Priority test\"; priority:5; priority:4; sid:8;)"); |
161 | | FAIL_IF_NULL(sig); |
162 | | FAIL_IF_NOT(sig->prio == 4); |
163 | | |
164 | | sig = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any " |
165 | | "(msg:\"Priority test\"; priority:5; priority:4; " |
166 | | "priority:1; sid:9;)"); |
167 | | FAIL_IF_NULL(sig); |
168 | | FAIL_IF_NOT(sig->prio == 1); |
169 | | |
170 | | DetectEngineCtxFree(de_ctx); |
171 | | PASS; |
172 | | } |
173 | | |
174 | | /** |
175 | | * \brief This function registers unit tests for Classification Config API. |
176 | | */ |
177 | | static void PriorityRegisterTests(void) |
178 | | { |
179 | | UtRegisterTest("DetectPriorityTest01", DetectPriorityTest01); |
180 | | UtRegisterTest("DetectPriorityTest02", DetectPriorityTest02); |
181 | | } |
182 | | #endif /* UNITTESTS */ |