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

📄 sp_pcre.c

📁 Linux snort-2.4.4源代码
💻 C
字号:
/* $Id$ *//*** Copyright (C) 2003 Brian Caswell <bmc@snort.org>** Copyright (C) 2003 Michael J. Pomraning <mjp@securepipe.com>** 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.*/#ifdef HAVE_CONFIG_H#include "config.h"#endif#include "bounds.h"#include "rules.h"#include "debug.h"#include "decode.h"#include "plugbase.h"#include "parser.h"#include "plugin_enum.h"#include "util.h"#include "mstring.h"#include <sys/types.h>#ifdef WIN32#define PCRE_DEFINITION#endif#include <pcre.h>typedef struct _PcreData{    pcre *re;           /* compiled regex */    pcre_extra *pe;     /* studied regex foo */    int options;        /* sp_pcre specfic options (relative & inverse) */} PcreData;#define SNORT_PCRE_RELATIVE 1  /* relative to the end of the last match */#define SNORT_PCRE_INVERT   2  /* invert detect */#define SNORT_PCRE_URI      4  /* check URI buffers */#define SNORT_PCRE_RAWBYTES 8  /* Don't use decoded buffer (if available) *//*  * we need to specify the vector length for our pcre_exec call.  we only care  * about the first vector, which if the match is successful will include the * offset to the end of the full pattern match.  If we decide to store other * matches, make *SURE* that this is a multiple of 3 as pcre requires it. */#define SNORT_PCRE_OVECTOR_SIZE 3extern u_int8_t DecodeBuffer[DECODE_BLEN];extern u_int8_t *doe_ptr;void SnortPcreInit(char *, OptTreeNode *, int);void SnortPcreParse(char *, PcreData *, OptTreeNode *);void SnortPcreDump(PcreData *);int SnortPcre(Packet *, struct _OptTreeNode *, OptFpList *);void SetupPcre(void){    RegisterPlugin("pcre", SnortPcreInit);}void SnortPcreInit(char *data, OptTreeNode *otn, int protocol){    PcreData *pcre_data;    OptFpList *fpl;    /*      * allocate the data structure for pcre     */    pcre_data = (PcreData *) SnortAlloc(sizeof(PcreData));    if(pcre_data == NULL)    {        FatalError("%s (%d): Unable to allocate pcre_data node\n",                   file_name, file_line);    }    SnortPcreParse(data, pcre_data, otn);    fpl = AddOptFuncToList(SnortPcre, otn);    /*     * attach it to the context node so that we can call each instance     * individually     */    fpl->context = (void *) pcre_data;    return;}void SnortPcreParse(char *data, PcreData *pcre_data, OptTreeNode *otn){    const char *error;    char *re, *free_me;    char *opts;    char delimit = '/';    int erroffset;    int compile_flags = 0;        if(data == NULL)     {        FatalError("%s (%d): pcre requires a regular expression\n",                    file_name, file_line);    }    if(!(free_me = strdup(data)))    {        FatalError("%s (%d): pcre strdup() failed\n", file_name, file_line);    }    re = free_me;    /* get rid of starting and ending whitespace */    while (isspace((int)re[strlen(re)-1])) re[strlen(re)-1] = '\0';    while (isspace((int)*re)) re++;    if(*re == '!') {         pcre_data->options |= SNORT_PCRE_INVERT;        re++;        while(isspace((int)*re)) re++;    }    /* now we wrap the RE in double quotes.  stupid snort parser.... */    if(*re != '"') {        printf("It isn't \"\n");        goto syntax;    }    re++;    if(re[strlen(re)-1] != '"')    {        printf("It isn't \"\n");        goto syntax;    }        /* remove the last quote from the string */    re[strlen(re) - 1] = '\0';        /* 'm//' or just '//' */            if(*re == 'm')    {        re++;        if(! *re) goto syntax;                /* Space as a ending delimiter?  Uh, no. */        if(isspace((int)*re)) goto syntax;        /* using R would be bad, as it triggers RE */        if(*re == 'R') goto syntax;           delimit = *re;    }     else if(! *re == delimit)        goto syntax;    /* find ending delimiter, trim delimit chars */    opts = strrchr(re, delimit);    if(!((opts - re) > 1)) /* empty regex(m||) or missing delim not OK */        goto syntax;    re++;    *opts++ = '\0';    /* process any /regex/ismxR options */    while(*opts != '\0') {        switch(*opts) {        case 'i':  compile_flags |= PCRE_CASELESS;            break;        case 's':  compile_flags |= PCRE_DOTALL;              break;        case 'm':  compile_flags |= PCRE_MULTILINE;           break;        case 'x':  compile_flags |= PCRE_EXTENDED;            break;                        /*              * these are pcre specific... don't work with perl             */         case 'A':  compile_flags |= PCRE_ANCHORED;            break;        case 'E':  compile_flags |= PCRE_DOLLAR_ENDONLY;      break;        case 'G':  compile_flags |= PCRE_UNGREEDY;            break;            /*             * these are snort specific don't work with pcre or perl             */        case 'R':  pcre_data->options |= SNORT_PCRE_RELATIVE; break;        case 'U':  pcre_data->options |= SNORT_PCRE_URI;      break;        case 'B':  pcre_data->options |= SNORT_PCRE_RAWBYTES; break;        default:            FatalError("%s (%d): unknown/extra pcre option encountered\n", file_name, file_line);        }        opts++;    }    if(pcre_data->options & SNORT_PCRE_RELATIVE &&        pcre_data->options & SNORT_PCRE_URI)        FatalError("%s(%d): PCRE unsupported configuration : both relative & uri options specified\n", file_name, file_line);        /* now compile the re */    DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "pcre: compiling %s\n", re););    pcre_data->re = pcre_compile(re, compile_flags, &error, &erroffset, NULL);    if(pcre_data->re == NULL)     {        FatalError("%s(%d) : pcre compile of \"%s\" failed at offset "                   "%d : %s\n", file_name, file_line, re, erroffset, error);    }    /* now study it... */    pcre_data->pe = pcre_study(pcre_data->re, 0, &error);    if(error != NULL)     {        FatalError("%s(%d) : pcre study failed : %s\n", file_name,                    file_line, error);    }    free(free_me);    return; syntax:    if(free_me) free(free_me);    FatalError("ERROR %s Line %d => unable to parse pcre regex %s\n",                file_name, file_line, data);}/**  * Perform a search of the PCRE data. *  * @param pcre_data structure that options and patterns are passed in * @param buf buffer to search * @param len size of buffer * @param start_offset initial offset into the buffer * @param found_offset pointer to an integer so that we know where the search ended * * *found_offset will be set to -1 when the find is unsucessful OR the routine is inverted * * @return 1 when we find the string, 0 when we don't (unless we've been passed a flag to invert) */static int pcre_search(const PcreData *pcre_data,                       const char *buf,                       int len,                       int start_offset,                       int *found_offset){    int ovector[SNORT_PCRE_OVECTOR_SIZE];    int matched;    int result;        if(pcre_data == NULL       || buf == NULL       || len <= 0       || start_offset < 0       || start_offset >= len       || found_offset == NULL)    {        DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,                                "Returning 0 because we didn't have the required parameters!\n"););        return 0;    }    *found_offset = -1;        result = pcre_exec(pcre_data->re,            /* result of pcre_compile() */                       pcre_data->pe,            /* result of pcre_study()   */                       buf,                      /* the subject string */                       len,                      /* the length of the subject string */                       start_offset,             /* start at offset 0 in the subject */                       0,                        /* options(handled at compile time */                       ovector,                  /* vector for substring information */                       SNORT_PCRE_OVECTOR_SIZE); /* number of elements in the vector */    if(result >= 0)    {        matched = 1;    }    else if(result == PCRE_ERROR_NOMATCH)    {        matched = 0;    }    else    {        DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "pcre_exec error : %d \n", result););        return 0;    }    /* invert sense of match */    if(pcre_data->options & SNORT_PCRE_INVERT)     {        matched = !matched;    }    else    {                *found_offset = ovector[1];                DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,                                "Setting Doe_ptr and found_offset: %p %d\n",                                doe_ptr, found_offset););    }    return matched;}int SnortPcre(Packet *p, struct _OptTreeNode *otn, OptFpList *fp_list){    PcreData *pcre_data;   /* pointer to the eval string for each test */    int found_offset;  /* where is the ending location of the pattern */    char *base_ptr, *end_ptr, *start_ptr;    int dsize;    int length; /* length of the buffer pointed to by base_ptr  */    int matched = 0;    extern HttpUri UriBufs[URI_COUNT];    int i;    DEBUG_WRAP(char *hexbuf;);    /* get my data */    pcre_data =(PcreData *) fp_list->context;    /* This is the HTTP case */    if(pcre_data->options & SNORT_PCRE_URI)     {        for(i=0;i<p->uri_count;i++)        {            matched = pcre_search(pcre_data,                                  UriBufs[i].uri,                                  UriBufs[i].length,                                  0,                                  &found_offset);                        if(matched)            {                /* don't touch doe_ptr on URI contents */                return fp_list->next->OptTestFunc(p, otn, fp_list->next);            }        }                return 0;    }    /* end of the HTTP case */    if(p->packet_flags & PKT_ALT_DECODE && !(pcre_data->options & SNORT_PCRE_RAWBYTES))    {        dsize = p->alt_dsize;        start_ptr = (char *) DecodeBuffer;        DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,                                "using alternative decode buffer in pcre!\n"););    }    else    {        dsize = p->dsize;        start_ptr = (char *) p->data;    }    base_ptr = start_ptr;    end_ptr = start_ptr + dsize;    /* doe_ptr's would be set by the previous content option */    if(pcre_data->options & SNORT_PCRE_RELATIVE && doe_ptr)    {        if(!inBounds(start_ptr, end_ptr, doe_ptr))        {            DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,                                     "pcre bounds check failed on a relative content match\n"););            return 0;        }                DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,                                "pcre ... checking relative offset\n"););        base_ptr = doe_ptr;    }    else    {        DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,                                "pcre ... checking absolute offset\n"););        base_ptr = start_ptr;    }    length = end_ptr - base_ptr;        DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,                            "pcre ... base: %p start: %p end: %p doe: %p length: %d\n",                            base_ptr, start_ptr, end_ptr, doe_ptr, length););    DEBUG_WRAP(hexbuf = hex(base_ptr, length);               DebugMessage(DEBUG_PATTERN_MATCH, "pcre payload: %s\n", hexbuf);               free(hexbuf);               );    matched = pcre_search(pcre_data, base_ptr, length, 0, &found_offset);    /* set the doe_ptr if we have a valid offset */    if(found_offset > 0)    {        doe_ptr = (u_int8_t *) base_ptr + found_offset;    }        while(matched)    {        int search_offset = found_offset;        int next_found = fp_list->next->OptTestFunc(p, otn, fp_list->next);        if(next_found)        {            /* if the OTN checks are successful, return 1, else               return the next iteration */            /* set the doe_ptr for stateful pattern matching later */            doe_ptr = (u_int8_t *) base_ptr + found_offset;            return 1;        }        /* the other OTNs search's were not successful so we need to keep searching */        if(search_offset <= 0 || length < search_offset)        {            /* make sure that the search offset is reasonable */            return 0;        }        matched = pcre_search(pcre_data, base_ptr, length,                              search_offset, &found_offset);        /* set the doe_ptr if we have a valid offset */        if(found_offset > 0)        {            doe_ptr = (u_int8_t *) base_ptr + found_offset;        }                if(matched)        {            if(fp_list->next->OptTestFunc(p, otn, fp_list->next))            {                /* if the OTN checks are successful, return 1, else                   return the next iteration */                return 1;            }                    }                }    /* finally return 0 */    return 0;}

⌨️ 快捷键说明

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