⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rules.c

📁 该软件是一个有名的基于网络的入侵检测系统
💻 C
📖 第 1 页 / 共 5 页
字号:
/* $Id: rules.c,v 1.22 2000/03/16 02:58:44 roesch Exp $ */
/*
** Copyright (C) 1998,1999,2000 Martin Roesch <roesch@clark.net>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/


#include "rules.h"
ListHead Alert;      /* Alert Block Header */
ListHead Log;        /* Log Block Header */
ListHead Pass;       /* Pass Block Header */

RuleTreeNode *rtn_tmp;  /* temp data holder */
OptTreeNode *otn_tmp;   /* OptTreeNode temp ptr */

struct VarEntry *VarHead = NULL;

char *file_name;    /* current rules file being processed */
int file_line;      /* current line being processed in the rules file */
int list_file_line; /* current line being processed in the list file */
int rule_count;     /* number of rules generated */
int head_count;     /* number of header blocks (chain heads?) */
int opt_count;      /* number of chains */
int do_detect;


extern KeywordXlateList *KeywordList;             /* detection plugin keywords */
extern PreprocessKeywordList *PreprocessKeywords; /* preprocessor plugin keywords */
extern PreprocessFuncNode *PreprocessList;        /* Preprocessor function list */
extern OutputKeywordList *OutputKeywords;         /* Output plugin keyword list */
extern OutputFuncNode *AlertList;                 /* Alert function list */
extern OutputFuncNode *LogList;                   /* log function list */


#ifdef BENCHMARK
int check_count;    /* number of tests for a given rule to determine a match */
int cmpcount;       /* compare counter */
#endif


/****************************************************************************
 *
 * Function: ParseRulesFile(char *, int)
 *
 * Purpose:  Read the rules file a line at a time and send each rule to
 *           the rule parser
 *
 * Arguments: file => rules file filename
 *            inclevel => nr of stacked "include"s
 *
 * Returns: void function
 *
 ***************************************************************************/
void ParseRulesFile(char *file, int inclevel)
{
    FILE *thefp;       /* file pointer for the rules file */
    char buf[STD_BUF]; /* file read buffer */
    char *index;       /* buffer indexing pointer */
    char *stored_file_name = file_name;
    int  stored_file_line = file_line;

#ifdef DEBUG
    printf("Opening rules file: %s\n", file);
#endif
    if (inclevel == 0)
    {
        if ( !pv.quiet_flag )
        {
            printf("\n+++++++++++++++++++++++++++++++++++++++++++++++++++\n");
            printf("Initializing rule chains...\n");
        }
        file_name = strdup(file);
    }

    /* open the rules file */
    if ((thefp = fopen(file,"r")) == NULL)
    {
        FatalError( "ERROR: Unable to open rules file: %s\n", file);
    }

    /* clear the line buffer */
    bzero((char *)buf, STD_BUF);

    stored_file_line = file_line;
    stored_file_name = file_name;
    file_name = strdup(file);
    file_line = 0;

    /* loop thru each file line and send it to the rule parser */
    while ((fgets(buf, STD_BUF, thefp)) != NULL)
    {
        /* inc the line counter so the error messages know which line to 
           bitch about */
        file_line++;

        index = buf;


#ifdef DEBUG2
        printf("Got line %s (%d): %s", file_name, file_line, buf);
#endif
        /* if it's not a comment or a <CR>, send it to the parser */
        if ((*index != '#') && (*index != 0x0a) && (*index != ';') && (index != NULL))
        {
            /* advance through any whitespace at the beginning of the line */
            while (isspace((int) *index)) index++;

            ParseRule(index, inclevel);
        }

        bzero((char *)buf, STD_BUF);
    }

    if (file_name)
        free(file_name);
    file_name = stored_file_name;
    file_line = stored_file_line;

    if (inclevel == 0 && ! pv.quiet_flag )
    {
        printf("%d Snort rules read...\n", rule_count);
        printf("%d Option Chains linked into %d Chain Headers\n", opt_count, head_count);
        printf("+++++++++++++++++++++++++++++++++++++++++++++++++++\n\n");
    }

    fclose(thefp);

    if (inclevel == 0)
    {
#ifdef DEBUG
        DumpChain(Alert.TcpList, "Alert TCP Chains");
        DumpChain(Alert.UdpList, "Alert UDP Chains");
        DumpChain(Alert.IcmpList, "Alert ICMP Chains");


        DumpChain(Log.TcpList, "Log TCP Chains");
        DumpChain(Log.UdpList, "Log UDP Chains");
        DumpChain(Log.IcmpList, "Log ICMP Chains");


        DumpChain(Pass.TcpList, "Pass TCP Chains");
        DumpChain(Pass.UdpList, "Pass UDP Chains");
        DumpChain(Pass.IcmpList, "Pass ICMP Chains");

        if ( !pv.quiet_flag )
        {
            printf("Performing Rule List Integrity Tests...\n");
            printf("---------------------------------------\n");
        }

        IntegrityCheck(Alert.TcpList,"Alert TCP Chains" );
        IntegrityCheck(Alert.UdpList, "Alert UDP Chains");
        IntegrityCheck(Alert.IcmpList, "Alert ICMP Chains");

        IntegrityCheck(Log.TcpList, "Log TCP Chains");
        IntegrityCheck(Log.UdpList, "Log UDP Chains");
        IntegrityCheck(Log.IcmpList, "Log ICMP Chains");

        IntegrityCheck(Pass.TcpList, "Pass TCP Chains");
        IntegrityCheck(Pass.UdpList, "Pass UDP Chains");
        IntegrityCheck(Pass.IcmpList, "Pass ICMP Chains");
        if ( !pv.quiet_flag )
        {
            printf("---------------------------------------\n\n");
        }
#endif
    }

    return;
}



