Esempio n. 1
0
/*
*
*/
#ifndef WIN32  /* To avoid naming conflict, Win32 will use the hbm_prep() in mwm.c */
HBM_STRUCT * hbm_prep(unsigned char * pat, int m)
{
    HBM_STRUCT    *p;

    p = (HBM_STRUCT*)SnortAlloc(sizeof(HBM_STRUCT));

    if( !hbm_prepx( p, pat, m ) )
    {
        FatalError("Error initializing pattern matching. Check arguments.");
    }

    return p;
}
Esempio n. 2
0
/*
**  Set default values
*/
EventQueueConfig * EventQueueConfigNew(void)
{
    EventQueueConfig *eq =
        (EventQueueConfig *)SnortAlloc(sizeof(EventQueueConfig));

    eq->max_events = 8;
    eq->log_events = 3;

    eq->order = SNORT_EVENTQ_CONTENT_LEN;
    eq->process_all_events = 0;

    return eq;
}
Esempio n. 3
0
File: sfthd.c Progetto: anarey/snort
/*!
Add a permanent threshold object to the threshold table. Multiple
objects may be defined for each gen_id and sig_id pair. Internally
a unique threshold id is generated for each pair.

Threshold objects track the number of events seen during the time
interval specified by seconds. Depending on the type of threshold
object and the count value, the thresholding object determines if
the current event should be logged or dropped.

@param thd Threshold object from sfthd_new()
@param gen_id Generator id
@param sig_id Signauture id
@param tracking Selects tracking by src ip or by dst ip
@param type  Thresholding type: Limit, Threshold, or Limt+Threshold, Suppress
@param priority Assigns a relative priority to this object, higher numbers imply higher priority

@param count Number of events
@param seconds Time duration over which this threshold object acts.
@param ip      IP address, for supression
@param ip-mask IP mask, applied with ip_mask, for supression

@return integer
@retval  0 successfully added the thresholding object
@retval !0 failed

 --- Local and Global Thresholding is setup here  ---

*/
int sfthd_create_threshold(SnortConfig *sc,
                           ThresholdObjects *thd_objs,
                           unsigned gen_id,
                           unsigned sig_id,
                           int tracking,
                           int type,
                           int priority,
                           int count,
                           int seconds,
                           IpAddrSet* ip_address,
                           IpAddrSet* dst_ip_address)
{
    //allocate memory fpr sfthd_array if needed.
    tSfPolicyId policyId = getParserPolicy(sc);
    THD_NODE sfthd_node;
    memset(&sfthd_node, 0, sizeof(sfthd_node));

    thd_objs->count++;

    sfthd_node.thd_id    = thd_objs->count;  /* produce a unique thd_id for this node */
    sfthd_node.gen_id    = gen_id;
    sfthd_node.sig_id    = sig_id;
    sfthd_node.tracking  = tracking; /* by_src, by_dst */
    sfthd_node.type      = type;
    sfthd_node.priority  = priority;
    sfthd_node.count     = count;
    sfthd_node.seconds   = seconds;
    sfthd_node.ip_address= ip_address;
    sfthd_node.dst_ip_address= dst_ip_address;

    sfDynArrayCheckBounds ((void **)&thd_objs->sfthd_garray, policyId, &thd_objs->numPoliciesAllocated);
    if (thd_objs->sfthd_garray[policyId] == NULL)
    {
        thd_objs->sfthd_garray[policyId] = SnortAlloc(THD_MAX_GENID * sizeof(THD_NODE *));
        if (thd_objs->sfthd_garray[policyId] == NULL)
        {
            return -1;
        }
    }

    if( sig_id == 0 )
    {
        return sfthd_create_threshold_global(sc, thd_objs, &sfthd_node);
    }

    if( gen_id == 0 )
        return -1;

    return sfthd_create_threshold_local(sc, thd_objs, &sfthd_node);
}
Esempio n. 4
0
IPSET * ipset_new( int family )
{
    IPSET * p = (IPSET *)SnortAlloc( sizeof(IPSET));

    if( family == IPV4_FAMILY )
    {
        ipset_init( p );
    }
    else
    {
        ipset6_init( p );
    }

    return p;
}
Esempio n. 5
0
/**
**  Initialize the event queue.  Provide the max number of nodes that this
**  queue will support, the number of top nodes to log in the queue, the
**  size of the event structure that the user will fill in, and the function
**  to determine where to insert the incoming events in the queue.
**
**  @return integer
**
**  @retval -1 failure
**  @retval  0 success
*/
SF_EVENTQ * sfeventq_new(int max_nodes, int log_nodes, int event_size, 
                         int (*sort)(void *, void *))
{
    SF_EVENTQ *eq;

    if(max_nodes <= 0 || log_nodes <= 0 || event_size <= 0 ) /* || !sort) Jan06 -- not required */
        return NULL;

    eq = (SF_EVENTQ *)SnortAlloc(sizeof(SF_EVENTQ));

    /* Initialize the memory for the nodes that we are going to use. */
    eq->node_mem = (SF_EVENTQ_NODE *)SnortAlloc(sizeof(SF_EVENTQ_NODE) * max_nodes);
    eq->event_mem = (char *)SnortAlloc(event_size * (max_nodes + 1));

    eq->max_nodes = max_nodes;
    eq->log_nodes = log_nodes;
    eq->event_size = event_size;
    eq->sort = sort;
    eq->cur_nodes = 0;
    eq->cur_events = 0;
    eq->reserve_event = (void *)(&eq->event_mem[max_nodes * eq->event_size]);

    return eq;
}
Esempio n. 6
0
RBMQ *RBMQ_Alloc(uint32_t msg_ring_entries, uint16_t msg_ring_header_size, uint32_t data_ring_size)
{
    RBMQ *mq;

    mq = SnortAlloc(sizeof(RBMQ));
    memset(mq, 0, sizeof(RBMQ));

    /* Initialize the control ring. */
    mq->msg_ring.msgs = SnortAlloc(msg_ring_entries * sizeof(RBMQ_Msg));
    mq->msg_ring.headers = SnortAlloc(msg_ring_entries * msg_ring_header_size);
    mq->msg_ring.entries = msg_ring_entries;
    mq->msg_ring.header_size = msg_ring_header_size;
    memset(mq->msg_ring.msgs, 0, mq->msg_ring.entries * sizeof(RBMQ_Msg));
    mq->msg_ring.last_reserved = 0;
    mq->msg_ring.last_read = 0;
    mq->msg_ring.last_acked = 0;

    /* Initialize the data ring. */
    mq->data_ring.data = SnortAlloc(data_ring_size);
    mq->data_ring.size = data_ring_size;
    memset(mq->data_ring.data, 0, mq->data_ring.size);

    return mq;
}
Esempio n. 7
0
FileContext* create_file_context(void *ssnptr)
{
    FileSession *file_session;
    FileContext *context = file_context_create();

    /* Create file session if not yet*/
    file_session = get_file_session (ssnptr);
    if(!file_session)
    {
        file_session = (FileSession *)SnortAlloc(sizeof(*file_session));
        session_api->set_application_data(ssnptr, PP_FILE, file_session,
                file_session_free);
    }
    file_stats.files_total++;
    return context;
}
static int ConvertByteJumpOption(Rule *rule, int index, OptTreeNode *otn)
{
    ByteData *byte = rule->options[index]->option_u.byte;
    ByteJumpData *byte_jump = SnortAlloc(sizeof(ByteJumpData));
    OptFpList *fpl;
    void *dup;

    byte_jump->bytes_to_grab = byte->bytes;
    byte_jump->offset = byte->offset;
    byte_jump->offset_var = GetVarByName(byte->offset_refId);
    byte_jump->multiplier = byte->multiplier;
    byte_jump->post_offset = byte->post_offset;

    if (byte->flags & CONTENT_RELATIVE)
        byte_jump->relative_flag = 1;
    if (byte->flags & EXTRACT_AS_STRING)
        byte_jump->data_string_convert_flag = 1;
    if (byte->flags & JUMP_FROM_BEGINNING)
        byte_jump->from_beginning_flag = 1;
    if (byte->flags & JUMP_ALIGN)
        byte_jump->align_flag = 1;
    if (byte->flags & BYTE_BIG_ENDIAN)
        byte_jump->endianess = BIG;
    else
        byte_jump->endianess = LITTLE;
    if (byte->flags & EXTRACT_AS_HEX)
        byte_jump->base = 16;
    if (byte->flags & EXTRACT_AS_DEC)
        byte_jump->base = 10;
    if (byte->flags & EXTRACT_AS_OCT)
        byte_jump->base = 8;

    fpl = AddOptFuncToList(ByteJump, otn);
    fpl->type = RULE_OPTION_TYPE_BYTE_JUMP;
    if (add_detection_option(RULE_OPTION_TYPE_BYTE_JUMP, (void *)byte_jump, &dup) == DETECTION_OPTION_EQUAL)
    {
        free(byte_jump);
        byte_jump = dup;
    }
    fpl->context = (void *)byte_jump;

    if (byte_jump->relative_flag == 1)
        fpl->isRelative = 1;

    return 1;
}
tSfActionQueueId sfActionQueueInit(
        int queueLength
        )
{
    tSfActionQueue *queue = SnortAlloc(sizeof(tSfActionQueue));
    if (queue)
    {
        if (mempool_init(&queue->mempool,
                queueLength, sizeof(tSfActionNode)) != 0)
        {
            FatalError("%s(%d) Could not initialize action queue memory pool.\n",
                    __FILE__, __LINE__);
        }
    }

    return queue;
}
Esempio n. 10
0
/*Only set the pointer for performance, no deep copy*/
void file_name_set (FileContext *context, uint8_t *file_name, uint32_t name_size,
        bool save_in_context)
{
    uint8_t *name = file_name;
    if (!context)
        return;
    if (save_in_context)
    {
        if (context->file_name && context->file_name_saved)
            free(context->file_name);
        name = SnortAlloc(name_size);
        memcpy(name, file_name, name_size);
        context->file_name_saved = true;
    }
    context->file_name = name;
    context->file_name_size = name_size;
}
static void Asn1Init(char *data, OptTreeNode *otn, int protocol)
{
    ASN1_CTXT *asn1;
    OptFpList *ofl;

    /* 
     * allocate the data structure and attach 
     * it to the rule's data struct list 
     */
    asn1 = (ASN1_CTXT *)SnortAlloc(sizeof(ASN1_CTXT));
    memset(asn1, 0x00, sizeof(ASN1_CTXT));

    Asn1RuleParse(data, otn, asn1);

    ofl = AddOptFuncToList(Asn1Detect, otn);

    ofl->context = (void *)asn1;
}
Esempio n. 12
0
void file_signature_sha256(FileContext* context, uint8_t* file_data,
        int size, FilePosition position)
{
    int data_size;

    if (!context)
        return;

    data_size = get_data_size_from_depth_limit(context, SNORT_FILE_SHA256, size);

    if (data_size != size)
    {
        context->file_state.sig_state = FILE_SIG_DEPTH_FAIL;
        return;
    }

    switch (position)
    {
    case SNORT_FILE_START:
        if (!context->file_signature_context)
            context->file_signature_context = SnortAlloc(sizeof(SHA256CONTEXT));
        SHA256INIT((SHA256CONTEXT *)context->file_signature_context);
        SHA256UPDATE((SHA256CONTEXT *)context->file_signature_context, file_data, data_size);
        break;
    case SNORT_FILE_MIDDLE:
        if (!context->file_signature_context)
            context->file_signature_context = SnortAlloc(sizeof(SHA256CONTEXT));
        SHA256UPDATE((SHA256CONTEXT *)context->file_signature_context, file_data, data_size);
        break;
    case SNORT_FILE_END:
        if (!context->file_signature_context)
            context->file_signature_context = SnortAlloc(sizeof(SHA256CONTEXT));
        if (context->processed_bytes == 0)
            SHA256INIT((SHA256CONTEXT *)context->file_signature_context);
        SHA256UPDATE((SHA256CONTEXT *)context->file_signature_context, file_data, data_size);
        context->sha256 = SnortAlloc(SHA256_HASH_SIZE);
        SHA256FINAL(context->sha256, (SHA256CONTEXT *)context->file_signature_context);
        context->file_state.sig_state = FILE_SIG_DONE;
        break;
    case SNORT_FILE_FULL:
        if (!context->file_signature_context)
            context->file_signature_context = SnortAlloc(sizeof (SHA256CONTEXT));
        SHA256INIT((SHA256CONTEXT *)context->file_signature_context);
        SHA256UPDATE((SHA256CONTEXT *)context->file_signature_context, file_data, data_size);
        context->sha256 = SnortAlloc(SHA256_HASH_SIZE);
        SHA256FINAL(context->sha256, (SHA256CONTEXT *)context->file_signature_context);
        context->file_state.sig_state = FILE_SIG_DONE;
        break;
    default:
        break;
    }
}
Esempio n. 13
0
static int SCRegisterHandler(SCHandler **handlers, uint16_t type, SCMProcessMsgFunc processMsgFunc, void *data)
{
    SCHandler *handler;

    if (!ScSideChannelEnabled())
        return 0;

    handler = SnortAlloc(sizeof(SCHandler));

    handler->next = NULL;
    handler->type = type;
    handler->processMsgFunc = processMsgFunc;
    handler->data = data;

    handler->next = *handlers;
    *handlers = handler;

    return 0;
}
Esempio n. 14
0
static void SetGzipBuffers(HttpSessionData *hsd, HI_SESSION *session)
{
    if ((hsd != NULL) && (hsd->decomp_state == NULL)
            && (session != NULL) && (session->server_conf != NULL)
            && (session->global_conf != NULL) && session->server_conf->extract_gzip)
    {
        MemBucket *bkt = mempool_alloc(hi_gzip_mempool);

        if (bkt != NULL)
        {
            hsd->decomp_state = (DECOMPRESS_STATE *)SnortAlloc(sizeof(DECOMPRESS_STATE));
            hsd->decomp_state->gzip_bucket = bkt;
            hsd->decomp_state->compr_depth = session->global_conf->compr_depth;
            hsd->decomp_state->decompr_depth = session->global_conf->decompr_depth;
            hsd->decomp_state->compr_buffer = (unsigned char *)bkt->data;
            hsd->decomp_state->decompr_buffer = (unsigned char *)bkt->data + session->global_conf->compr_depth;
            hsd->decomp_state->inflate_init = 0;
        }
    }
}
Esempio n. 15
0
/**
 * Respond2 initialization function
 *
 * @param data argument passed to the resp keyword
 * @param otn pointer to an OptTreeNode structure
 * @param protocol Snort rule protocol (IP/TCP/UDP)
 *
 * @return void function
 */
