suricata
util-rule-vars.c
Go to the documentation of this file.
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 */
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 */
66 const char *conf_var_name,
67 SCRuleVarsType conf_vars_type)
68{
69 SCEnter();
70
71 const char *conf_var_type_name = NULL;
72 char conf_var_full_name[2048];
73 const char *conf_var_full_name_value = NULL;
74
75 if (conf_var_name == NULL)
76 goto end;
77
78 while (conf_var_name[0] != '\0' && isspace((unsigned char)conf_var_name[0])) {
79 conf_var_name++;
80 }
81
82 (conf_var_name[0] == '$') ? conf_var_name++ : conf_var_name;
83 conf_var_type_name = SCMapEnumValueToName(conf_vars_type,
85 if (conf_var_type_name == NULL)
86 goto end;
87
88 if (de_ctx != NULL && strlen(de_ctx->config_prefix) > 0) {
89 if (snprintf(conf_var_full_name, sizeof(conf_var_full_name), "%s.%s.%s",
90 de_ctx->config_prefix, conf_var_type_name, conf_var_name) < 0) {
91 goto end;
92 }
93 } else {
94 if (snprintf(conf_var_full_name, sizeof(conf_var_full_name), "%s.%s",
95 conf_var_type_name, conf_var_name) < 0) {
96 goto end;
97 }
98 }
99
100 if (SCConfGet(conf_var_full_name, &conf_var_full_name_value) != 1) {
101 SCLogError("Variable \"%s\" is not defined in "
102 "configuration file",
103 conf_var_name);
104 goto end;
105 }
106
107 SCLogDebug("Value obtained from the yaml conf file, for the var "
108 "\"%s\" is \"%s\"", conf_var_name, conf_var_full_name_value);
109
110 end:
111 SCReturnCharPtr(conf_var_full_name_value);
112}
113
114
115/**********************************Unittests***********************************/
116#ifdef UNITTESTS
117
118static 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 */
188static int SCRuleVarsPositiveTest01(void)
189{
191 SCConfInit();
192 SCConfYamlLoadString(dummy_conf_string, strlen(dummy_conf_string));
193
194 /* check for address-groups */
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);
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);
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 SCConfDeInit();
243 PASS;
244}
245
246/**
247 * \test Check that invalid address and port groups are properly handled by the
248 * API.
249 */
250static int SCRuleVarsNegativeTest02(void)
251{
253 SCConfInit();
254 SCConfYamlLoadString(dummy_conf_string, strlen(dummy_conf_string));
255
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 SCConfDeInit();
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 */
270static int SCRuleVarsPositiveTest03(void)
271{
273 SCConfInit();
274 SCConfYamlLoadString(dummy_conf_string, strlen(dummy_conf_string));
275
279
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 SCConfDeInit();
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 */
295static int SCRuleVarsNegativeTest04(void)
296{
298 SCConfInit();
299 SCConfYamlLoadString(dummy_conf_string, strlen(dummy_conf_string));
303
305 de_ctx, "alert tcp $HTTP_SERVER any -> any any (msg:\"Rule Vars Test\"; sid:1;)");
308 de_ctx, "alert tcp $http_servers any -> any any (msg:\"Rule Vars Test\"; sid:1;)");
311 "alert tcp $http_servers any -> any $HTTP_PORTS (msg:\"Rule Vars Test\"; sid:1;)");
314 "alert tcp !$TELNET_SERVERS !80 -> any !$SSH_PORTS (msg:\"Rule Vars Test\"; sid:1;)");
316
318 SCConfDeInit();
320 PASS;
321}
322
323static 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 */
348static int SCRuleVarsMTest01(void)
349{
350 int result = 0;
351 DetectEngineCtx *de_ctx = NULL;
352
354 SCConfInit();
355 SCConfYamlLoadString(dummy_mt_conf_string, strlen(dummy_mt_conf_string));
356
357 if ( (de_ctx = DetectEngineCtxInit()) == NULL)
358 return 0;
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 &&
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 &&
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
389end:
390 SCConfDeInit();
392
393 if (de_ctx != NULL)
395 return result;
396}
397
398#endif /* UNITTESTS */
399
401{
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}
int SCConfYamlLoadString(const char *string, size_t len)
Load configuration from a YAML string.
void SCConfInit(void)
Initialize the configuration system.
Definition conf.c:120
void SCConfDeInit(void)
De-initializes the configuration system.
Definition conf.c:703
int SCConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
Definition conf.c:350
void SCConfCreateContextBackup(void)
Creates a backup of the conf_hash hash_table used by the conf API.
Definition conf.c:684
void SCConfRestoreContextBackup(void)
Restores the backup of the hash_table present in backup_conf_hash back to conf_hash.
Definition conf.c:694
DetectEngineCtx * DetectEngineCtxInit(void)
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Signature * DetectEngineAppendSig(DetectEngineCtx *, const char *)
Parse and append a Signature into the Detection Engine Context signature list.
#define DE_QUIET
Definition detect.h:330
DetectEngineCtx * de_ctx
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
#define PASS
Pass the test.
#define FAIL_IF_NOT_NULL(expr)
Fail a test if expression evaluates to non-NULL.
main detection engine ctx
Definition detect.h:932
uint8_t flags
Definition detect.h:934
char config_prefix[64]
Definition detect.h:1051
Signature container.
Definition detect.h:668
#define SCEnter(...)
Definition util-debug.h:277
#define SCLogDebug(...)
Definition util-debug.h:275
#define SCReturnCharPtr(x)
Definition util-debug.h:289
#define SCLogError(...)
Macro used to log ERROR messages.
Definition util-debug.h:267
const char * SCMapEnumValueToName(int enum_value, SCEnumCharMap *table)
Maps an enum value to a string name, from the supplied table.
Definition util-enum.c:68
const char * SCRuleVarsGetConfVar(const DetectEngineCtx *de_ctx, const char *conf_var_name, SCRuleVarsType conf_vars_type)
SCEnumCharMap sc_rule_vars_type_map[]
void SCRuleVarsRegisterTests(void)
SCRuleVarsType
@ SC_RULE_VARS_PORT_GROUPS
@ SC_RULE_VARS_ADDRESS_GROUPS