/****************************************************************************
 *
 * Function: ParseRule(char *, int)
 *
 * Purpose:  Process an individual rule and add it to the rule list
 *
 * Arguments: rule => rule string
 *            inclevel => nr of stacked "include"s
 *
 * Returns: void function
 *
 ***************************************************************************/
void ParseRule(char *prule, int inclevel)
{
    char **toks;          /* dbl ptr for mSplit call, holds rule tokens */
    int num_toks;         /* holds number of tokens found by mSplit */
    int rule_type;        /* rule type enumeration variable */
    char rule[1024];
    int protocol;
    RuleTreeNode proto_node;

    /* clean house */
    bzero((char *)&proto_node, sizeof(RuleTreeNode));

    /* chop off the <CR/LF> from the string */
    strip(prule);

    /* expand all variables */
    strcpy(rule, ExpandVars(prule));

    /* break out the tokens from the rule string */
    toks = mSplit(rule, " ", 10, &num_toks,0);

#ifdef DEBUG
    printf("[*] Rule start\n");
#endif

    /* figure out what we're looking at */
    rule_type = RuleType(toks[0]);

    proto_node.type = rule_type;

#ifdef DEBUG
    printf("Rule type: ");
#endif

    /* handle non-rule entries */
    switch (rule_type)
    {
        case RULE_PASS:
#ifdef DEBUG
            printf("Pass\n");
#endif
            break;

        case RULE_LOG:
#ifdef DEBUG
            printf("Log\n");
#endif
            break;

        case RULE_ALERT:
#ifdef DEBUG
            printf("Alert\n");
#endif
            break;

        case RULE_INCLUDE:
#ifdef DEBUG
            printf("Include\n");
#endif
            ParseRulesFile(toks[1], inclevel + 1);
            return;

        case RULE_VAR:
#ifdef DEBUG
            printf("Variable\n");
#endif
            VarDefine(toks[1], toks[2]);
            return;

        case RULE_PREPROCESS:
#ifdef DEBUG
            printf("Preprocessor\n");
#endif
            ParsePreprocessor(rule);
            return;

        case RULE_OUTPUT:
#ifdef DEBUG
            printf("Output Plugin\n");
#endif
            ParseOutputPlugin(rule);
            return;
    }

    /* set the rule protocol */
    protocol = WhichProto(toks[1]);

    /* Process the IP address and CIDR netmask */
    /* changed version 1.2.1 */
    /* "any" IP's are now set to addr 0, netmask 0, and the normal rules are 
       applied instead of checking the flag */
    /* if we see a "!<ip number>" we need to set a flag so that we can properly 
       deal with it when we are processing packets */
    if (*toks[2]=='!')  /* we found a negated address*/
    {
        proto_node.flags |= EXCEPT_SRC_IP;
        ParseIP(&toks[2][1], (u_long *) &proto_node.sip,
                (u_long *) &proto_node.smask);
    }
    else
    {
        ParseIP(toks[2], (u_long *) &proto_node.sip,
                (u_long *) &proto_node.smask);
    }

    /* do the same for the port */
    if (ParsePort(toks[3], (u_short *) &proto_node.hsp, 
                  (u_short *) &proto_node.lsp, toks[1], 
                  (int *) &proto_node.not_sp_flag))
    {
        proto_node.flags |= ANY_SRC_PORT;
    }

    if (proto_node.not_sp_flag)
        proto_node.flags |= EXCEPT_SRC_PORT;

    /* New in version 1.3: support for bidirectional rules */
    /* this checks the rule "direction" token and sets the bidirectional
       flag if the token = '<>' */
    if (!strncmp("<>", toks[4], 2))
    {
#ifdef DEBUG
        printf("Bidirectional rule!\n");
#endif
        proto_node.flags |= BIDIRECTIONAL;
    }

    /* changed version 1.2.1 */
    /* "any" IP's are now set to addr 0, netmask 0, and the normal rules are
        applied instead of checking the flag */
    /* if we see a "!<ip number>" we need to set a flag so that we can properly 
       deal with it when we are processing packets */
    if (*toks[5]=='!')  /*we found a negated address*/
    {
#ifdef DEBUG
        printf("setting exception flag for dest IP\n");
#endif
        proto_node.flags |= EXCEPT_DST_IP;
        ParseIP(&toks[5][1], (u_long *) &proto_node.dip,
                (u_long *) &proto_node.dmask);
    }
    else
        ParseIP(toks[5], (u_long *) &proto_node.dip,
                (u_long *) &proto_node.dmask);

    if (ParsePort(toks[6], (u_short *) &proto_node.hdp, 
                  (u_short *) &proto_node.ldp, toks[1], 
                  (int *) &proto_node.not_dp_flag))
    {
        proto_node.flags |= ANY_DST_PORT;
    }

    if (proto_node.not_dp_flag)
        proto_node.flags |= EXCEPT_DST_PORT;

#ifdef DEBUG
    printf("proto_node.flags = 0x%X\n", proto_node.flags);
#endif

    switch (rule_type)
    {
        case RULE_ALERT:
            ProcessHeadNode(&proto_node, &Alert, protocol); 
            break;

        case RULE_LOG:
            ProcessHeadNode(&proto_node, &Log, protocol); 
            break;

        case RULE_PASS:
            ProcessHeadNode(&proto_node, &Pass, protocol); 
            break;
    }

    rule_count++;
    ParseRuleOptions(rule, rule_type, protocol);

    free(toks);

    return;
}