static void Respond2Init(char *data, OptTreeNode *otn, int protocol) 
{
    static int setup = 0;
    RespondData *rd = NULL;

    if (!(protocol & (IPPROTO_ICMP | IPPROTO_TCP | IPPROTO_UDP)))
        FatalError("%s: %s(%d): Can't respond to IP protocol rules.\n", 
                MODNAME, file_name, file_line);

    rd = (RespondData *)SnortAlloc(sizeof(RespondData));

    if (!setup)
    {
        SetLinkInfo();      /* setup link-layer pointer arithmetic info */
        SetRespAttempts(&config);       /* configure # of TCP attempts */
        SetRespCacheRows(&config);      /* configure # of rows in cache */
        SetRespCacheMemcap(&config);    /* configure response cache memcap */

        if ((respcache_init(&respcache, &config)) != 0)
            FatalError("%s: Unable to allocate hash table memory.\n", MODNAME);

        /* Open raw socket or network device before Snort drops privileges */
        if (link_offset)
        {
            if (config.ethdev == NULL)     /* open link-layer device */
            {
                if ((config.ethdev = eth_open(pv.respond2_ethdev)) == NULL)
                    FatalError("%s: Unable to open link-layer device: %s.\n", 
                            MODNAME, pv.respond2_ethdev);
            }
            DEBUG_WRAP(
                    DebugMessage(DEBUG_PLUGIN, "%s: using link-layer "
                            "injection on interface %s\n", MODNAME,
                            pv.respond2_ethdev);
                    DebugMessage(DEBUG_PLUGIN, "%s: link_offset = %d\n", 
                            MODNAME, link_offset);
        
                    );
        }
Esempio n. 16
0
/* Create file cache */
FileCache *file_cache_create(uint64_t memcap, uint32_t cleanup_files)
{
    FileCache *fileCache = NULL;
    int  max_files = 0;
    uint64_t file_segment_memcap = memcap/2;

    if( !memcap )
    {
        WarningMessage("%s(%d) File cache memory unlimited!\n",
                file_name, file_line);
    }

    /* Half for file segment, half for file context tracking*/
    max_files = get_max_files_from_memcap(memcap - file_segment_memcap);

    fileCache = SnortAlloc( sizeof( *fileCache ) );
    if( fileCache )
    {
        fileCache->max_files = max_files;
        /* Okay, now create the table */
        fileCache->hashTable = sfxhash_new(max_files, sizeof(FileKey), sizeof(FileEntry),
                0, 0, NULL, file_entry_free_func, 1 );

        if (!fileCache->hashTable)
            FatalError( "%s(%d) Unable to create a file cache.\n", file_name, file_line);

        sfxhash_set_max_nodes( fileCache->hashTable, max_files );
        fileCache->file_segment_memcap = file_segment_memcap;
        fileCache->max_file_depth = file_api->get_max_file_depth();
        fileCache->cleanup_files = cleanup_files;
    }
    else
    {
        FatalError( "%s(%d) Unable to create a file cache.\n",
                file_name, file_line);
    }

    return fileCache;
}
/* Option-converting functions */
static int ConvertPreprocessorOption(Rule *rule, int index, OptTreeNode *otn)
{
    PreprocessorOption *preprocOpt = rule->options[index]->option_u.preprocOpt;
    PreprocessorOptionInfo *preprocOptInfo = SnortAlloc(sizeof(PreprocessorOptionInfo));
    OptFpList *fpl;
    void *option_dup;

    preprocOptInfo->optionInit = preprocOpt->optionInit;
    preprocOptInfo->optionEval = preprocOpt->optionEval;
    preprocOptInfo->optionFpFunc = preprocOpt->optionFpFunc;
    preprocOptInfo->data = preprocOpt->dataPtr;

    /* FreeOneRule() already calls the cleanup function. Left NULL here
       to avoid a double-free. */
    preprocOptInfo->optionCleanup = NULL;

    preprocOptInfo->optionHash = NULL;
    preprocOptInfo->optionKeyCompare = NULL;
    preprocOptInfo->otnHandler = NULL;

    //  Add to option chain with generic callback
    fpl = AddOptFuncToList(PreprocessorOptionFunc, otn);

    /*
     * attach custom info to the context node so that we can call each instance
     * individually
     */
    fpl->context = (void *) preprocOptInfo;

    if (add_detection_option(RULE_OPTION_TYPE_PREPROCESSOR,
                             (void *)preprocOptInfo, &option_dup) == DETECTION_OPTION_EQUAL)
    {
        PreprocessorRuleOptionsFreeFunc(preprocOptInfo);
        fpl->context = preprocOptInfo = option_dup;
    }
    fpl->type = RULE_OPTION_TYPE_PREPROCESSOR;

    return 1;
}
Esempio n. 18
0
THD_STRUCT * sfthd_new(unsigned lbytes, unsigned gbytes)
{
    THD_STRUCT * thd;

    /* Create the THD struct */
    thd = (THD_STRUCT *)SnortAlloc(sizeof(THD_STRUCT));

#ifndef CRIPPLE
    /* Create hash table for all of the local IP Nodes */
    thd->ip_nodes = sfthd_local_new(lbytes);
    if( !thd->ip_nodes )
    {
#ifdef THD_DEBUG
        printf("Could not allocate the sfxhash table\n");
#endif
        free(thd);
        return NULL;
    }

    if ( gbytes == 0 )
        return thd;

    /* Create hash table for all of the global IP Nodes */
    thd->ip_gnodes = sfthd_global_new(gbytes);
    if( !thd->ip_gnodes )
    {
#ifdef THD_DEBUG
        printf("Could not allocate the sfxhash table\n");
#endif
        sfxhash_delete(thd->ip_nodes);
        free(thd);
        return NULL;
    }
#endif

    return thd;
}
static int ConvertFlowflagsOption(Rule *rule, int index, OptTreeNode *otn)
{
    FlowFlags *flow = rule->options[index]->option_u.flowFlags;
    ClientServerData *csdata = SnortAlloc(sizeof(ClientServerData));
    OptFpList *fpl;
    void *dup;

    if (flow->flags & FLOW_FR_SERVER)
        csdata->from_server = 1;
    if (flow->flags & FLOW_FR_CLIENT)
        csdata->from_client = 1;
    if (flow->flags & FLOW_IGNORE_REASSEMBLED)
        csdata->ignore_reassembled |= IGNORE_STREAM;
    if (flow->flags & FLOW_ONLY_REASSEMBLED)
        csdata->only_reassembled |= ONLY_STREAM;
    if (flow->flags & FLOW_ESTABLISHED)
        csdata->established = 1;
    csdata->stateless = 0;
    csdata->unestablished = 0;

    otn->established = csdata->established;
    otn->stateless = 0;
    otn->unestablished = 0;

    if (add_detection_option(RULE_OPTION_TYPE_FLOW, (void *)csdata, &dup) == DETECTION_OPTION_EQUAL)
    {
        free(csdata);
        csdata = dup;
    }

    fpl = AddOptFuncToList(CheckFlow, otn);
    fpl->type = RULE_OPTION_TYPE_FLOW;
    fpl->context = (void *)csdata;
    otn->ds_list[PLUGIN_CLIENTSERVER] = (void *)csdata;

    return 1;
}
static int ConvertFileDataOption(Rule *rule, int index, OptTreeNode *otn)
{
    CursorInfo *cursor = rule->options[index]->option_u.cursor;
    FileData *data = (FileData *) SnortAlloc(sizeof(FileData));
    OptFpList *fpl;
    void *dup;

    if (cursor->flags & BUF_FILE_DATA_MIME)
        data->mime_decode_flag = 1;
    else
        data->mime_decode_flag = 0;

    if (add_detection_option(RULE_OPTION_TYPE_FILE_DATA, (void *)data, &dup) == DETECTION_OPTION_EQUAL)
    {
        free(data);
        data = dup;
    }

    fpl = AddOptFuncToList(FileDataEval, otn);
    fpl->type = RULE_OPTION_TYPE_FILE_DATA;
    fpl->context = (void *)data;

    return 1;
}
Esempio n. 21
0
/*
*  Allocate Memory, initialize arrays, etc...
*/
int InitFlowStats(SFFLOW *sfFlow)
{
    static char first = 1;

    if (first)
    {
        sfFlow->pktLenCnt = (uint64_t*)SnortAlloc(sizeof(uint64_t) * (SF_MAX_PKT_LEN + 1));
        sfFlow->portTcpSrc = (uint64_t*)SnortAlloc(sizeof(uint64_t) * SF_MAX_PORT);
        sfFlow->portTcpDst = (uint64_t*)SnortAlloc(sizeof(uint64_t) * SF_MAX_PORT);
        sfFlow->portUdpSrc = (uint64_t*)SnortAlloc(sizeof(uint64_t) * SF_MAX_PORT);
        sfFlow->portUdpDst = (uint64_t*)SnortAlloc(sizeof(uint64_t) * SF_MAX_PORT);
        sfFlow->typeIcmp = (uint64_t *)SnortAlloc(sizeof(uint64_t) * 256);

        first = 0;
    }
    else
    {
        memset(sfFlow->pktLenCnt, 0, sizeof(uint64_t) * (SF_MAX_PKT_LEN + 1));
        memset(sfFlow->portTcpSrc, 0, sizeof(uint64_t) * SF_MAX_PORT);
        memset(sfFlow->portTcpDst, 0, sizeof(uint64_t) * SF_MAX_PORT);
        memset(sfFlow->portUdpSrc, 0, sizeof(uint64_t) * SF_MAX_PORT);
        memset(sfFlow->portUdpDst, 0, sizeof(uint64_t) * SF_MAX_PORT);
        memset(sfFlow->typeIcmp, 0, sizeof(uint64_t) * 256);
    }

    sfFlow->pktTotal = 0;
    sfFlow->byteTotal = 0;

    sfFlow->portTcpHigh=0;
    sfFlow->portTcpTotal=0;

    sfFlow->portUdpHigh=0;
    sfFlow->portUdpTotal=0;

    sfFlow->typeIcmpTotal = 0;

    return 0;
}
Esempio n. 22
0
ThresholdObjects * sfthd_objs_new(void)
{
    return (ThresholdObjects *)SnortAlloc(sizeof(ThresholdObjects));
}
static int ConvertByteExtractOption(Rule *rule, int index, OptTreeNode *otn)
{
    ByteExtract *so_byte = rule->options[index]->option_u.byteExtract;
    ByteExtractData *snort_byte = SnortAlloc(sizeof(ByteExtractData));
    OptFpList *fpl;
    void *dup;

    /* Clear out sp_byte_extract.c's variable_names array if this is the first
       byte_extract option in the rule. */
    ClearVarNames(otn->opt_func);

    /* Copy over the various struct members */
    snort_byte->bytes_to_grab = so_byte->bytes;
    snort_byte->offset = so_byte->offset;
    snort_byte->align = so_byte->align;
    snort_byte->name = strdup(so_byte->refId);

    /* In an SO rule, setting multiplier to 0 means that the multiplier is
       ignored. This is not the case in the text rule version of byte_extract. */
    if (so_byte->multiplier)
        snort_byte->multiplier = so_byte->multiplier;
    else
        snort_byte->multiplier = 1;

    if (so_byte->flags & CONTENT_RELATIVE)
        snort_byte->relative_flag = 1;

    if (so_byte->flags & EXTRACT_AS_STRING)
        snort_byte->data_string_convert_flag = 1;

    if (so_byte->flags & BYTE_BIG_ENDIAN)
        snort_byte->endianess = BIG;
    else
        snort_byte->endianess = LITTLE;

    if (so_byte->flags & EXTRACT_AS_HEX)
        snort_byte->base = 16;
    if (so_byte->flags & EXTRACT_AS_DEC)
        snort_byte->base = 10;
    if (so_byte->flags & EXTRACT_AS_OCT)
        snort_byte->base = 8;

    snort_byte->var_number = AddVarNameToList(snort_byte);
    snort_byte->byte_order_func = NULL;

    /* Add option to list */
    fpl = AddOptFuncToList(DetectByteExtract, otn);
    fpl->type = RULE_OPTION_TYPE_BYTE_EXTRACT;
    if (add_detection_option(RULE_OPTION_TYPE_BYTE_EXTRACT, (void *)snort_byte, &dup) == DETECTION_OPTION_EQUAL)
    {
        free(snort_byte->name);
        free(snort_byte);
        snort_byte = dup;
    }

    fpl->context = (void *) snort_byte;
    if (snort_byte->relative_flag)
        fpl->isRelative = 1;

    return 0;
}
Esempio n. 24
0
/*
 * Function: ParseIP(char *, IpAddrSet *)
 *
 * Purpose: Convert a supplied IP address to it's network order 32-bit long
 *          value.  Also convert the CIDR block notation into a real
 *          netmask.
 *
 * Arguments: char *addr  => address string to convert
 *            IpAddrSet * =>
 *
 *
 * Returns: 0 for normal addresses, 1 for an "any" address
 */
int ParseIP(char *paddr, IpAddrSet *ias, int negate) //, IpAddrNode *node)
{
    char **toks;        /* token dbl buffer */
    int num_toks;       /* number of tokens found by mSplit() */
    int cidr = 1;       /* is network expressed in CIDR format */
    int nmask = -1;     /* netmask temporary storage */
    char *addr;         /* string to parse, eventually a
                         * variable-contents */
    struct hostent *host_info;  /* various struct pointers for stuff */
    struct sockaddr_in sin; /* addr struct */
    char broadcast_addr_set = 0;

    IpAddrNode *address_data = (IpAddrNode*)SnortAlloc(sizeof(IpAddrNode));

    if(!paddr || !ias)
        return 1;

    addr = paddr;

    if(*addr == '!')
    {
        negate = !negate;
//        address_data->addr_flags |= EXCEPT_IP;

        addr++;  /* inc past the '!' */
    }

    /* check for wildcards */
    if(!strcasecmp(addr, "any"))
    {
        if(negate)
        {
            FatalError("%s(%d) => !any is not allowed\n", file_name, file_line);
        }

        /* Make first node 0, which matches anything */
        if(!ias->iplist)
        {
            ias->iplist = (IpAddrNode*)SnortAlloc(sizeof(IpAddrNode));
        }
        ias->iplist->ip_addr = 0;
        ias->iplist->netmask = 0;

        free(address_data);

        return 1;
    }
    /* break out the CIDR notation from the IP address */
    toks = mSplit(addr, "/", 2, &num_toks, 0);

    /* "/" was not used as a delimeter, try ":" */
    if(num_toks == 1)
    {
        mSplitFree(&toks, num_toks);
        toks = mSplit(addr, ":", 2, &num_toks, 0);
    }

    /*
     * if we have a mask spec and it is more than two characters long, assume
     * it is netmask format
     */
    if((num_toks > 1) && strlen(toks[1]) > 2)
    {
        cidr = 0;
    }

    switch(num_toks)
    {
        case 1:
            address_data->netmask = netmasks[32];
            break;

        case 2:
            if(cidr)
            {
                /* convert the CIDR notation into a real live netmask */
                nmask = atoi(toks[1]);

                /* it's pain to differ whether toks[1] is correct if netmask */
                /* is /0, so we deploy some sort of evil hack with isdigit */

                if(!isdigit((int) toks[1][0]))
                    nmask = -1;

                /* if second char is != '\0', it must be a digit
                 * by Daniel B. Cid, [email protected]
                 */
                if((toks[1][1] != '\0')&&(!isdigit((int) toks[1][1]) ))
                    nmask = -1;

                if((nmask > -1) && (nmask < 33))
                {
                    address_data->netmask = netmasks[nmask];
                }
                else
                {
                    FatalError("%s(%d): Invalid CIDR block for IP addr "
                            "%s\n", file_name, file_line, addr);

                }
            }
            else
            {
                /* convert the netmask into its 32-bit value */

                /* broadcast address fix from
                 * Steve Beaty <*****@*****.**>
                 */

                /*
                 * if the address is the (v4) broadcast address, inet_addr *
                 * returns -1 which usually signifies an error, but in the *
                 * broadcast address case, is correct.  we'd use inet_aton() *
                 * here, but it's less portable.
                 */
                if(!strncmp(toks[1], "255.255.255.255", 15))
                {
                    address_data->netmask = INADDR_BROADCAST;
                }
                else if((address_data->netmask = inet_addr(toks[1])) == INADDR_NONE)
                {
                    FatalError("%s(%d): Unable to parse rule netmask "
                            "(%s)\n", file_name, file_line, toks[1]);
                }
                /* Set nmask so we don't try to do a host lookup below.
                 * The value of 0 is irrelevant. */
                nmask = 0;
            }
            break;

        default:
            FatalError("%s(%d) => Unrecognized IP address/netmask %s\n",
                    file_name, file_line, addr);
            break;
    }
    sin.sin_addr.s_addr = inet_addr(toks[0]);

#ifndef WORDS_BIGENDIAN
    /*
     * since PC's store things the "wrong" way, shuffle the bytes into the
     * right order.  Non-CIDR netmasks are already correct.
     */
    if(cidr)
    {
        address_data->netmask = htonl(address_data->netmask);
    }
#endif
    /* broadcast address fix from Steve Beaty <*****@*****.**> */
    /* Changed location */
    if(!strncmp(toks[0], "255.255.255.255", 15))
    {
        address_data->ip_addr = INADDR_BROADCAST;
        broadcast_addr_set = 1;
    }
    else if (nmask == -1)
    {
        /* Try to do a host lookup if the address didn't
         * convert to a valid IP and there were not any
         * mask bits specified (CIDR or dot notation). */
        if(sin.sin_addr.s_addr == INADDR_NONE)
        {
            /* get the hostname and fill in the host_info struct */
            host_info = gethostbyname(toks[0]);
            if (host_info)
            {
                /* protecting against malicious DNS servers */
                if(host_info->h_length <= (int)sizeof(sin.sin_addr))
                {
                    bcopy(host_info->h_addr, (char *) &sin.sin_addr, host_info->h_length);
                }
                else
                {
                    bcopy(host_info->h_addr, (char *) &sin.sin_addr, sizeof(sin.sin_addr));
                }
            }
            /* Using h_errno */
            else if(h_errno == HOST_NOT_FOUND)
            /*else if((sin.sin_addr.s_addr = inet_addr(toks[0])) == INADDR_NONE)*/
            {
                FatalError("%s(%d): Couldn't resolve hostname %s\n",
                    file_name, file_line, toks[0]);
            }
        }
        else
        {
            /* It was a valid IP address with no netmask specified. */
            /* Noop */
        }
    }
    else
    {
        if(sin.sin_addr.s_addr == INADDR_NONE)
        {
            /* It was not a valid IP address but had a valid netmask. */
            FatalError("%s(%d): Rule IP addr (%s) didn't translate\n",
                file_name, file_line, toks[0]);
        }
    }

    /* Only set this if we haven't set it above as 255.255.255.255 */
    if (!broadcast_addr_set)
    {
        address_data->ip_addr = ((u_long) (sin.sin_addr.s_addr) &
            (address_data->netmask));
    }
    mSplitFree(&toks, num_toks);

    /* Add new IP address to address set */
    if(!negate)
    {
        IpAddrNode *idx;

        if(!ias->iplist)
        {
            ias->iplist = address_data;
        }
        else
        {
            /* Get to the end of the list */
            for(idx = ias->iplist; idx->next; idx=idx->next) ;

            idx->next = address_data;
        }
    }
    else
    {
        IpAddrNode *idx;

        if(!ias->neg_iplist)
        {
            ias->neg_iplist = address_data;
        }
        else
        {
            /* Get to the end of the list */
            for(idx = ias->neg_iplist; idx->next; idx=idx->next) ;

            idx->next = address_data;
        }

        address_data->addr_flags |= EXCEPT_IP;
    }

    return 0;
}
static int ConvertPcreOption(Rule *rule, int index, OptTreeNode *otn)
{
    PcreData *pcre_data = (PcreData *) SnortAlloc(sizeof(PcreData));
    PCREInfo *pcre_info = rule->options[index]->option_u.pcre;
    OptFpList *fpl;
    void *pcre_dup;
    const char *error;
    int erroroffset;

    /* Need to recompile the expression so double free doesn't occur
     * during reload */

    /* Compile & Study PCRE */
    pcre_data->re = pcreCompile(
        pcre_info->expr,
        pcre_info->compile_flags,
        &error,
        &erroroffset,
        NULL
        );

    if (pcre_data->re == NULL)
    {
        free(pcre_data);
        return -1;
    }

    pcre_data->pe = pcreStudy(
        pcre_data->re,
        pcre_info->compile_flags,
        &error
        );

    if (error)
    {
        free(pcre_data->re);
        free(pcre_data);
        return -1;
    }

    /* Copy to struct used for normal PCRE rules */
    pcre_data->expression = SnortStrdup(pcre_info->expr);

    /* Option values differ between PCREInfo and PcreData,
     * so a straight copy of the options variable won't work. */
    if (pcre_info->flags & CONTENT_RELATIVE)
        pcre_data->options |= SNORT_PCRE_RELATIVE;

    if (pcre_info->flags & NOT_FLAG)
        pcre_data->options |= SNORT_PCRE_INVERT;

    if (pcre_info->flags & CONTENT_BUF_RAW)
        pcre_data->options |= SNORT_PCRE_RAWBYTES;

    if (pcre_info->flags & CONTENT_BUF_NORMALIZED)
        pcre_data->options &= ~SNORT_PCRE_RAWBYTES;

    if (pcre_info->flags & CONTENT_BUF_POST)
        pcre_data->options |= SNORT_PCRE_HTTP_BODY;

    if (pcre_info->flags & CONTENT_BUF_HEADER)
        pcre_data->options |= SNORT_PCRE_HTTP_HEADER;

    if (pcre_info->flags & CONTENT_BUF_METHOD)
        pcre_data->options |= SNORT_PCRE_HTTP_METHOD;

    if (pcre_info->flags & CONTENT_BUF_COOKIE)
        pcre_data->options |= SNORT_PCRE_HTTP_COOKIE;

    if (pcre_info->flags & CONTENT_BUF_URI)
        pcre_data->options |= SNORT_PCRE_HTTP_URI;

    if (pcre_info->flags & CONTENT_BUF_STAT_CODE)
        pcre_data->options |= SNORT_PCRE_HTTP_STAT_CODE;

    if (pcre_info->flags & CONTENT_BUF_STAT_MSG)
        pcre_data->options |= SNORT_PCRE_HTTP_STAT_MSG;

    if (pcre_info->flags & CONTENT_BUF_RAW_URI)
        pcre_data->options |= SNORT_PCRE_HTTP_RAW_URI;

    if (pcre_info->flags & CONTENT_BUF_RAW_HEADER)
        pcre_data->options |= SNORT_PCRE_HTTP_RAW_HEADER;

    if (pcre_info->flags & CONTENT_BUF_RAW_COOKIE)
        pcre_data->options |= SNORT_PCRE_HTTP_RAW_COOKIE;

    if (pcre_info->flags & CONTENT_BUF_STAT_CODE)
        pcre_data->options |= SNORT_PCRE_HTTP_STAT_CODE;

    if (pcre_info->flags & CONTENT_BUF_STAT_MSG)
        pcre_data->options |= SNORT_PCRE_HTTP_STAT_MSG;

    PcreCheckAnchored(pcre_data);

    /* Attach option to tree, checking for duplicate */
    otn->pcre_flag = 1;
    fpl = AddOptFuncToList(SnortPcre, otn);
    fpl->type = RULE_OPTION_TYPE_PCRE;

    if (add_detection_option(RULE_OPTION_TYPE_PCRE, (void *)pcre_data, &pcre_dup) == DETECTION_OPTION_EQUAL)
    {
        if (pcre_data->expression)
            free(pcre_data->expression);
        if (pcre_data->pe)
            free(pcre_data->pe);
        if (pcre_data->re)
            free(pcre_data->re);

        free(pcre_data);
        pcre_data = pcre_dup;
    }

    fpl->context = (void *)pcre_data;
    if (pcre_data->options & SNORT_PCRE_RELATIVE)
        fpl->isRelative = 1;

    if (otn->ds_list[PLUGIN_PCRE] == NULL)
        otn->ds_list[PLUGIN_PCRE] = (void *)pcre_data;

    return 1;
}
static int ConvertContentOption(Rule *rule, int index, OptTreeNode *otn)
{
    ContentInfo *content = rule->options[index]->option_u.content;
    PatternMatchData *pmd = NULL;
    OptFpList *fpl;
    char *pattern;
    unsigned int pattern_size, i;

    /* ParsePattern expects quotations marks around the pattern. */
    if (content->pattern[0] != '"')
    {
        pattern_size = strlen((const char*)content->pattern) + 3;
        pattern = SnortAlloc(sizeof(char) * pattern_size);
        pattern[0] = '"';
        memcpy(pattern+1, content->pattern, pattern_size-3);
        pattern[pattern_size-2] = '"';
    }
    else
    {
        pattern = (char*)content->pattern;
    }

    /* Allocate a new node, based on the type of content option. */
    if ( content->flags & URI_CONTENT_BUFS )
    {
        pmd = NewNode(otn, PLUGIN_PATTERN_MATCH_URI);
        ParsePattern(pattern, otn, PLUGIN_PATTERN_MATCH_URI);
        fpl = AddOptFuncToList(CheckUriPatternMatch, otn);
        fpl->type = RULE_OPTION_TYPE_CONTENT_URI;
        pmd->buffer_func = CHECK_URI_PATTERN_MATCH;
    }
    else
    {
        pmd = NewNode(otn, PLUGIN_PATTERN_MATCH);
        ParsePattern(pattern, otn, PLUGIN_PATTERN_MATCH);
        fpl = AddOptFuncToList(CheckANDPatternMatch, otn);
        fpl->type = RULE_OPTION_TYPE_CONTENT;
        pmd->buffer_func = CHECK_AND_PATTERN_MATCH;
    }

    /* Initialize var numbers */
    if (content->flags & CONTENT_RELATIVE)
    {
        pmd->distance_var = GetVarByName(content->offset_refId);
        pmd->within_var = GetVarByName(content->depth_refId);
        pmd->offset_var = -1;
        pmd->depth_var = -1;
    }
    else
    {
        pmd->offset_var = GetVarByName(content->offset_refId);
        pmd->depth_var = GetVarByName(content->depth_refId);
        pmd->distance_var = -1;
        pmd->within_var = -1;
    }

    /* Set URI buffer flags */
    if (content->flags & CONTENT_BUF_URI)
        pmd->uri_buffer |= HTTP_SEARCH_URI;
    if (content->flags & CONTENT_BUF_HEADER)
        pmd->uri_buffer |= HTTP_SEARCH_HEADER;
    if (content->flags & CONTENT_BUF_POST)
        pmd->uri_buffer |= HTTP_SEARCH_CLIENT_BODY;
    if (content->flags & CONTENT_BUF_METHOD)
        pmd->uri_buffer |= HTTP_SEARCH_METHOD;
    if (content->flags & CONTENT_BUF_COOKIE)
        pmd->uri_buffer |= HTTP_SEARCH_COOKIE;
    if (content->flags & CONTENT_BUF_RAW_URI)
        pmd->uri_buffer |= HTTP_SEARCH_RAW_URI;
    if (content->flags & CONTENT_BUF_RAW_HEADER)
        pmd->uri_buffer |= HTTP_SEARCH_RAW_HEADER;
    if (content->flags & CONTENT_BUF_RAW_COOKIE)
        pmd->uri_buffer |= HTTP_SEARCH_RAW_COOKIE;
    if (content->flags & CONTENT_BUF_STAT_CODE)
        pmd->uri_buffer |= HTTP_SEARCH_STAT_CODE;
    if (content->flags & CONTENT_BUF_STAT_MSG)
        pmd->uri_buffer |= HTTP_SEARCH_STAT_MSG;


    if (content->flags & CONTENT_BUF_RAW)
    {
        pmd->rawbytes = 1;
    }

    /* Handle options */
    if (content->flags & CONTENT_NOCASE)
    {
        pmd->nocase = 1;
        for (i = 0; i < pmd->pattern_size; i++)
        {
            pmd->pattern_buf[i] = toupper(pmd->pattern_buf[i]);
        }
        make_precomp(pmd);
        pmd->search = uniSearchCI;
    }
    if (content->flags & CONTENT_RELATIVE)
    {
        pmd->distance = content->offset;
        pmd->within = content->depth;
        pmd->use_doe = 1;
        fpl->isRelative = 1;
    }
    else
    {
        pmd->offset = content->offset;
        pmd->depth = content->depth;
    }

    if (content->flags & CONTENT_FAST_PATTERN)
        pmd->fp = 1;

    /* Fast pattern only and specifying an offset and length are
     * technically mutually exclusive - see
     * detection-plugins/sp_pattern_match.c */
    if (content->flags & CONTENT_FAST_PATTERN_ONLY)
    {
        pmd->fp_only = 1;
    }
    else
    {
        pmd->fp_offset = content->fp_offset;
        pmd->fp_length = content->fp_length;
    }

    if (content->flags & NOT_FLAG)
        pmd->exception_flag = 1;

    fpl->context = pmd;
    pmd->fpl = fpl;

    if (pattern != (char *)content->pattern)
        free(pattern);

    return 1;
}
Esempio n. 27
0
    SnortConfig *sc = snort_conf_for_parsing;
    vartable_t *ip_vartable;

    if ((sc == NULL) || (sc->targeted_policies[getParserPolicy()] == NULL))
    {
        FatalError("%s(%d) Snort conf for parsing is NULL.\n",
                   __FILE__, __LINE__);
    }

    ip_vartable = sc->targeted_policies[getParserPolicy()]->ip_vartable;
#endif

    DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Got address string: %s\n",
                addr););

    ret = (IpAddrSet*)SnortAlloc(sizeof(IpAddrSet));

