/src/suricata7/src/util-rule-vars.c
Line | Count | Source |
1 | | /* Copyright (C) 2007-2010 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 Anoop Saldanha <anoopsaldanha@gmail.com> |
22 | | * |
23 | | * Rule variable utility functions |
24 | | */ |
25 | | |
26 | | #include "suricata-common.h" |
27 | | #include "conf.h" |
28 | | #include "conf-yaml-loader.h" |
29 | | |
30 | | #include "detect.h" |
31 | | #include "detect-content.h" |
32 | | #include "detect-parse.h" |
33 | | #include "detect-engine.h" |
34 | | #include "detect-engine-mpm.h" |
35 | | |
36 | | #include "util-rule-vars.h" |
37 | | #include "util-enum.h" |
38 | | #include "util-debug.h" |
39 | | #include "util-unittest.h" |
40 | | |
41 | | /** An enum-string map, that maps the different vars type in the yaml conf |
42 | | * type with the mapping path in the yaml conf file */ |
43 | | SCEnumCharMap sc_rule_vars_type_map[ ] = { |
44 | | { "vars.address-groups", SC_RULE_VARS_ADDRESS_GROUPS }, |
45 | | { "vars.port-groups", SC_RULE_VARS_PORT_GROUPS } |
46 | | }; |
47 | | |
48 | | /** |
49 | | * \internal |
50 | | * \brief Retrieves a value for a yaml mapping. The sequence from the yaml |
51 | | * conf file, from which the conf value has to be retrieved can be |
52 | | * specified by supplying a SCRuleVarsType enum. The string mapping |
53 | | * for each of the SCRuleVarsType is present in sc_rule_vars_type_map. |
54 | | * |
55 | | * \param conf_var_name Pointer to a character string containing the conf var |
56 | | * name, whose value has to be retrieved from the yaml |
57 | | * conf file. |
58 | | * \param conf_vars_type Holds an enum value that indicates the kind of yaml |
59 | | * mapping that has to be retrieved. Can be one of the |
60 | | * values in SCRuleVarsType. |
61 | | * |
62 | | * \retval conf_var_name_value Pointer to the string containing the conf value |
63 | | * on success; NULL on failure. |
64 | | */ |
65 | | const char *SCRuleVarsGetConfVar(const DetectEngineCtx *de_ctx, |
66 | | const char *conf_var_name, |
67 | | SCRuleVarsType conf_vars_type) |
68 | 18.3k | { |
69 | 18.3k | SCEnter(); |
70 | | |
71 | 18.3k | const char *conf_var_type_name = NULL; |
72 | 18.3k | char conf_var_full_name[2048]; |
73 | 18.3k | const char *conf_var_full_name_value = NULL; |
74 | | |
75 | 18.3k | if (conf_var_name == NULL) |
76 | 0 | goto end; |
77 | | |
78 | 21.9k | while (conf_var_name[0] != '\0' && isspace((unsigned char)conf_var_name[0])) { |
79 | 3.55k | conf_var_name++; |
80 | 3.55k | } |
81 | | |
82 | 18.3k | (conf_var_name[0] == '$') ? conf_var_name++ : conf_var_name; |
83 | 18.3k | conf_var_type_name = SCMapEnumValueToName(conf_vars_type, |
84 | 18.3k | sc_rule_vars_type_map); |
85 | 18.3k | if (conf_var_type_name == NULL) |
86 | 0 | goto end; |
87 | | |
88 | 18.3k | if (de_ctx != NULL && strlen(de_ctx->config_prefix) > 0) { |
89 | 0 | if (snprintf(conf_var_full_name, sizeof(conf_var_full_name), "%s.%s.%s", |
90 | 0 | de_ctx->config_prefix, conf_var_type_name, conf_var_name) < 0) { |
91 | 0 | goto end; |
92 | 0 | } |
93 | 18.3k | } else { |
94 | 18.3k | if (snprintf(conf_var_full_name, sizeof(conf_var_full_name), "%s.%s", |
95 | 18.3k | conf_var_type_name, conf_var_name) < 0) { |
96 | 0 | goto end; |
97 | 0 | } |
98 | 18.3k | } |
99 | | |
100 | 18.3k | if (ConfGet(conf_var_full_name, &conf_var_full_name_value) != 1) { |
101 | 18.3k | SCLogError("Variable \"%s\" is not defined in " |
102 | 18.3k | "configuration file", |
103 | 18.3k | conf_var_name); |
104 | 18.3k | goto end; |
105 | 18.3k | } |
106 | | |
107 | 0 | SCLogDebug("Value obtained from the yaml conf file, for the var " |
108 | 0 | "\"%s\" is \"%s\"", conf_var_name, conf_var_full_name_value); |
109 | |
|
110 | 18.3k | end: |
111 | 18.3k | SCReturnCharPtr(conf_var_full_name_value); |
112 | 0 | } |
113 | | |
114 | | |
115 | | /**********************************Unittests***********************************/ |
116 | | #ifdef UNITTESTS |
117 | | |
118 | | static const char *dummy_conf_string = |
119 | | "%YAML 1.1\n" |
120 | | "---\n" |
121 | | "\n" |
122 | | "default-log-dir: /var/log/suricata\n" |
123 | | "\n" |
124 | | "logging:\n" |
125 | | "\n" |
126 | | " default-log-level: debug\n" |
127 | | "\n" |
128 | | " default-format: \"<%t> - <%l>\"\n" |
129 | | "\n" |
130 | | " default-startup-message: Your IDS has started.\n" |
131 | | "\n" |
132 | | " default-output-filter:\n" |
133 | | "\n" |
134 | | " output:\n" |
135 | | "\n" |
136 | | " - interface: console\n" |
137 | | " log-level: info\n" |
138 | | "\n" |
139 | | " - interface: file\n" |
140 | | " filename: /var/log/suricata.log\n" |
141 | | "\n" |
142 | | " - interface: syslog\n" |
143 | | " facility: local5\n" |
144 | | " format: \"%l\"\n" |
145 | | "\n" |
146 | | "pfring:\n" |
147 | | "\n" |
148 | | " interface: eth0\n" |
149 | | "\n" |
150 | | " clusterid: 99\n" |
151 | | "\n" |
152 | | "vars:\n" |
153 | | "\n" |
154 | | " address-groups:\n" |
155 | | "\n" |
156 | | " HOME_NET: \"[192.168.0.0/16,10.8.0.0/16,127.0.0.1,2001:888:" |
157 | | "13c5:5AFE::/64,2001:888:13c5:CAFE::/64]\"\n" |
158 | | "\n" |
159 | | " EXTERNAL_NET: \"[!192.168.0.0/16,2000::/3]\"\n" |
160 | | "\n" |
161 | | " HTTP_SERVERS: \"!192.168.0.0/16\"\n" |
162 | | "\n" |
163 | | " SMTP_SERVERS: \"!192.168.0.0/16\"\n" |
164 | | "\n" |
165 | | " SQL_SERVERS: \"!192.168.0.0/16\"\n" |
166 | | "\n" |
167 | | " DNS_SERVERS: any\n" |
168 | | "\n" |
169 | | " TELNET_SERVERS: any\n" |
170 | | "\n" |
171 | | " AIM_SERVERS: any\n" |
172 | | "\n" |
173 | | " port-groups:\n" |
174 | | "\n" |
175 | | " HTTP_PORTS: \"80:81,88\"\n" |
176 | | "\n" |
177 | | " SHELLCODE_PORTS: 80\n" |
178 | | "\n" |
179 | | " ORACLE_PORTS: 1521\n" |
180 | | "\n" |
181 | | " SSH_PORTS: 22\n" |
182 | | "\n"; |
183 | | |
184 | | /** |
185 | | * \test Check that valid address and port group vars are correctly retrieved |
186 | | * from the configuration. |
187 | | */ |
188 | | static int SCRuleVarsPositiveTest01(void) |
189 | | { |
190 | | ConfCreateContextBackup(); |
191 | | ConfInit(); |
192 | | ConfYamlLoadString(dummy_conf_string, strlen(dummy_conf_string)); |
193 | | |
194 | | /* check for address-groups */ |
195 | | FAIL_IF_NOT(SCRuleVarsGetConfVar(NULL, "$HOME_NET", SC_RULE_VARS_ADDRESS_GROUPS) != NULL && |
196 | | strcmp(SCRuleVarsGetConfVar(NULL, "$HOME_NET", SC_RULE_VARS_ADDRESS_GROUPS), |
197 | | "[192.168.0.0/16,10.8.0.0/16,127.0.0.1,2001:888:13c5:" |
198 | | "5AFE::/64,2001:888:13c5:CAFE::/64]") == 0); |
199 | | FAIL_IF_NOT(SCRuleVarsGetConfVar(NULL, "$EXTERNAL_NET", SC_RULE_VARS_ADDRESS_GROUPS) != NULL && |
200 | | strcmp(SCRuleVarsGetConfVar(NULL, "$EXTERNAL_NET", SC_RULE_VARS_ADDRESS_GROUPS), |
201 | | "[!192.168.0.0/16,2000::/3]") == 0); |
202 | | FAIL_IF_NOT(SCRuleVarsGetConfVar(NULL, "$HTTP_SERVERS", SC_RULE_VARS_ADDRESS_GROUPS) != NULL && |
203 | | strcmp(SCRuleVarsGetConfVar(NULL, "$HTTP_SERVERS", SC_RULE_VARS_ADDRESS_GROUPS), |
204 | | "!192.168.0.0/16") == 0); |
205 | | FAIL_IF_NOT(SCRuleVarsGetConfVar(NULL, "$SMTP_SERVERS", SC_RULE_VARS_ADDRESS_GROUPS) != NULL && |
206 | | strcmp(SCRuleVarsGetConfVar(NULL, "$SMTP_SERVERS", SC_RULE_VARS_ADDRESS_GROUPS), |
207 | | "!192.168.0.0/16") == 0); |
208 | | FAIL_IF_NOT(SCRuleVarsGetConfVar(NULL, "$SQL_SERVERS", SC_RULE_VARS_ADDRESS_GROUPS) != NULL && |
209 | | strcmp(SCRuleVarsGetConfVar(NULL, "$SQL_SERVERS", SC_RULE_VARS_ADDRESS_GROUPS), |
210 | | "!192.168.0.0/16") == 0); |
211 | | FAIL_IF_NOT(SCRuleVarsGetConfVar(NULL, "$DNS_SERVERS", SC_RULE_VARS_ADDRESS_GROUPS) != NULL && |
212 | | strcmp(SCRuleVarsGetConfVar(NULL, "$DNS_SERVERS", SC_RULE_VARS_ADDRESS_GROUPS), |
213 | | "any") == 0); |
214 | | FAIL_IF_NOT( |
215 | | SCRuleVarsGetConfVar(NULL, "$TELNET_SERVERS", SC_RULE_VARS_ADDRESS_GROUPS) != NULL && |
216 | | strcmp(SCRuleVarsGetConfVar(NULL, "$TELNET_SERVERS", SC_RULE_VARS_ADDRESS_GROUPS), |
217 | | "any") == 0); |
218 | | FAIL_IF_NOT(SCRuleVarsGetConfVar(NULL, "$AIM_SERVERS", SC_RULE_VARS_ADDRESS_GROUPS) != NULL && |
219 | | strcmp(SCRuleVarsGetConfVar(NULL, "$AIM_SERVERS", SC_RULE_VARS_ADDRESS_GROUPS), |
220 | | "any") == 0); |
221 | | |
222 | | /* Test that a leading space is stripped. */ |
223 | | FAIL_IF_NOT(SCRuleVarsGetConfVar(NULL, " $AIM_SERVERS", SC_RULE_VARS_ADDRESS_GROUPS) != NULL && |
224 | | strcmp(SCRuleVarsGetConfVar(NULL, " $AIM_SERVERS", SC_RULE_VARS_ADDRESS_GROUPS), |
225 | | "any") == 0); |
226 | | |
227 | | /* check for port-groups */ |
228 | | FAIL_IF_NOT(SCRuleVarsGetConfVar(NULL, "$HTTP_PORTS", SC_RULE_VARS_PORT_GROUPS) != NULL && |
229 | | strcmp(SCRuleVarsGetConfVar(NULL, "$HTTP_PORTS", SC_RULE_VARS_PORT_GROUPS), |
230 | | "80:81,88") == 0); |
231 | | FAIL_IF_NOT(SCRuleVarsGetConfVar(NULL, "$SHELLCODE_PORTS", SC_RULE_VARS_PORT_GROUPS) != NULL && |
232 | | strcmp(SCRuleVarsGetConfVar(NULL, "$SHELLCODE_PORTS", SC_RULE_VARS_PORT_GROUPS), |
233 | | "80") == 0); |
234 | | FAIL_IF_NOT(SCRuleVarsGetConfVar(NULL, "$ORACLE_PORTS", SC_RULE_VARS_PORT_GROUPS) != NULL && |
235 | | strcmp(SCRuleVarsGetConfVar(NULL, "$ORACLE_PORTS", SC_RULE_VARS_PORT_GROUPS), |
236 | | "1521") == 0); |
237 | | FAIL_IF_NOT( |
238 | | SCRuleVarsGetConfVar(NULL, "$SSH_PORTS", SC_RULE_VARS_PORT_GROUPS) != NULL && |
239 | | strcmp(SCRuleVarsGetConfVar(NULL, "$SSH_PORTS", SC_RULE_VARS_PORT_GROUPS), "22") == 0); |
240 | | |
241 | | ConfDeInit(); |
242 | | ConfRestoreContextBackup(); |
243 | | PASS; |
244 | | } |
245 | | |
246 | | /** |
247 | | * \test Check that invalid address and port groups are properly handled by the |
248 | | * API. |
249 | | */ |
250 | | static int SCRuleVarsNegativeTest02(void) |
251 | | { |
252 | | ConfCreateContextBackup(); |
253 | | ConfInit(); |
254 | | ConfYamlLoadString(dummy_conf_string, strlen(dummy_conf_string)); |
255 | | |
256 | | FAIL_IF_NOT(SCRuleVarsGetConfVar(NULL, "$HOME_NETW", SC_RULE_VARS_ADDRESS_GROUPS) == NULL); |
257 | | FAIL_IF_NOT(SCRuleVarsGetConfVar(NULL, "$home_net", SC_RULE_VARS_ADDRESS_GROUPS) == NULL); |
258 | | FAIL_IF_NOT(SCRuleVarsGetConfVar(NULL, "$TOMCAT_PORTSW", SC_RULE_VARS_PORT_GROUPS) == NULL); |
259 | | FAIL_IF_NOT(SCRuleVarsGetConfVar(NULL, "$tomcat_ports", SC_RULE_VARS_PORT_GROUPS) == NULL); |
260 | | |
261 | | ConfDeInit(); |
262 | | ConfRestoreContextBackup(); |
263 | | PASS; |
264 | | } |
265 | | |
266 | | /** |
267 | | * \test Check that Signatures with valid address and port groups are parsed |
268 | | * without any errors by the Signature parsing API. |
269 | | */ |
270 | | static int SCRuleVarsPositiveTest03(void) |
271 | | { |
272 | | ConfCreateContextBackup(); |
273 | | ConfInit(); |
274 | | ConfYamlLoadString(dummy_conf_string, strlen(dummy_conf_string)); |
275 | | |
276 | | DetectEngineCtx *de_ctx = DetectEngineCtxInit(); |
277 | | FAIL_IF_NULL(de_ctx); |
278 | | de_ctx->flags |= DE_QUIET; |
279 | | |
280 | | Signature *s = DetectEngineAppendSig(de_ctx, |
281 | | "alert tcp [$HTTP_SERVERS,$HOME_NET,192.168.2.5] $HTTP_PORTS -> $EXTERNAL_NET " |
282 | | "[80,[!$HTTP_PORTS,$ORACLE_PORTS]] (msg:\"Rule Vars Test\"; sid:1;)"); |
283 | | FAIL_IF_NULL(s); |
284 | | |
285 | | ConfDeInit(); |
286 | | ConfRestoreContextBackup(); |
287 | | DetectEngineCtxFree(de_ctx); |
288 | | PASS; |
289 | | } |
290 | | |
291 | | /** |
292 | | * \test Check that Signatures with invalid address and port groups, are |
293 | | * are invalidated by the Signature parsing API. |
294 | | */ |
295 | | static int SCRuleVarsNegativeTest04(void) |
296 | | { |
297 | | ConfCreateContextBackup(); |
298 | | ConfInit(); |
299 | | ConfYamlLoadString(dummy_conf_string, strlen(dummy_conf_string)); |
300 | | DetectEngineCtx *de_ctx = DetectEngineCtxInit(); |
301 | | FAIL_IF_NULL(de_ctx); |
302 | | de_ctx->flags |= DE_QUIET; |
303 | | |
304 | | Signature *s = DetectEngineAppendSig( |
305 | | de_ctx, "alert tcp $HTTP_SERVER any -> any any (msg:\"Rule Vars Test\"; sid:1;)"); |
306 | | FAIL_IF_NOT_NULL(s); |
307 | | s = DetectEngineAppendSig( |
308 | | de_ctx, "alert tcp $http_servers any -> any any (msg:\"Rule Vars Test\"; sid:1;)"); |
309 | | FAIL_IF_NOT_NULL(s); |
310 | | s = DetectEngineAppendSig(de_ctx, |
311 | | "alert tcp $http_servers any -> any $HTTP_PORTS (msg:\"Rule Vars Test\"; sid:1;)"); |
312 | | FAIL_IF_NOT_NULL(s); |
313 | | s = DetectEngineAppendSig(de_ctx, |
314 | | "alert tcp !$TELNET_SERVERS !80 -> any !$SSH_PORTS (msg:\"Rule Vars Test\"; sid:1;)"); |
315 | | FAIL_IF_NOT_NULL(s); |
316 | | |
317 | | DetectEngineCtxFree(de_ctx); |
318 | | ConfDeInit(); |
319 | | ConfRestoreContextBackup(); |
320 | | PASS; |
321 | | } |
322 | | |
323 | | static const char *dummy_mt_conf_string = |
324 | | "%YAML 1.1\n" |
325 | | "---\n" |
326 | | "vars:\n" |
327 | | "\n" |
328 | | " address-groups:\n" |
329 | | "\n" |
330 | | " HOME_NET: \"[1.2.3.4]\"\n" |
331 | | " port-groups:\n" |
332 | | " HTTP_PORTS: \"12345\"\n" |
333 | | "multi-detect:\n" |
334 | | " 0:\n" |
335 | | " vars:\n" |
336 | | "\n" |
337 | | " address-groups:\n" |
338 | | "\n" |
339 | | " HOME_NET: \"[8.8.8.8]\"\n" |
340 | | " port-groups:\n" |
341 | | " HTTP_PORTS: \"54321\"\n" |
342 | | "\n"; |
343 | | |
344 | | /** |
345 | | * \test Check that valid address and port group vars are correctly retrieved |
346 | | * from the configuration. |
347 | | */ |
348 | | static int SCRuleVarsMTest01(void) |
349 | | { |
350 | | int result = 0; |
351 | | DetectEngineCtx *de_ctx = NULL; |
352 | | |
353 | | ConfCreateContextBackup(); |
354 | | ConfInit(); |
355 | | ConfYamlLoadString(dummy_mt_conf_string, strlen(dummy_mt_conf_string)); |
356 | | |
357 | | if ( (de_ctx = DetectEngineCtxInit()) == NULL) |
358 | | return 0; |
359 | | de_ctx->flags |= DE_QUIET; |
360 | | snprintf(de_ctx->config_prefix, sizeof(de_ctx->config_prefix), |
361 | | "multi-detect.0"); |
362 | | |
363 | | /* check for address-groups */ |
364 | | result = (SCRuleVarsGetConfVar(de_ctx,"$HOME_NET", SC_RULE_VARS_ADDRESS_GROUPS) != NULL && |
365 | | strcmp(SCRuleVarsGetConfVar(de_ctx,"$HOME_NET", SC_RULE_VARS_ADDRESS_GROUPS), |
366 | | "[8.8.8.8]") == 0); |
367 | | if (result == 0) |
368 | | goto end; |
369 | | |
370 | | result = (SCRuleVarsGetConfVar(NULL,"$HOME_NET", SC_RULE_VARS_ADDRESS_GROUPS) != NULL && |
371 | | strcmp(SCRuleVarsGetConfVar(NULL,"$HOME_NET", SC_RULE_VARS_ADDRESS_GROUPS), |
372 | | "[1.2.3.4]") == 0); |
373 | | if (result == 0) |
374 | | goto end; |
375 | | |
376 | | /* check for port-groups */ |
377 | | result = (SCRuleVarsGetConfVar(de_ctx,"$HTTP_PORTS", SC_RULE_VARS_PORT_GROUPS) != NULL && |
378 | | strcmp(SCRuleVarsGetConfVar(de_ctx,"$HTTP_PORTS", SC_RULE_VARS_PORT_GROUPS), |
379 | | "54321") == 0); |
380 | | if (result == 0) |
381 | | goto end; |
382 | | |
383 | | result = (SCRuleVarsGetConfVar(NULL,"$HTTP_PORTS", SC_RULE_VARS_PORT_GROUPS) != NULL && |
384 | | strcmp(SCRuleVarsGetConfVar(NULL,"$HTTP_PORTS", SC_RULE_VARS_PORT_GROUPS), |
385 | | "12345") == 0); |
386 | | if (result == 0) |
387 | | goto end; |
388 | | |
389 | | end: |
390 | | ConfDeInit(); |
391 | | ConfRestoreContextBackup(); |
392 | | |
393 | | if (de_ctx != NULL) |
394 | | DetectEngineCtxFree(de_ctx); |
395 | | return result; |
396 | | } |
397 | | |
398 | | #endif /* UNITTESTS */ |
399 | | |
400 | | void SCRuleVarsRegisterTests(void) |
401 | 0 | { |
402 | | #ifdef UNITTESTS |
403 | | UtRegisterTest("SCRuleVarsPositiveTest01", SCRuleVarsPositiveTest01); |
404 | | UtRegisterTest("SCRuleVarsNegativeTest02", SCRuleVarsNegativeTest02); |
405 | | UtRegisterTest("SCRuleVarsPositiveTest03", SCRuleVarsPositiveTest03); |
406 | | UtRegisterTest("SCRuleVarsNegativeTest04", SCRuleVarsNegativeTest04); |
407 | | |
408 | | UtRegisterTest("SCRuleVarsMTest01", SCRuleVarsMTest01); |
409 | | #endif |
410 | |
|
411 | 0 | return; |
412 | 0 | } |