/****************************************************************************
 *
 * Function: ProcessHeadNode(RuleTreeNode *, ListHead *, int)
 *
 * Purpose:  Process the header block info and add to the block list if 
 *           necessary
 *
 * Arguments: test_node => data generated by the rules parsers
 *            list => List Block Header refernece
 *            protocol => ip protocol
 *
 * Returns: void function
 *
 ***************************************************************************/
void ProcessHeadNode(RuleTreeNode *test_node, ListHead *list, int protocol)
{
    int match = 0;
    RuleTreeNode *rtn_idx;
    int count = 0;

    /* select the proper protocol list to attach the current rule to */
    switch (protocol)
    {
        case IPPROTO_TCP:
            rtn_idx =  list->TcpList; 
            break;

        case IPPROTO_UDP:
            rtn_idx =  list->UdpList; 
            break;

        case IPPROTO_ICMP:
            rtn_idx =  list->IcmpList; 
            break;

        default: rtn_idx = NULL;
            break;
    }

    /* if the list head is NULL (empty), make a new one and attach 
       the ListHead to it */
    if (rtn_idx == NULL)
    {
        head_count++;

        switch (protocol)
        {
            case IPPROTO_TCP:
                list->TcpList = (RuleTreeNode *) calloc(sizeof(RuleTreeNode), sizeof(char)); 
                rtn_tmp = list->TcpList;
                break;

            case IPPROTO_UDP:
                list->UdpList = (RuleTreeNode *) calloc(sizeof(RuleTreeNode), sizeof(char)); 
                rtn_tmp = list->UdpList;
                break;

            case IPPROTO_ICMP:
                list->IcmpList = (RuleTreeNode *) calloc(sizeof(RuleTreeNode), sizeof(char)); 
                rtn_tmp = list->IcmpList;
                break;
        }

        /* copy the prototype header data into the new node */
        XferHeader(test_node, rtn_tmp);

        rtn_tmp->head_node_number = head_count; 

        /* null out the down (options) pointer */
        rtn_tmp->down = NULL;

        /* add the function list to the new rule */
        SetupRTNFuncList(rtn_tmp);

        return;
    }

    /* see if this prototype node matches any of the existing header nodes */
    match = TestHeader(rtn_idx,test_node);

    while ((rtn_idx->right != NULL) && !match)
    {
        count++;
        match = TestHeader(rtn_idx,test_node);

        if (!match)
            rtn_idx = rtn_idx->right;
        else
            break;
    }

    /* have to check this twice since my loop above exits early, which sucks 
       but it's not performance critical */
    match = TestHeader(rtn_idx,test_node);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -