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

📄 sp_flowbits.c

📁 Linux snort-2.4.4源代码
💻 C
字号:
/*** $Id$**** sp_flowbits** ** Purpose:**** Wouldn't it be nice if we could do some simple state tracking ** across multiple packets?  Well, this allows you to do just that.**** Effect:**** - [Un]set a bitmask stored with the session** - Check the value of the bitmask**** Copyright (C) 2003 Sourcefire, Inc** ** 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 <stdlib.h>#include <string.h>#include <ctype.h>#include <sys/types.h>#include "rules.h"#include "decode.h"#include "plugbase.h"#include "parser.h"#include "debug.h"#include "util.h"#include "plugin_enum.h"#include "snort.h"#include "flow.h"#include "bitop.h"#include "sfghash.h"#include "flow/flow.h"#include "spp_flow.h"/****  The FLOWBITS_OBJECT is used to track the different**  flowbit names that set/unset/etc. bits.  We use these**  so that we can verify that the rules that use flowbits**  make sense.****  The types element tracks all the different operations that**  may occur for a given object.  This is different from how**  the type element is used from the FLOWBITS_ITEM structure.*/typedef struct _FLOWBITS_OBJECT{    u_int32_t id;    u_int8_t  types;} FLOWBITS_OBJECT;/****  This structure is the context ptr for each detection option**  on a rule.  The id is associated with a FLOWBITS_OBJECT id.****  The type element track only one operation.*/typedef struct _FLOWBITS_OP{    u_int32_t id;    u_int8_t  type;        /* Set, Unset, Invert, IsSet, IsNotSet, Reset  */} FLOWBITS_OP;#define FLOWBITS_SET       0x01  #define FLOWBITS_UNSET     0x02#define FLOWBITS_TOGGLE    0x04#define FLOWBITS_ISSET     0x08#define FLOWBITS_ISNOTSET  0x10#define FLOWBITS_RESET     0x20#define FLOWBITS_NOALERT   0x40extern unsigned int giFlowbitSize;static u_int32_t flowbits_count = 0;static SFGHASH *flowbits_hash;static void FlowBitsInit(char *, OptTreeNode *, int);static void FlowBitsParse(char *, FLOWBITS_OP *, OptTreeNode *);static int  FlowBitsCheck(Packet *, struct _OptTreeNode *, OptFpList *);/**************************************************************************** *  * Function: SetupFlowBits() * * Purpose: Generic detection engine plugin template.  Registers the *          configuration function and links it to a rule keyword.  This is *          the function that gets called from InitPlugins in plugbase.c. * * Arguments: None. * * Returns: void function * * 3/4/05 - man beefed up the hash table size from 100 -> 10000 * ****************************************************************************/void SetupFlowBits(){    /* setup our storage hash */    flowbits_hash = sfghash_new( 10000, 0 , 0, 0);    if (!flowbits_hash) {        FatalError("Could not setup flowbits hash\n");    }    /* map the keyword to an initialization/processing function */    RegisterPlugin("flowbits", FlowBitsInit);    DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Plugin: FlowBits Setup\n"););}/**************************************************************************** *  * Function: FlowBitsInit(char *, OptTreeNode *) * * Purpose: Configure the flow init option to register the appropriate checks * * Arguments: data => rule arguments/data *            otn => pointer to the current rule option list node * * Returns: void function * ****************************************************************************/static void FlowBitsInit(char *data, OptTreeNode *otn, int protocol){    FLOWBITS_OP *flowbits;    OptFpList *fpl;     if(!SppFlowIsRunning())    {        LogMessage("Warning: %s (%d) => flowbits without flow.  flow must be enabled for this plugin.\n", file_name,file_line);    }    flowbits = (FLOWBITS_OP *) SnortAlloc(sizeof(FLOWBITS_OP));    if (!flowbits) {        FatalError("%s (%d): Unable to allocate flowbits node\n", file_name,                file_line);    }    FlowBitsParse(data, flowbits, otn);    fpl = AddOptFuncToList(FlowBitsCheck, otn);    /*     * attach it to the context node so that we can call each instance      * individually     */        fpl->context = (void *) flowbits;    return;}/**************************************************************************** *  * Function: FlowBitsParse(char *, FlowBits *flowbits, OptTreeNode *) * * Purpose: parse the arguments to the flow plugin and alter the otn *          accordingly * * Arguments: otn => pointer to the current rule option list node * * Returns: void function * ****************************************************************************/static void FlowBitsParse(char *data, FLOWBITS_OP *flowbits, OptTreeNode *otn){    FLOWBITS_OBJECT *flowbits_item;    char *token, *str, *p;    u_int32_t id = 0;    int hstatus;    DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "flowbits parsing %s\n",data););        str = strdup(data);    if(str == NULL)    {        FatalError("ParseFlowArgs: Can't strdup data\n");    }    p = str;    /* nuke leading whitespace */    while(isspace((int)*p)) p++;    token = strtok(p, ",");    if(!token)    {        FatalError("%s(%d) ParseFlowArgs: Must specify flowbits operation.",                file_name, file_line);    }    while(isspace((int)*token))        token++;    if(!strncasecmp("set",token,3))    {        flowbits->type = FLOWBITS_SET;    }     else if(!strncasecmp("unset",token,5))    {        flowbits->type = FLOWBITS_UNSET;    }    else if(!strncasecmp("toggle",token,6))    {        flowbits->type = FLOWBITS_TOGGLE;    }    else if(!strncasecmp("isset",token,5))    {        flowbits->type = FLOWBITS_ISSET;    }    else if(!strncasecmp("isnotset",token,8))    {        flowbits->type = FLOWBITS_ISNOTSET;    }     else if(!strncasecmp("noalert", token, 7))    {        if(strtok(NULL, " ,\t"))        {            FatalError("%s (%d): Do not specify a flowbits tag id for the "                       "keyword 'noalert'.\n", file_name, file_line);        }        flowbits->type = FLOWBITS_NOALERT;        flowbits->id   = 0;        free(str);        return;    }    else if(!strncasecmp("reset",token,5))    {        if(strtok(NULL, " ,\t"))        {            FatalError("%s (%d): Do not specify a flowbits tag id for the "                       "keyword 'reset'.\n", file_name, file_line);        }        flowbits->type = FLOWBITS_RESET;        flowbits->id   = 0;        free(str);        return;    }     else    {        FatalError("%s(%d) ParseFlowArgs: Invalid token %s\n",                file_name, file_line, token);    }    /*    **  Let's parse the flowbits name    */    token = strtok(NULL, " ,\t");    if(!token || !strlen(token))    {        FatalError("%s (%d): flowbits tag id must be provided\n",                file_name, file_line);    }    /*    **  Take space from the beginning    */    while(isspace((int)*token))         token++;    /*    **  Do we still have a ID tag left.    */    if (!strlen(token))    {        FatalError("%s (%d): flowbits tag id must be provided\n",                file_name, file_line);    }    /*    **  Is there a anything left?    */    if(strtok(NULL, " ,\t"))    {        FatalError("%s (%d): flowbits tag id cannot include spaces or "                   "commas.\n", file_name, file_line);    }        flowbits_item = (FLOWBITS_OBJECT *)sfghash_find(flowbits_hash, token);    if (flowbits_item)     {        flowbits_item->types |= flowbits->type;        id = flowbits_item->id;    }     else    {        flowbits_item =             (FLOWBITS_OBJECT *)SnortAlloc(sizeof(FLOWBITS_OBJECT));        flowbits_item->id = flowbits_count;        flowbits_item->types |= flowbits->type;        hstatus = sfghash_add( flowbits_hash, token, flowbits_item);        if(hstatus)         {            FatalError("Could not add flowbits key (%s) to hash",token);        }        id = flowbits_count;        flowbits_count++;        if(flowbits_count >= (giFlowbitSize<<3) )        {            FatalError("FLOWBITS ERROR: The number of flowbit IDs in the "                       "current ruleset (%d) exceed the maximum number of IDs "                       "that are allowed (%d).\n", flowbits_count,giFlowbitSize<<3);        }    }    flowbits->id = id;    free(str);}static int ResetFlowbits(Packet *p){    Session *ssn;    if(!p || !p->ssnptr)    {        return 0;    }    ssn = p->ssnptr;    /*    **  Check session_flags for new TCP session    **    **  PKT_STREAM_EST is pretty obvious why it's in here    **    **  SEEN_CLIENT and SEEN_SERVER allow us to only reset the bits    **  once on the first SYN pkt.  There after bits will be    **  accumulated for that session.    */    if((p->packet_flags & PKT_STREAM_EST) ||       ((ssn->session_flags & (SSNFLAG_SEEN_CLIENT | SSNFLAG_SEEN_SERVER)) ==         (SSNFLAG_SEEN_CLIENT | SSNFLAG_SEEN_SERVER)))    {        return 0;    }    return 1;}/***  NAME**    GetFlowbitsData::*//****  This function initializes/retrieves flowbits data that is associated**  with a given flow.*/static FLOWDATA *GetFlowbitsData(Packet *p){    FLOW     *fp;    FLOWDATA *flowdata;    if(!p->flow)    {        return NULL;    }    fp = (FLOW *)p->flow;    flowdata = &(fp->data);    if(!flowdata)        return NULL;    /*    **  Since we didn't initialize BITOP (which resets during init)    **  we have to check for resetting here, because it may be    **  a new flow.    **    **  NOTE:    **    We can only do this on TCP flows because we know when a    **    connection begins and ends.  So that's what we check.    */    if(ResetFlowbits(p))    {        boResetBITOP(&(flowdata->boFlowbits));    }    return flowdata;}/**************************************************************************** *  * Function: FlowBitsCheck(Packet *, struct _OptTreeNode *, OptFpList *) * * Purpose: Check flow bits foo  * * Arguments: data => argument data *            otn => pointer to the current rule's OTN * * Returns: 0 on failure * ****************************************************************************/static int FlowBitsCheck(Packet *p,struct _OptTreeNode *otn, OptFpList *fp_list){    FLOWBITS_OP *flowbits;   /* pointer to the eval struct */    FLOWDATA *flowdata;    int result = 0;    if(!p)    {        DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,                    "FLOWBITSCHECK: No pkt."););        return 0;    }    flowdata = GetFlowbitsData(p);    if(!flowdata)    {        DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "No FLOWBITS_DATA"););        return 0;    }    flowbits = (FLOWBITS_OP *) fp_list->context;    DEBUG_WRAP    (        DebugMessage(DEBUG_PLUGIN,"flowbits: type = %d\n",flowbits->type);        DebugMessage(DEBUG_PLUGIN,"flowbits: value = %d\n",flowbits->id);    );    switch(flowbits->type)    {        case FLOWBITS_SET:            boSetBit(&(flowdata->boFlowbits),flowbits->id);            result = 1;            break;        case FLOWBITS_UNSET:            boClearBit(&(flowdata->boFlowbits),flowbits->id);            result = 1;            break;        case FLOWBITS_RESET:            boResetBITOP(&(flowdata->boFlowbits));            result = 1;            break;        case FLOWBITS_ISSET:            if(boIsBitSet(&(flowdata->boFlowbits),flowbits->id))            {                result = 1;            }            break;        case FLOWBITS_ISNOTSET:            if (boIsBitSet(&(flowdata->boFlowbits),flowbits->id))            {                result = 0;            }            else            {                result = 1;            }            break;        case FLOWBITS_TOGGLE:            if (boIsBitSet(&(flowdata->boFlowbits),flowbits->id))            {                boClearBit(&(flowdata->boFlowbits),flowbits->id);            }            else            {                boSetBit(&(flowdata->boFlowbits),flowbits->id);            }            result = 1;            break;        case FLOWBITS_NOALERT:            /*            **  This logic allows us to put flowbits: noalert any where            **  in the detection chain, and still do bit ops after this            **  option.            */            fp_list->next->OptTestFunc(p, otn, fp_list->next);            return 0;        default:            /*            **  Always return failure here.            */            return 0;    }        /*    **  Now return what we found    */    if (result == 1)    {        return fp_list->next->OptTestFunc(p, otn, fp_list->next);    }    return 0;}/**************************************************************************** *  * Function: FlowBitsVerify() * * Purpose: Check flow bits foo to make sure its valid * * Arguments:  * * Returns: 0 on failure * ****************************************************************************/void FlowBitsVerify(void){    SFGHASH_NODE * n;    FLOWBITS_OBJECT *fb;    for (n = sfghash_findfirst(flowbits_hash);          n != 0;          n= sfghash_findnext(flowbits_hash))    {        fb = (FLOWBITS_OBJECT *)n->data;        if (fb->types & FLOWBITS_SET) {            if (!(fb->types & FLOWBITS_ISSET || fb->types & FLOWBITS_ISNOTSET))            {                LogMessage("Warning: flowbits key '%s' is set but not ever checked.\n",n->key);            }        } else {            if (fb->types & FLOWBITS_ISSET || fb->types & FLOWBITS_ISNOTSET) {                LogMessage("Warning: flowbits key '%s' is checked but not ever set.\n",n->key);            }        }    }}

⌨️ 快捷键说明

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