#ifdef SUP_IP6
    if((ret_code = sfvt_add_to_var(ip_vartable, ret, addr)) != SFIP_SUCCESS)
    {
        if(ret_code == SFIP_LOOKUP_FAILURE)
            FatalError("%s(%d) => Undefined variable in the string: %s\n",
                file_name, file_line, addr);
        else if(ret_code == SFIP_CONFLICT)
            FatalError("%s(%d) => Negated IP ranges that equal to or are"
                " more-specific than non-negated ranges are not allowed."
                " Consider inverting the logic: %s.\n",
                file_name, file_line, addr);
        else
            FatalError("%s(%d) => Unable to process the IP address: %s\n",
                file_name, file_line, addr);
Esempio n. 28
0
int IntelPmAddPattern(SnortConfig *sc, IntelPm *ipm, unsigned char *pat, int pat_len,
        unsigned no_case, unsigned negative, void *pat_data, int pat_id)
{

    Cpa32U patternOptions = CPA_PM_PDB_OPTIONS_CASELESS | CPA_PM_PDB_OPTIONS_LITERAL;
    CpaStatus status;
    IntelPmPattern *ipp;

    if ((ipm == NULL) || (sc->ipm_handles == NULL))
        return -1;

    if (!ipm->patternGroupId)
    {
        ipm->patternGroupId = sc->ipm_handles->pgids++;
        ipm->patternIds = 1;
    }

    status = cpaPmPdbAddPattern(
            ipm_instance,
            sc->ipm_handles->psh,
            ipm->patternIds,
            patternOptions,
            pat_len,
            pat,
            ipm->patternGroupId);

    if (status != CPA_STATUS_SUCCESS)
        FatalError("cpaPmPdbAddPattern() failed: %s\n", GetCpaStatusStr(status));

    if (ipm->pattern_array == NULL)
    {
        ipm->pattern_array = (IntelPmPattern *)SnortAlloc(
                sizeof(IntelPmPattern) * PATTERN_ARRAY_ALLOC_SIZE);
        ipm->pattern_array_len = PATTERN_ARRAY_ALLOC_SIZE;
    }
    else if (ipm->patternIds >= ipm->pattern_array_len)
    {
        IntelPmPattern *tmp = (IntelPmPattern *)SnortAlloc(
                sizeof(IntelPmPattern) * (ipm->patternIds + PATTERN_ARRAY_ALLOC_SIZE));
        memcpy((void *)tmp, ipm->pattern_array, ipm->patternIds * sizeof(IntelPmPattern));
        free(ipm->pattern_array);
        ipm->pattern_array = tmp;
        ipm->pattern_array_len = ipm->patternIds + PATTERN_ARRAY_ALLOC_SIZE;
    }

    ipp = &ipm->pattern_array[ipm->patternIds];
    ipp->user_data = pat_data;
    ipp->rule_option_tree = NULL;
    ipp->neg_list = NULL;
    //ipp->pattern = (unsigned char *)SnortAlloc(pat_len);
    //memcpy(ipp->pattern, pat, pat_len);
    ipp->pattern = NULL;
    ipp->pattern_len = pat_len;
    ipp->no_case = no_case;
    ipp->negative = negative;
    ipp->id = pat_id;
    ipp->patternId = ipm->patternIds++;

    sc->ipm_handles->pids++;
    sc->ipm_handles->pcs += pat_len;

    return 0;
}
Esempio n. 29
0
 *            type => used to determine where keyword is allowed
 *
 * Returns: void function
 *
 ***************************************************************************/
void RegisterRuleOption(char *opt_name, RuleOptConfigFunc ro_config_func,
                        RuleOptOverrideInitFunc override_init_func,
                        RuleOptType opt_type,
                        RuleOptOtnHandler otn_handler)
{
    RuleOptConfigFuncNode *node;

    DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Registering keyword:func => %s/%s:%p\n",
                            ENUM2STR(opt_type, optTypeMap), opt_name, ro_config_func););

    node = (RuleOptConfigFuncNode *)SnortAlloc(sizeof(RuleOptConfigFuncNode));

    if (rule_opt_config_funcs == NULL)
    {
        rule_opt_config_funcs = node;
    }
    else
    {
        RuleOptConfigFuncNode *tmp = rule_opt_config_funcs;
        RuleOptConfigFuncNode *last;

        do
        {
            if (strcasecmp(tmp->keyword, opt_name) == 0)
            {
                free(node);
Esempio n. 30
0
void IntelPmCompile(SnortConfig *sc)
{
    if ((ipm_instance == NULL) || (sc->ipm_handles == NULL)
            || (sc->ipm_handles->psh == NULL))
    {
        return;
    }

    if (sc->ipm_handles->pdbh == NULL)
    {
        CpaStatus status;
        Cpa16U patternGroup;
        Cpa32U numMatchStates;

        status = cpaPmPdbCompile(ipm_instance, sc->ipm_handles->psh,
                CPA_PM_COMPILE_OPTION_CONSOLIDATE, NULL, &sc->ipm_handles->pdbh);
        if (status != CPA_STATUS_SUCCESS)
            FatalError("cpaPmPdbCompile() failed: %s\n", GetCpaStatusStr(status));

        status = cpaPmMsoGetNumMatchStates(ipm_instance, sc->ipm_handles->pdbh, &numMatchStates);
        if (status != CPA_STATUS_SUCCESS)
            FatalError("cpaPmMsoGetNumMatchStates() failed: %s\n", GetCpaStatusStr(status));

        /* Hack because the last match state is returned instead of the
         * number of match states */
        numMatchStates += 1;
        sc->ipm_handles->pm_mtchs = (IntelPmMatchState *)SnortAlloc(numMatchStates * sizeof(IntelPmMatchState));
        sc->ipm_handles->pm_mtchs_len = numMatchStates;

        for (patternGroup = 1; patternGroup < sc->ipm_handles->pgids; patternGroup++)
        {
            CpaPmMsoMatchStateIter matchStateIter = NULL;
            Cpa32U matchStateId;
            IntelPm *ipm = sc->ipm_handles->ipms[patternGroup];

            if (ipm == NULL)
                continue;

            status = cpaPmMsoGetFirstMatchState(ipm_instance, sc->ipm_handles->pdbh,
                    patternGroup, &matchStateIter, &matchStateId);

            if (status != CPA_STATUS_SUCCESS)
                FatalError("cpaPmMsoGetFirstMatchState() failed: %s\n", GetCpaStatusStr(status));

            while (matchStateIter != NULL)
            {
                CpaPmMsoPatternIdIter patternIdIter = NULL;
                Cpa32U patternID;
                IntelPmPattern *ipp = NULL;
                void *rule_option_tree = NULL;
                void *neg_list = NULL;
                void *user_data = NULL;

                status = cpaPmMsoGetFirstPatternId(ipm_instance, sc->ipm_handles->pdbh,
                        matchStateIter, &patternIdIter, &patternID);

                if (status != CPA_STATUS_SUCCESS)
                    FatalError("cpaPmMsoGetFirstPatternId() failed: %s\n", GetCpaStatusStr(status));

                while (patternIdIter != NULL)
                {
                    ipp = &ipm->pattern_array[patternID];
                    if (user_data == NULL)
                        user_data = ipp->user_data;

                    if (ipp->negative)
                        ipm->neg_list_func(ipp->user_data, &neg_list);
                    else
                        ipm->build_tree(sc, ipp->user_data, &rule_option_tree);

                    status = cpaPmMsoGetNextPatternId(ipm_instance, sc->ipm_handles->pdbh,
                            &patternIdIter, &patternID);

                    if (status != CPA_STATUS_SUCCESS)
                        FatalError("cpaPmMsoGetNextPatternId() failed: %s\n", GetCpaStatusStr(status));
                }

                if (ipp != NULL)
                {
                    ipm->build_tree(sc, NULL, &rule_option_tree);

                    sc->ipm_handles->pm_mtchs[matchStateId].user_data = user_data;
                    sc->ipm_handles->pm_mtchs[matchStateId].neg_list = neg_list;
                    sc->ipm_handles->pm_mtchs[matchStateId].rule_option_tree = rule_option_tree;

                    sc->ipm_handles->pm_mtchs[matchStateId].user_free = ipm->user_free;
                    sc->ipm_handles->pm_mtchs[matchStateId].option_tree_free = ipm->option_tree_free;
                    sc->ipm_handles->pm_mtchs[matchStateId].neg_list_free = ipm->neg_list_free;
                }

                status = cpaPmMsoGetNextMatchState(ipm_instance, sc->ipm_handles->pdbh,
                        patternGroup, &matchStateIter, &matchStateId);

                if (status != CPA_STATUS_SUCCESS)
                    FatalError("cpaPmMsoGetNextMatchState() failed: %s\n", GetCpaStatusStr(status));
            }
        }
    }
}