You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
suricata/src/util-rule-vars.c

423 lines
14 KiB
C

/** Copyright (c) 2009 Open Information Security Foundation.
* \author Anoop Saldanha <poonaatsoc@gmail.com>
*/
#include "suricata-common.h"
#include "conf.h"
#include "conf-yaml-loader.h"
#include "detect.h"
#include "detect-content.h"
#include "detect-parse.h"
#include "detect-engine.h"
#include "detect-engine-mpm.h"
#include "util-rule-vars.h"
#include "util-enum.h"
#include "util-debug.h"
#include "util-unittest.h"
/** An enum-string map, that maps the different vars type in the yaml conf
* type with the mapping path in the yaml conf file */
SCEnumCharMap sc_rule_vars_type_map[ ] = {
{ "vars.address-groups", SC_RULE_VARS_ADDRESS_GROUPS },
{ "vars.port-groups", SC_RULE_VARS_PORT_GROUPS }
};
/**
* \internal
* \brief Retrieves a value for a yaml mapping. The sequence from the yaml
* conf file, from which the conf value has to be retrieved can be
* specified by supplying a SCRuleVarsType enum. The string mapping
* for each of the SCRuleVarsType is present in sc_rule_vars_type_map.
*
* \param conf_var_name Pointer to a character string containing the conf var
* name, whose value has to be retrieved from the yaml
* conf file.
* \param conf_vars_type Holds an enum value that indicates the kind of yaml
* mapping that has to be retrieved. Can be one of the
* values in SCRuleVarsType.
*
* \retval conf_var_name_value Pointer to the string containing the conf value
* on success; NULL on failure.
*/
char *SCRuleVarsGetConfVar(const char *conf_var_name,
SCRuleVarsType conf_vars_type)
{
SCEnter();
const char *conf_var_type_name = NULL;
char *conf_var_full_name = NULL;
char *conf_var_full_name_value = NULL;
if (conf_var_name == NULL)
goto end;
(conf_var_name[0] == '$') ? conf_var_name++ : conf_var_name;
conf_var_type_name = SCMapEnumValueToName(conf_vars_type,
sc_rule_vars_type_map);
if (conf_var_type_name == NULL)
goto end;
/* the + 2 is for the '.' and the string termination character '\0' */
conf_var_full_name = (char *)malloc(strlen(conf_var_type_name) +
strlen(conf_var_name) + 2);
if (conf_var_full_name == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory");
goto end;
}
if (snprintf(conf_var_full_name,
strlen(conf_var_type_name) + strlen(conf_var_name) + 2, "%s.%s",
conf_var_type_name, conf_var_name) < 0) {
goto end;
}
if (ConfGet(conf_var_full_name, &conf_var_full_name_value) != 1) {
SCLogError(SC_ERR_UNDEFINED_VAR, "Variable \"%s\" is not defined in "
"configuration file", conf_var_name);
goto end;
}
SCLogDebug("Value obtained from the yaml conf file, for the var "
"\"%s\" is \"%s\"", conf_var_name, conf_var_full_name_value);
end:
if (conf_var_full_name != NULL)
free(conf_var_full_name);
SCReturnCharPtr(conf_var_full_name_value);
}
/**********************************Unittests***********************************/
static const char *dummy_conf_string =
"default-log-dir: /var/log/suricata\n"
"\n"
"logging:\n"
"\n"
" default-log-level: debug\n"
"\n"
" default-format: \"<%t> - <%l>\"\n"
"\n"
" default-startup-message: Your IDS has started.\n"
"\n"
" default-output-filter:\n"
"\n"
" output:\n"
"\n"
" - interface: console\n"
" log-level: info\n"
"\n"
" - interface: file\n"
" filename: /var/log/suricata.log\n"
"\n"
" - interface: syslog\n"
" facility: local5\n"
" format: \"%l\"\n"
"\n"
"pfring:\n"
"\n"
" interface: eth0\n"
"\n"
" clusterid: 99\n"
"\n"
"vars:\n"
"\n"
" address-groups:\n"
"\n"
" HOME_NET: \"[192.168.0.0/16,10.8.0.0/16,127.0.0.1,2001:888:"
"13c5:5AFE::/64,2001:888:13c5:CAFE::/64]\"\n"
"\n"
" EXTERNAL_NET: \"[!192.168.0.0/16,2000::/3]\"\n"
"\n"
" HTTP_SERVERS: \"!192.168.0.0/16\"\n"
"\n"
" SMTP_SERVERS: \"!192.168.0.0/16\"\n"
"\n"
" SQL_SERVERS: \"!192.168.0.0/16\"\n"
"\n"
" DNS_SERVERS: any\n"
"\n"
" TELNET_SERVERS: any\n"
"\n"
" AIM_SERVERS: any\n"
"\n"
" port-groups:\n"
"\n"
" HTTP_PORTS: \"80:81,88\"\n"
"\n"
" SHELLCODE_PORTS: 80\n"
"\n"
" ORACLE_PORTS: 1521\n"
"\n"
" SSH_PORTS: 22\n"
"\n";
/**
* \test Check that valid address and port group vars are correctly retrieved
* from the configuration.
*/
int SCRuleVarsPositiveTest01(void)
{
int result = 1;
ConfCreateContextBackup();
ConfInit();
ConfYamlLoadString(dummy_conf_string, strlen(dummy_conf_string));
/* check for address-groups */
result &= (SCRuleVarsGetConfVar("$HOME_NET", SC_RULE_VARS_ADDRESS_GROUPS) != NULL &&
strcmp(SCRuleVarsGetConfVar("$HOME_NET", SC_RULE_VARS_ADDRESS_GROUPS),
"[192.168.0.0/16,10.8.0.0/16,127.0.0.1,2001:888:13c5:"
"5AFE::/64,2001:888:13c5:CAFE::/64]") == 0);
result &= (SCRuleVarsGetConfVar("$EXTERNAL_NET", SC_RULE_VARS_ADDRESS_GROUPS) != NULL &&
strcmp(SCRuleVarsGetConfVar("$EXTERNAL_NET", SC_RULE_VARS_ADDRESS_GROUPS),
"[!192.168.0.0/16,2000::/3]") == 0);
result &= (SCRuleVarsGetConfVar("$HTTP_SERVERS", SC_RULE_VARS_ADDRESS_GROUPS) != NULL &&
strcmp(SCRuleVarsGetConfVar("$HTTP_SERVERS", SC_RULE_VARS_ADDRESS_GROUPS),
"!192.168.0.0/16") == 0);
result &= (SCRuleVarsGetConfVar("$SMTP_SERVERS", SC_RULE_VARS_ADDRESS_GROUPS) != NULL &&
strcmp(SCRuleVarsGetConfVar("$SMTP_SERVERS", SC_RULE_VARS_ADDRESS_GROUPS),
"!192.168.0.0/16") == 0);
result &= (SCRuleVarsGetConfVar("$SQL_SERVERS", SC_RULE_VARS_ADDRESS_GROUPS) != NULL &&
strcmp(SCRuleVarsGetConfVar("$SQL_SERVERS", SC_RULE_VARS_ADDRESS_GROUPS),
"!192.168.0.0/16") == 0);
result &= (SCRuleVarsGetConfVar("$DNS_SERVERS", SC_RULE_VARS_ADDRESS_GROUPS) != NULL &&
strcmp(SCRuleVarsGetConfVar("$DNS_SERVERS", SC_RULE_VARS_ADDRESS_GROUPS),
"any") == 0);
result &= (SCRuleVarsGetConfVar("$TELNET_SERVERS", SC_RULE_VARS_ADDRESS_GROUPS) != NULL &&
strcmp(SCRuleVarsGetConfVar("$TELNET_SERVERS", SC_RULE_VARS_ADDRESS_GROUPS),
"any") == 0);
result &= (SCRuleVarsGetConfVar("$AIM_SERVERS", SC_RULE_VARS_ADDRESS_GROUPS) != NULL &&
strcmp(SCRuleVarsGetConfVar("$AIM_SERVERS", SC_RULE_VARS_ADDRESS_GROUPS),
"any") == 0);
/* check for port-groups */
result &= (SCRuleVarsGetConfVar("$HTTP_PORTS", SC_RULE_VARS_PORT_GROUPS) != NULL &&
strcmp(SCRuleVarsGetConfVar("$HTTP_PORTS", SC_RULE_VARS_PORT_GROUPS),
"80:81,88") == 0);
result &= (SCRuleVarsGetConfVar("$SHELLCODE_PORTS", SC_RULE_VARS_PORT_GROUPS) != NULL &&
strcmp(SCRuleVarsGetConfVar("$SHELLCODE_PORTS", SC_RULE_VARS_PORT_GROUPS),
"80") == 0);
result &= (SCRuleVarsGetConfVar("$ORACLE_PORTS", SC_RULE_VARS_PORT_GROUPS) != NULL &&
strcmp(SCRuleVarsGetConfVar("$ORACLE_PORTS", SC_RULE_VARS_PORT_GROUPS),
"1521") == 0);
result &= (SCRuleVarsGetConfVar("$SSH_PORTS", SC_RULE_VARS_PORT_GROUPS) != NULL &&
strcmp(SCRuleVarsGetConfVar("$SSH_PORTS", SC_RULE_VARS_PORT_GROUPS),
"22") == 0);
ConfDeInit();
ConfRestoreContextBackup();
return result;
}
/**
* \test Check that invalid address and port groups are properly handled by the
* API.
*/
int SCRuleVarsNegativeTest02(void)
{
int result = 1;
ConfCreateContextBackup();
ConfInit();
ConfYamlLoadString(dummy_conf_string, strlen(dummy_conf_string));
result &= (SCRuleVarsGetConfVar("$HOME_NETW", SC_RULE_VARS_ADDRESS_GROUPS) == NULL);
result &= (SCRuleVarsGetConfVar("$home_net", SC_RULE_VARS_ADDRESS_GROUPS) == NULL);
result &= (SCRuleVarsGetConfVar("$TOMCAT_PORTSW", SC_RULE_VARS_PORT_GROUPS) == NULL);
result &= (SCRuleVarsGetConfVar("$tomcat_ports", SC_RULE_VARS_PORT_GROUPS) == NULL);
ConfDeInit();
ConfRestoreContextBackup();
return result;
}
/**
* \test Check that Signatures with valid address and port groups are parsed
* without any errors by the Signature parsing API.
*/
int SCRuleVarsPositiveTest03(void)
{
int result = 0;
Signature *s = NULL;
DetectEngineCtx *de_ctx = NULL;
ConfCreateContextBackup();
ConfInit();
ConfYamlLoadString(dummy_conf_string, strlen(dummy_conf_string));
if ( (de_ctx = DetectEngineCtxInit()) == NULL)
goto end;
de_ctx->flags |= DE_QUIET;
/*
s = SigInit(de_ctx, "alert tcp $HTTP_SERVERS any -> any any (msg:\"Rule Vars Test\"; sid:1;)");
if (s == NULL)
goto end;
SigFree(s);
s = SigInit(de_ctx, "alert tcp $SMTP_SERVERS any -> $HTTP_SERVERS any (msg:\"Rule Vars Test\"; sid:1;)");
if (s == NULL)
goto end;
SigFree(s);
s = SigInit(de_ctx, "alert tcp $AIM_SERVERS any -> $AIM_SERVERS any (msg:\"Rule Vars Test\"; sid:1;)");
if (s == NULL)
goto end;
SigFree(s);
s = SigInit(de_ctx, "alert tcp $TELNET_SERVERS any -> any $SSH_PORTS (msg:\"Rule Vars Test\"; sid:1;)");
if (s == NULL)
goto end;
SigFree(s);
s = SigInit(de_ctx, "alert tcp $TELNET_SERVERS any -> any !$SSH_PORTS (msg:\"Rule Vars Test\"; sid:1;)");
if (s == NULL)
goto end;
SigFree(s);
s = SigInit(de_ctx, "alert tcp $TELNET_SERVERS 80 -> any !$SSH_PORTS (msg:\"Rule Vars Test\"; sid:1;)");
if (s == NULL)
goto end;
SigFree(s);
s = SigInit(de_ctx, "alert tcp $TELNET_SERVERS !80 -> any !$SSH_PORTS (msg:\"Rule Vars Test\"; sid:1;)");
if (s == NULL)
goto end;
SigFree(s);
s = SigInit(de_ctx, "alert tcp !$HTTP_SERVERS !80 -> any !$SSH_PORTS (msg:\"Rule Vars Test\"; sid:1;)");
if (s == NULL)
goto end;
SigFree(s);
s = SigInit(de_ctx, "alert tcp 192.168.1.2 any -> any $HTTP_PORTS (msg:\"Rule Vars Test\"; sid:1;)");
if (s == NULL)
goto end;
SigFree(s);
s = SigInit(de_ctx, "alert tcp !192.168.1.2 any -> any $HTTP_PORTS (msg:\"Rule Vars Test\"; sid:1;)");
if (s == NULL)
goto end;
SigFree(s);
s = SigInit(de_ctx, "alert tcp !192.168.1.2 any -> any !$HTTP_PORTS (msg:\"Rule Vars Test\"; sid:1;)");
if (s == NULL)
goto end;
SigFree(s);
s = SigInit(de_ctx, "alert tcp !192.168.1.2 any -> !$HTTP_SERVERS !$HTTP_PORTS (msg:\"Rule Vars Test\"; sid:1;)");
if (s == NULL)
goto end;
SigFree(s);
s = SigInit(de_ctx, "alert tcp !192.168.1.2 $HTTP_PORTS -> !$HTTP_SERVERS !$HTTP_PORTS (msg:\"Rule Vars Test\"; sid:1;)");
if (s == NULL)
goto end;
SigFree(s);
s = SigInit(de_ctx, "alert tcp [!192.168.24.0/23,!167.12.0.0/24] any -> any $HTTP_PORTS (msg:\"Rule Vars Test\"; sid:1;)");
if (s == NULL)
goto end;
SigFree(s);
s = SigInit(de_ctx, "alert tcp ![192.168.24.0/23,!167.12.0.0/24] any -> any $HTTP_PORTS (msg:\"Rule Vars Test\"; sid:1;)");
if (s == NULL)
goto end;
SigFree(s);
s = SigInit(de_ctx, "alert tcp [$HOME_NET,!192.168.1.2] $HTTP_PORTS -> !$HTTP_SERVERS !$HTTP_PORTS (msg:\"Rule Vars Test\"; sid:1;)");
if (s == NULL)
goto end;
SigFree(s);
s = SigInit(de_ctx, "alert tcp [[192.168.1.3,$EXTERNAL_NET],192.168.2.5] $HTTP_PORTS -> !$HTTP_SERVERS !$HTTP_PORTS (msg:\"Rule Vars Test\"; sid:1;)");
if (s == NULL)
goto end;
SigFree(s);
s = SigInit(de_ctx, "alert tcp [[192.168.1.3,$EXTERNAL_NET],192.168.2.5] $HTTP_PORTS -> !$HTTP_SERVERS [80,[!$HTTP_PORTS,$ORACLE_PORTS]] (msg:\"Rule Vars Test\"; sid:1;)");
if (s == NULL)
goto end;
SigFree(s);
*/
s = SigInit(de_ctx, "alert tcp [![192.168.1.3,$EXTERNAL_NET],[$HTTP_SERVERS,!$HOME_NET],192.168.2.5] $HTTP_PORTS -> !$HTTP_SERVERS [80,[!$HTTP_PORTS,$ORACLE_PORTS]] (msg:\"Rule Vars Test\"; sid:1;)");
if (s == NULL)
goto end;
SigFree(s);
result = 1;
end:
ConfDeInit();
ConfRestoreContextBackup();
if (de_ctx != NULL)
DetectEngineCtxFree(de_ctx);
return result;
}
/**
* \test Check that Signatures with invalid address and port groups, are
* are invalidated by the Singature parsing API.
*/
int SCRuleVarsNegativeTest04(void)
{
int result = 0;
Signature *s = NULL;
DetectEngineCtx *de_ctx = NULL;
ConfCreateContextBackup();
ConfInit();
ConfYamlLoadString(dummy_conf_string, strlen(dummy_conf_string));
if ( (de_ctx = DetectEngineCtxInit()) == NULL)
goto end;
de_ctx->flags |= DE_QUIET;
s = SigInit(de_ctx, "alert tcp $HTTP_SERVER any -> any any (msg:\"Rule Vars Test\"; sid:1;)");
if (s != NULL)
goto end;
s = SigInit(de_ctx, "alert tcp $http_servers any -> any any (msg:\"Rule Vars Test\"; sid:1;)");
if (s != NULL)
goto end;
SigFree(s);
s = SigInit(de_ctx, "alert tcp $http_servers any -> any $HTTP_PORTS (msg:\"Rule Vars Test\"; sid:1;)");
if (s != NULL)
goto end;
SigFree(s);
s = SigInit(de_ctx, "alert tcp !$TELNET_SERVERS !80 -> any !$SSH_PORTS (msg:\"Rule Vars Test\"; sid:1;)");
if (s != NULL)
goto end;
SigFree(s);
result = 1;
end:
ConfDeInit();
ConfRestoreContextBackup();
if (de_ctx != NULL)
DetectEngineCtxFree(de_ctx);
return result;
}
void SCRuleVarsRegisterTests(void)
{
#ifdef UNITTESTS
UtRegisterTest("SCRuleVarsPositiveTest01", SCRuleVarsPositiveTest01, 1);
UtRegisterTest("SCRuleVarsNegativeTest02", SCRuleVarsNegativeTest02, 1);
UtRegisterTest("SCRuleVarsPositiveTest03", SCRuleVarsPositiveTest03, 1);
UtRegisterTest("SCRuleVarsNegativeTest04", SCRuleVarsNegativeTest04, 1);
#endif
return;
}