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 (ConfGet(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 
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 {
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();
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 {
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();
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 {
273  ConfInit();
274  ConfYamlLoadString(dummy_conf_string, strlen(dummy_conf_string));
275 
278  de_ctx->flags |= DE_QUIET;
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  ConfDeInit();
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 {
298  ConfInit();
299  ConfYamlLoadString(dummy_conf_string, strlen(dummy_conf_string));
302  de_ctx->flags |= DE_QUIET;
303 
305  de_ctx, "alert tcp $HTTP_SERVER any -> any any (msg:\"Rule Vars Test\"; sid:1;)");
306  FAIL_IF_NOT_NULL(s);
308  de_ctx, "alert tcp $http_servers any -> any any (msg:\"Rule Vars Test\"; sid:1;)");
309  FAIL_IF_NOT_NULL(s);
311  "alert tcp $http_servers any -> any $HTTP_PORTS (msg:\"Rule Vars Test\"; sid:1;)");
312  FAIL_IF_NOT_NULL(s);
314  "alert tcp !$TELNET_SERVERS !80 -> any !$SSH_PORTS (msg:\"Rule Vars Test\"; sid:1;)");
315  FAIL_IF_NOT_NULL(s);
316 
318  ConfDeInit();
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 
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 &&
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 
389 end:
390  ConfDeInit();
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 }
detect-content.h
detect-engine.h
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
SCReturnCharPtr
#define SCReturnCharPtr(x)
Definition: util-debug.h:283
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
SC_RULE_VARS_ADDRESS_GROUPS
@ SC_RULE_VARS_ADDRESS_GROUPS
Definition: util-rule-vars.h:31
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:841
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2611
DE_QUIET
#define DE_QUIET
Definition: detect.h:323
SCRuleVarsType
SCRuleVarsType
Definition: util-rule-vars.h:30
DetectEngineAppendSig
Signature * DetectEngineAppendSig(DetectEngineCtx *, const char *)
Parse and append a Signature into the Detection Engine Context signature list.
Definition: detect-parse.c:2587
util-unittest.h
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:82
ConfGet
int ConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
Definition: conf.c:335
FAIL_IF_NOT_NULL
#define FAIL_IF_NOT_NULL(expr)
Fail a test if expression evaluates to non-NULL.
Definition: util-unittest.h:96
util-debug.h
SC_RULE_VARS_PORT_GROUPS
@ SC_RULE_VARS_PORT_GROUPS
Definition: util-rule-vars.h:32
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:17
SCRuleVarsRegisterTests
void SCRuleVarsRegisterTests(void)
Definition: util-rule-vars.c:400
SCEnter
#define SCEnter(...)
Definition: util-debug.h:271
detect-engine-mpm.h
detect.h
ConfYamlLoadString
int ConfYamlLoadString(const char *string, size_t len)
Load configuration from a YAML string.
Definition: conf-yaml-loader.c:523
util-rule-vars.h
conf-yaml-loader.h
conf.h
ConfCreateContextBackup
void ConfCreateContextBackup(void)
Creates a backup of the conf_hash hash_table used by the conf API.
Definition: conf.c:669
sc_rule_vars_type_map
SCEnumCharMap sc_rule_vars_type_map[]
Definition: util-rule-vars.c:43
DetectEngineCtx_::config_prefix
char config_prefix[64]
Definition: detect.h:960
SCMapEnumValueToName
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
suricata-common.h
SCEnumCharMap_
Definition: util-enum.h:27
ConfRestoreContextBackup
void ConfRestoreContextBackup(void)
Restores the backup of the hash_table present in backup_conf_hash back to conf_hash.
Definition: conf.c:679
ConfInit
void ConfInit(void)
Initialize the configuration system.
Definition: conf.c:120
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:261
detect-parse.h
Signature_
Signature container.
Definition: detect.h:601
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2572
ConfDeInit
void ConfDeInit(void)
De-initializes the configuration system.
Definition: conf.c:688
DetectEngineCtx_::flags
uint8_t flags
Definition: detect.h:843
SCRuleVarsGetConfVar
const char * SCRuleVarsGetConfVar(const DetectEngineCtx *de_ctx, const char *conf_var_name, SCRuleVarsType conf_vars_type)
Definition: util-rule-vars.c:65
util-enum.h