snort 源码分析之规则文件解析- ipvar变量

snort的规则文件系统中包含很多配置,其中一些配置依赖于其他的配置项,使得snort规则解析分为两步,第一步解析配置的变量。

例如ipvar HOME_NET any  这是一个ip变量的设置,关键字ipvar 、HOME_NET :变量名、any :变量值;定义完之后,就可以在规则中使用,例如

alert tcp $EXTERNAL_NET any -> $HOME_NET $HTTP_PORTS (msg:"APP-DETECT Acunetix web vulnerability scan attempt"; flow:to_server,established; flowbits:set,acunetix-scan; content:"Acunetix-"; fast_pattern:only; http_header; metadata:service http; reference:url,www.acunetix.com; classtype:web-application-attack; sid:25358; rev:3;)
其中的红色部分就是使用的方式,在变量名中需要加上$。

下面以源码的形式进行分析解析变量的动作,snort中每个变量的关键字一般会在parser.h中以宏的方式定义,例如:

# define SNORT_CONF_KEYWORD__IPVAR               "ipvar"
该关键字对应的解析函数会放置在一个叫snort_conf_keywords的数组中,在解析配置文件的时候,会遍历这个数组进行解析


typedef struct _KeywordFunc
{
    char *name;/* 关键字 例如 ipvar*/
    KeywordType type; /* 类型:规则配置、主配置、 所有*/
    int expand_vars; /* */
    int default_policy_only;
    ParseFunc parse_func; /* 配置的解析函数类型*/

} KeywordFunc;

static const KeywordFunc snort_conf_keywords[] =
{
...
    { SNORT_CONF_KEYWORD__IPVAR,             KEYWORD_TYPE__MAIN, 0, 0, ParseIpVar },
...
};

下面是解析ipvar的函数实现

/*
 * sc : snort的配置对象
 * p  : snort 的策略,实际内容保存它的ip_vartable属性中
 * args : 配置项内容(除关键字)
 */
static void ParseIpVar(SnortConfig *sc, SnortPolicy *p, char *args)
{
    char **toks;
    int num_toks;
    int ret;
...
    /* 通过上面的例子可以知道 ipvar的配置只有两项,所以如果切分的结果不等于二,说明有问题,报错退出程序,并在日志文件或者终端,显示错信息,具体到配置文件的名字和行号,方便调试*/
    toks = mSplit(args, " \t", 0, &num_toks, 0);
    if (num_toks != 2)
    {
        ParseError("Missing argument to %s", toks[0]);
    }

    /* Check command line variables to see if this has already
     * been defined */
    /* 检查命令行中是否已经定义该变量,如果已定义,抛弃配置文件的定义*/
    if (cmd_line_var_list != NULL)
    {
        VarNode *tmp = cmd_line_var_list;

        while (tmp != NULL)
        {
            /* Already defined this via command line */
            if (strcasecmp(toks[0], tmp->name) == 0)
            {
                mSplitFree(&toks, num_toks);
                return;
            }

            tmp = tmp->next;
        }
    }

    DisallowCrossTableDuplicateVars(sc, toks[0], VAR_TYPE__IPVAR);

    /* 检查是否定义过该变量,如果定义过,或者语法错误,报错退出,如果未定义,将该变量保存到策略p->ip_vartable属性的链表中*/
    if((ret = sfvt_define(p->ip_vartable, toks[0], toks[1])) != SFIP_SUCCESS)
    {
        switch(ret) {
            case SFIP_ARG_ERR:
                ParseError("The following is not allowed: %s.", toks[1]);
                break;

            case SFIP_DUPLICATE:
                ParseMessage("Var '%s' redefined.", toks[0]);
                break;

            case SFIP_CONFLICT:
                ParseError("Negated IP ranges that are more general than "
                        "non-negated ranges are not allowed. Consider "
                        "inverting the logic in %s.", toks[0]);
                break;

            case SFIP_NOT_ANY:
                ParseError("!any is not allowed in %s.", toks[0]);
                break;

            default:
                ParseError("Failed to parse the IP address: %s.", toks[1]);
        }
    }

    mSplitFree(&toks, num_toks);
}

这样ipvar的解析就算完成了。

接下来看一下规则中怎么使用的

/* 解析规则时,使用ProcessIP解析IP字段 */
static void ParseRule(SnortConfig *sc, SnortPolicy *p, char *args,
                      RuleType rule_type, ListHead *list)
{
...
        ProcessIP(sc, toks[4], &test_rtn, DST, 0);

}



/* 在这个里面使用sfvt_lookup_var查询addr这个变量是否在ip_vartable是否存在,如果存在,规则头rtn->sip对变量内容进行深拷贝, 不存在,进行解析,并加入变量链表*/
static int ProcessIP(SnortConfig *sc, char *addr, RuleTreeNode *rtn, int mode, int neg_list)
{
    vartable_t *ip_vartable = sc->targeted_policies[getParserPolicy(sc)]->ip_vartable;
...
    if(mode == SRC)
    {
        int ret;

        if (rtn->sip == NULL)
        {
            sfip_var_t *tmp = sfvt_lookup_var(ip_vartable, addr);
            if (tmp != NULL)
            {
                rtn->sip = sfvar_create_alias(tmp, tmp->name);
                if (rtn->sip == NULL)
                    ret = SFIP_FAILURE;
                else
                    ret = SFIP_SUCCESS;
            }
            else
            {
                rtn->sip = (sfip_var_t *)SnortAlloc(sizeof(sfip_var_t));
                ret = sfvt_add_to_var(ip_vartable, rtn->sip, addr);
            }
        }
     ...
    }
    /* mode == DST */
    else
    {
...    
    }
...

    return 0;
}

 

你可能感兴趣的:(规则,snort)