PageRenderTime 125ms CodeModel.GetById 9ms app.highlight 95ms RepoModel.GetById 1ms app.codeStats 3ms

/src/detect-fast-pattern.c

https://github.com/decanio/suricata-tilera
C | 17067 lines | 13888 code | 2924 blank | 255 comment | 3694 complexity | 8f001207f0544d429199869e0b3116f1 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/* Copyright (C) 2007-2010 Open Information Security Foundation
   2 *
   3 * You can copy, redistribute or modify this Program under the terms of
   4 * the GNU General Public License version 2 as published by the Free
   5 * Software Foundation.
   6 *
   7 * This program is distributed in the hope that it will be useful,
   8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
   9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  10 * GNU General Public License for more details.
  11 *
  12 * You should have received a copy of the GNU General Public License
  13 * version 2 along with this program; if not, write to the Free Software
  14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  15 * 02110-1301, USA.
  16 */
  17
  18/**
  19 * \file
  20 *
  21 * \author Anoop Saldanha <anoopsaldanha@gmail.com>
  22 *
  23 * Implements the fast_pattern keyword
  24 */
  25
  26#include "suricata-common.h"
  27#include "detect.h"
  28#include "flow.h"
  29#include "detect-content.h"
  30#include "detect-parse.h"
  31#include "detect-engine.h"
  32#include "detect-engine-mpm.h"
  33#include "detect-fast-pattern.h"
  34
  35#include "util-error.h"
  36#include "util-debug.h"
  37#include "util-unittest.h"
  38#include "util-unittest-helper.h"
  39
  40#define DETECT_FAST_PATTERN_REGEX "^(\\s*only\\s*)|\\s*([0-9]+)\\s*,\\s*([0-9]+)\\s*$"
  41
  42static pcre *parse_regex = NULL;
  43static pcre_extra *parse_regex_study = NULL;
  44
  45static int DetectFastPatternSetup(DetectEngineCtx *, Signature *, char *);
  46void DetectFastPatternRegisterTests(void);
  47
  48/* holds the list of sm match lists that need to be searched for a keyword
  49 * that has fp support */
  50SCFPSupportSMList *sm_fp_support_smlist_list = NULL;
  51
  52/**
  53 * \brief Lets one add a sm list id to be searched for potential fp supported
  54 *        keywords later.
  55 *
  56 * \param list_id SM list id.
  57 * \param priority Priority for this list.
  58 */
  59static void SupportFastPatternForSigMatchList(int list_id, int priority)
  60{
  61    if (sm_fp_support_smlist_list == NULL) {
  62        SCFPSupportSMList *new = SCMalloc(sizeof(SCFPSupportSMList));
  63        if (unlikely(new == NULL))
  64            exit(EXIT_FAILURE);
  65        memset(new, 0, sizeof(SCFPSupportSMList));
  66        new->list_id = list_id;
  67        new->priority = priority;
  68
  69        sm_fp_support_smlist_list = new;
  70
  71        return;
  72    }
  73
  74    /* insertion point - ip */
  75    SCFPSupportSMList *ip = NULL;
  76    for (SCFPSupportSMList *tmp = sm_fp_support_smlist_list; tmp != NULL; tmp = tmp->next) {
  77        if (list_id == tmp->list_id) {
  78            SCLogError(SC_ERR_FATAL, "SM list already registered.");
  79            exit(EXIT_FAILURE);
  80        }
  81
  82        if (priority <= tmp->priority)
  83            break;
  84
  85        ip = tmp;
  86    }
  87
  88    SCFPSupportSMList *new = SCMalloc(sizeof(SCFPSupportSMList));
  89    if (unlikely(new == NULL))
  90        exit(EXIT_FAILURE);
  91    memset(new, 0, sizeof(SCFPSupportSMList));
  92    new->list_id = list_id;
  93    new->priority = priority;
  94    if (ip == NULL) {
  95        new->next = sm_fp_support_smlist_list;
  96        sm_fp_support_smlist_list = new;
  97    } else {
  98        new->next = ip->next;
  99        ip->next = new;
 100    }
 101
 102    for (SCFPSupportSMList *tmp = new->next; tmp != NULL; tmp = tmp->next) {
 103        if (list_id == tmp->list_id) {
 104            SCLogError(SC_ERR_FATAL, "SM list already registered.");
 105            exit(EXIT_FAILURE);
 106        }
 107    }
 108
 109    return;
 110}
 111
 112/**
 113 * \brief Registers the keywords(SMs) that should be given fp support.
 114 */
 115void SupportFastPatternForSigMatchTypes(void)
 116{
 117    SupportFastPatternForSigMatchList(DETECT_SM_LIST_HCBDMATCH, 2);
 118    SupportFastPatternForSigMatchList(DETECT_SM_LIST_HSBDMATCH, 2);
 119
 120    SupportFastPatternForSigMatchList(DETECT_SM_LIST_HHDMATCH, 2);
 121    SupportFastPatternForSigMatchList(DETECT_SM_LIST_HRHDMATCH, 2);
 122
 123    SupportFastPatternForSigMatchList(DETECT_SM_LIST_UMATCH, 2);
 124    SupportFastPatternForSigMatchList(DETECT_SM_LIST_HRUDMATCH, 2);
 125
 126    SupportFastPatternForSigMatchList(DETECT_SM_LIST_HHHDMATCH, 2);
 127    SupportFastPatternForSigMatchList(DETECT_SM_LIST_HRHHDMATCH, 2);
 128
 129    SupportFastPatternForSigMatchList(DETECT_SM_LIST_HCDMATCH, 2);
 130    SupportFastPatternForSigMatchList(DETECT_SM_LIST_HUADMATCH, 2);
 131
 132    SupportFastPatternForSigMatchList(DETECT_SM_LIST_PMATCH, 3);
 133    SupportFastPatternForSigMatchList(DETECT_SM_LIST_HMDMATCH, 3);
 134    SupportFastPatternForSigMatchList(DETECT_SM_LIST_HSCDMATCH, 3);
 135    SupportFastPatternForSigMatchList(DETECT_SM_LIST_HSMDMATCH, 3);
 136
 137#if 0
 138    SCFPSupportSMList *tmp = sm_fp_support_smlist_list;
 139    while (tmp != NULL) {
 140        printf("%d - %d\n", tmp->list_id, tmp->priority);
 141
 142        tmp = tmp->next;
 143    }
 144#endif
 145
 146    return;
 147}
 148
 149/**
 150 * \brief Registration function for fast_pattern keyword
 151 */
 152void DetectFastPatternRegister(void)
 153{
 154    sigmatch_table[DETECT_FAST_PATTERN].name = "fast_pattern";
 155    sigmatch_table[DETECT_FAST_PATTERN].desc = "force using preceding content in the multi pattern matcher";
 156    sigmatch_table[DETECT_FAST_PATTERN].url = "https://redmine.openinfosecfoundation.org/projects/suricata/wiki/HTTP-keywords#fast_pattern";
 157    sigmatch_table[DETECT_FAST_PATTERN].Match = NULL;
 158    sigmatch_table[DETECT_FAST_PATTERN].Setup = DetectFastPatternSetup;
 159    sigmatch_table[DETECT_FAST_PATTERN].Free  = NULL;
 160    sigmatch_table[DETECT_FAST_PATTERN].RegisterTests = DetectFastPatternRegisterTests;
 161
 162    sigmatch_table[DETECT_FAST_PATTERN].flags |= SIGMATCH_PAYLOAD;
 163
 164    const char *eb;
 165    int eo;
 166    int opts = 0;
 167
 168    parse_regex = pcre_compile(DETECT_FAST_PATTERN_REGEX, opts, &eb, &eo, NULL);
 169    if(parse_regex == NULL)
 170    {
 171        SCLogError(SC_ERR_PCRE_COMPILE, "pcre compile of \"%s\" failed at "
 172                   "offset %" PRId32 ": %s", DETECT_FAST_PATTERN_REGEX, eo, eb);
 173        goto error;
 174    }
 175
 176    parse_regex_study = pcre_study(parse_regex, 0, &eb);
 177    if(eb != NULL)
 178    {
 179        SCLogError(SC_ERR_PCRE_STUDY, "pcre study failed: %s", eb);
 180        goto error;
 181    }
 182
 183    return;
 184
 185 error:
 186    /* get some way to return an error code! */
 187    return;
 188}
 189
 190//static int DetectFastPatternParseArg(
 191
 192/**
 193 * \brief Configures the previous content context for a fast_pattern modifier
 194 *        keyword used in the rule.
 195 *
 196 * \param de_ctx   Pointer to the Detection Engine Context.
 197 * \param s        Pointer to the Signature to which the current keyword belongs.
 198 * \param null_str Should hold an empty string always.
 199 *
 200 * \retval  0 On success.
 201 * \retval -1 On failure.
 202 */
 203static int DetectFastPatternSetup(DetectEngineCtx *de_ctx, Signature *s, char *arg)
 204{
 205#define MAX_SUBSTRINGS 30
 206    int ret = 0, res = 0;
 207    int ov[MAX_SUBSTRINGS];
 208    const char *arg_substr = NULL;
 209    DetectContentData *cd = NULL;
 210
 211    if (s->sm_lists_tail[DETECT_SM_LIST_PMATCH] == NULL &&
 212        s->sm_lists_tail[DETECT_SM_LIST_UMATCH] == NULL &&
 213        s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH] == NULL &&
 214        s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH] == NULL &&
 215        s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH] == NULL &&
 216        s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH] == NULL &&
 217        s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH] == NULL &&
 218        s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH] == NULL &&
 219        s->sm_lists_tail[DETECT_SM_LIST_HRUDMATCH] == NULL &&
 220        s->sm_lists_tail[DETECT_SM_LIST_HSMDMATCH] == NULL &&
 221        s->sm_lists_tail[DETECT_SM_LIST_HSCDMATCH] == NULL &&
 222        s->sm_lists_tail[DETECT_SM_LIST_HUADMATCH] == NULL &&
 223        s->sm_lists_tail[DETECT_SM_LIST_HHHDMATCH] == NULL &&
 224        s->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH] == NULL) {
 225        SCLogWarning(SC_WARN_COMPATIBILITY, "fast_pattern found inside the "
 226                     "rule, without a preceding content based keyword.  "
 227                     "Currently we provide fast_pattern support for content, "
 228                     "uricontent, http_client_body, http_server_body, http_header, "
 229                     "http_raw_header, http_method, http_cookie, "
 230                     "http_raw_uri, http_stat_msg, http_stat_code, "
 231                     "http_user_agent, http_host or http_raw_host option");
 232        return -1;
 233    }
 234
 235    SigMatch *pm = SigMatchGetLastSMFromLists(s, 28,
 236            DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_PMATCH],
 237            DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_UMATCH],
 238            DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HCBDMATCH],
 239            DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSBDMATCH],
 240            DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HHDMATCH],
 241            DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRHDMATCH],
 242            DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HMDMATCH],
 243            DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HCDMATCH],
 244            DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSMDMATCH],
 245            DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HSCDMATCH],
 246            DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRUDMATCH],
 247            DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HUADMATCH],
 248            DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HHHDMATCH],
 249            DETECT_CONTENT, s->sm_lists_tail[DETECT_SM_LIST_HRHHDMATCH]);
 250    if (pm == NULL) {
 251        SCLogError(SC_ERR_INVALID_SIGNATURE, "fast_pattern found inside "
 252                   "the rule, without a content context. Please use a "
 253                   "content based keyword before using fast_pattern");
 254        return -1;
 255    }
 256
 257    cd = pm->ctx;
 258    if ((cd->flags & DETECT_CONTENT_NEGATED) &&
 259        ((cd->flags & DETECT_CONTENT_DISTANCE) ||
 260         (cd->flags & DETECT_CONTENT_WITHIN) ||
 261         (cd->flags & DETECT_CONTENT_OFFSET) ||
 262         (cd->flags & DETECT_CONTENT_DEPTH))) {
 263
 264        /* we can't have any of these if we are having "only" */
 265        SCLogError(SC_ERR_INVALID_SIGNATURE, "fast_pattern; cannot be "
 266                   "used with negated content, along with relative modifiers");
 267        goto error;
 268    }
 269
 270    if (arg == NULL|| strcmp(arg, "") == 0) {
 271        if (cd->flags & DETECT_CONTENT_FAST_PATTERN) {
 272            SCLogError(SC_ERR_INVALID_SIGNATURE, "can't use multiple fast_pattern "
 273                    "options for the same content");
 274            goto error;
 275        }
 276        else { /*allow only one content to have fast_pattern modifier*/
 277            int list_id = 0;
 278            for (list_id = 0; list_id < DETECT_SM_LIST_MAX; list_id++) {
 279                SigMatch *sm = NULL;
 280                for (sm = s->sm_lists[list_id]; sm != NULL; sm = sm->next) {
 281                    if (sm->type == DETECT_CONTENT) {
 282                        DetectContentData *tmp_cd = sm->ctx;
 283                        if (tmp_cd->flags & DETECT_CONTENT_FAST_PATTERN) {
 284                            SCLogError(SC_ERR_INVALID_SIGNATURE, "fast_pattern "
 285                                        "can be used on only one content in a rule");
 286                            goto error;
 287                        }
 288                    }
 289                } /* for (sm = s->sm_lists[list_id]; sm != NULL; sm = sm->next) */
 290            }
 291        }
 292        cd->flags |= DETECT_CONTENT_FAST_PATTERN;
 293        return 0;
 294    }
 295
 296    /* Execute the regex and populate args with captures. */
 297    ret = pcre_exec(parse_regex, parse_regex_study, arg,
 298                    strlen(arg), 0, 0, ov, MAX_SUBSTRINGS);
 299    /* fast pattern only */
 300    if (ret == 2) {
 301        if ((cd->flags & DETECT_CONTENT_NEGATED) ||
 302            (cd->flags & DETECT_CONTENT_DISTANCE) ||
 303            (cd->flags & DETECT_CONTENT_WITHIN) ||
 304            (cd->flags & DETECT_CONTENT_OFFSET) ||
 305            (cd->flags & DETECT_CONTENT_DEPTH)) {
 306
 307            /* we can't have any of these if we are having "only" */
 308            SCLogError(SC_ERR_INVALID_SIGNATURE, "fast_pattern: only; cannot be "
 309                       "used with negated content or with any of the relative "
 310                       "modifiers like distance, within, offset, depth");
 311            goto error;
 312        }
 313        cd->flags |= DETECT_CONTENT_FAST_PATTERN_ONLY;
 314
 315        /* fast pattern chop */
 316    } else if (ret == 4) {
 317        res = pcre_get_substring((char *)arg, ov, MAX_SUBSTRINGS,
 318                                 2, &arg_substr);
 319        if (res < 0) {
 320            SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed "
 321                       "for fast_pattern offset");
 322            goto error;
 323        }
 324        int offset = atoi(arg_substr);
 325        if (offset > 65535) {
 326            SCLogError(SC_ERR_INVALID_SIGNATURE, "Fast pattern offset exceeds "
 327                       "limit");
 328            goto error;
 329        }
 330
 331        res = pcre_get_substring((char *)arg, ov, MAX_SUBSTRINGS,
 332                                 3, &arg_substr);
 333        if (res < 0) {
 334            SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed "
 335                       "for fast_pattern offset");
 336            goto error;
 337        }
 338        int length = atoi(arg_substr);
 339        if (offset > 65535) {
 340            SCLogError(SC_ERR_INVALID_SIGNATURE, "Fast pattern length exceeds "
 341                       "limit");
 342            goto error;
 343        }
 344
 345        if (offset + length > 65535) {
 346            SCLogError(SC_ERR_INVALID_SIGNATURE, "Fast pattern (length + offset) "
 347                       "exceeds limit pattern length limit");
 348            goto error;
 349        }
 350
 351        if (offset + length > cd->content_len) {
 352            SCLogError(SC_ERR_INVALID_SIGNATURE, "Fast pattern (length + "
 353                       "offset (%u)) exceeds pattern length (%u)",
 354                       offset + length, cd->content_len);
 355            goto error;
 356        }
 357
 358        cd->fp_chop_offset = offset;
 359        cd->fp_chop_len = length;
 360        cd->flags |= DETECT_CONTENT_FAST_PATTERN_CHOP;
 361
 362    } else {
 363        SCLogError(SC_ERR_PCRE_PARSE, "parse error, ret %" PRId32
 364                   ", string %s", ret, arg);
 365        goto error;
 366    }
 367
 368    //int args;
 369    //args = 0;
 370    //printf("ret-%d\n", ret);
 371    //for (args = 0; args < ret; args++) {
 372    //    res = pcre_get_substring((char *)arg, ov, MAX_SUBSTRINGS,
 373    //                             args, &arg_substr);
 374    //    if (res < 0) {
 375    //        SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed "
 376    //                   "for arg 1");
 377    //        goto error;
 378    //    }
 379    //    printf("%d-%s\n", args, arg_substr);
 380    //}
 381
 382    cd->flags |= DETECT_CONTENT_FAST_PATTERN;
 383
 384    return 0;
 385
 386 error:
 387    return -1;
 388}
 389
 390/*----------------------------------Unittests---------------------------------*/
 391
 392#ifdef UNITTESTS
 393
 394/**
 395 * \test Checks if a fast_pattern is registered in a Signature
 396 */
 397int DetectFastPatternTest01(void)
 398{
 399    SigMatch *sm = NULL;
 400    DetectEngineCtx *de_ctx = NULL;
 401    int result = 0;
 402
 403    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
 404        goto end;
 405
 406    de_ctx->flags |= DE_QUIET;
 407    de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any "
 408                               "(content:\"/one/\"; tcpv4-csum:valid; fast_pattern; "
 409                               "msg:\"Testing fast_pattern\"; sid:1;)");
 410    if (de_ctx->sig_list == NULL)
 411        goto end;
 412
 413    result = 0;
 414    sm = de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH];
 415    while (sm != NULL) {
 416        if (sm->type == DETECT_CONTENT) {
 417            if ( ((DetectContentData *)sm->ctx)->flags &
 418                 DETECT_CONTENT_FAST_PATTERN) {
 419                result = 1;
 420                break;
 421            } else {
 422                result = 0;
 423                break;
 424            }
 425        }
 426        sm = sm->next;
 427    }
 428
 429 end:
 430    SigCleanSignatures(de_ctx);
 431    DetectEngineCtxFree(de_ctx);
 432    return result;
 433}
 434
 435/**
 436 * \test Checks if a fast_pattern is registered in a Signature
 437 */
 438int DetectFastPatternTest02(void)
 439{
 440    DetectEngineCtx *de_ctx = NULL;
 441    int result = 0;
 442
 443    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
 444        goto end;
 445
 446    de_ctx->flags |= DE_QUIET;
 447    de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any "
 448                               "(content:\"/one/\"; fast_pattern; "
 449                               "content:\"boo\"; fast_pattern; "
 450                               "msg:\"Testing fast_pattern\"; sid:1;)");
 451    if (de_ctx->sig_list != NULL)
 452        goto end;
 453
 454    result = 1;
 455
 456 end:
 457    SigCleanSignatures(de_ctx);
 458    DetectEngineCtxFree(de_ctx);
 459    return result;
 460}
 461
 462/**
 463 * \test Checks that we have no fast_pattern registerd for a Signature when the
 464 *       Signature doesn't contain a fast_pattern
 465 */
 466int DetectFastPatternTest03(void)
 467{
 468    SigMatch *sm = NULL;
 469    DetectEngineCtx *de_ctx = NULL;
 470    int result = 0;
 471
 472    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
 473        goto end;
 474
 475    de_ctx->flags |= DE_QUIET;
 476    de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any "
 477                               "(content:\"/one/\"; "
 478                               "msg:\"Testing fast_pattern\"; sid:1;)");
 479    if (de_ctx->sig_list == NULL)
 480        goto end;
 481
 482    result = 0;
 483    sm = de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH];
 484    while (sm != NULL) {
 485        if (sm->type == DETECT_CONTENT) {
 486            if ( !(((DetectContentData *)sm->ctx)->flags &
 487                   DETECT_CONTENT_FAST_PATTERN)) {
 488                result = 1;
 489            } else {
 490                result = 0;
 491                break;
 492            }
 493        }
 494        sm = sm->next;
 495    }
 496
 497 end:
 498    SigCleanSignatures(de_ctx);
 499    DetectEngineCtxFree(de_ctx);
 500    return result;
 501}
 502
 503/**
 504 * \test Checks that a fast_pattern is not registered in a Signature, when we
 505 *       supply a fast_pattern with an argument
 506 */
 507int DetectFastPatternTest04(void)
 508{
 509    DetectEngineCtx *de_ctx = NULL;
 510    int result = 0;
 511
 512    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
 513        goto end;
 514
 515    de_ctx->flags |= DE_QUIET;
 516    de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any "
 517                               "(content:\"/one/\"; fast_pattern:boo; "
 518                               "msg:\"Testing fast_pattern\"; sid:1;)");
 519    if (de_ctx->sig_list == NULL)
 520        result = 1;
 521
 522 end:
 523    SigCleanSignatures(de_ctx);
 524    DetectEngineCtxFree(de_ctx);
 525    return result;
 526}
 527
 528/**
 529 * \test Checks that a fast_pattern is used in the mpm phase.
 530 */
 531int DetectFastPatternTest05(void)
 532{
 533    uint8_t *buf = (uint8_t *) "Oh strin1.  But what "
 534        "strin2.  This is strings3.  We strins_str4. we "
 535        "have strins_string5";
 536    uint16_t buflen = strlen((char *)buf);
 537    Packet *p = NULL;
 538    ThreadVars th_v;
 539    DetectEngineThreadCtx *det_ctx = NULL;
 540    int result = 0;
 541
 542    memset(&th_v, 0, sizeof(th_v));
 543
 544    p = UTHBuildPacket(buf,buflen,IPPROTO_TCP);
 545
 546    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
 547    if (de_ctx == NULL)
 548        goto end;
 549
 550    de_ctx->flags |= DE_QUIET;
 551
 552    de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
 553                               "(msg:\"fast_pattern test\"; content:\"string1\"; "
 554                               "content:\"string2\"; content:\"strings3\"; fast_pattern; "
 555                               "content:\"strings_str4\"; content:\"strings_string5\"; "
 556                               "sid:1;)");
 557    if (de_ctx->sig_list == NULL) {
 558        printf("sig parse failed: ");
 559        goto end;
 560    }
 561
 562    SigGroupBuild(de_ctx);
 563    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
 564
 565    /* start the search phase */
 566    det_ctx->sgh = SigMatchSignaturesGetSgh(de_ctx, det_ctx, p);
 567    if (PacketPatternSearchWithStreamCtx(det_ctx, p) != 0)
 568        result = 1;
 569
 570    SigGroupCleanup(de_ctx);
 571    SigCleanSignatures(de_ctx);
 572
 573    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
 574
 575end:
 576    UTHFreePackets(&p, 1);
 577    DetectEngineCtxFree(de_ctx);
 578    return result;
 579}
 580
 581/**
 582 * \test Checks that a fast_pattern is used in the mpm phase.
 583 */
 584int DetectFastPatternTest06(void)
 585{
 586    uint8_t *buf = (uint8_t *) "Oh this is a string1.  But what is this with "
 587        "string2.  This is strings3.  We have strings_str4.  We also have "
 588        "strings_string5";
 589    uint16_t buflen = strlen((char *)buf);
 590    Packet *p = NULL;
 591    ThreadVars th_v;
 592    DetectEngineThreadCtx *det_ctx = NULL;
 593    int result = 0;
 594
 595    memset(&th_v, 0, sizeof(th_v));
 596    p = UTHBuildPacket(buf,buflen,IPPROTO_TCP);
 597
 598    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
 599    if (de_ctx == NULL)
 600        goto end;
 601
 602    de_ctx->flags |= DE_QUIET;
 603
 604    de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
 605                               "(msg:\"fast_pattern test\"; content:\"string1\"; "
 606                               "content:\"string2\"; content:\"strings3\"; fast_pattern; "
 607                               "content:\"strings_str4\"; content:\"strings_string5\"; "
 608                               "sid:1;)");
 609    if (de_ctx->sig_list == NULL)
 610        goto end;
 611
 612    SigGroupBuild(de_ctx);
 613    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
 614
 615    /* start the search phase */
 616    det_ctx->sgh = SigMatchSignaturesGetSgh(de_ctx, det_ctx, p);
 617    if (PacketPatternSearchWithStreamCtx(det_ctx, p) != 0)
 618        result = 1;
 619
 620    SigGroupCleanup(de_ctx);
 621    SigCleanSignatures(de_ctx);
 622
 623    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
 624
 625end:
 626    UTHFreePackets(&p, 1);
 627    DetectEngineCtxFree(de_ctx);
 628    return result;
 629}
 630
 631/**
 632 * \test Checks that a fast_pattern is used in the mpm phase, when the payload
 633 *       doesn't contain the fast_pattern string within it.
 634 */
 635int DetectFastPatternTest07(void)
 636{
 637    uint8_t *buf = (uint8_t *) "Dummy is our name.  Oh yes.  From right here "
 638        "right now, all the way to hangover.  right.  now here comes our "
 639        "dark knight strings_string5.  Yes here is our dark knight";
 640    uint16_t buflen = strlen((char *)buf);
 641    Packet *p = NULL;
 642    ThreadVars th_v;
 643    DetectEngineThreadCtx *det_ctx = NULL;
 644    int result = 0;
 645
 646    memset(&th_v, 0, sizeof(th_v));
 647    p = UTHBuildPacket(buf,buflen,IPPROTO_TCP);
 648
 649    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
 650    if (de_ctx == NULL)
 651        goto end;
 652
 653    de_ctx->flags |= DE_QUIET;
 654
 655    de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
 656                               "(msg:\"fast_pattern test\"; content:\"string1\"; "
 657                               "content:\"string2\"; content:\"strings3\"; fast_pattern; "
 658                               "content:\"strings_str4\"; content:\"strings_string5\"; "
 659                               "sid:1;)");
 660    if (de_ctx->sig_list == NULL)
 661        goto end;
 662
 663    SigGroupBuild(de_ctx);
 664    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
 665
 666    /* start the search phase */
 667    det_ctx->sgh = SigMatchSignaturesGetSgh(de_ctx, det_ctx, p);
 668    if (PacketPatternSearchWithStreamCtx(det_ctx, p) == 0)
 669        result = 1;
 670
 671    SigGroupCleanup(de_ctx);
 672    SigCleanSignatures(de_ctx);
 673
 674    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
 675
 676end:
 677    UTHFreePackets(&p, 1);
 678    DetectEngineCtxFree(de_ctx);
 679    return result;
 680}
 681
 682/**
 683 * \test Checks that a fast_pattern is used in the mpm phase and that we get
 684 *       exactly 1 match for the mpm phase.
 685 */
 686int DetectFastPatternTest08(void)
 687{
 688    uint8_t *buf = (uint8_t *) "Dummy is our name.  Oh yes.  From right here "
 689        "right now, all the way to hangover.  right.  now here comes our "
 690        "dark knight strings3.  Yes here is our dark knight";
 691    uint16_t buflen = strlen((char *)buf);
 692    Packet *p = NULL;
 693    ThreadVars th_v;
 694    DetectEngineThreadCtx *det_ctx = NULL;
 695    int result = 0;
 696
 697    memset(&th_v, 0, sizeof(th_v));
 698    p = UTHBuildPacket(buf,buflen,IPPROTO_TCP);
 699
 700    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
 701    if (de_ctx == NULL) {
 702        printf("de_ctx init: ");
 703        goto end;
 704    }
 705
 706    de_ctx->flags |= DE_QUIET;
 707
 708    de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
 709                               "(msg:\"fast_pattern test\"; content:\"string1\"; "
 710                               "content:\"string2\"; content:\"strings3\"; fast_pattern; "
 711                               "content:\"strings_str4\"; content:\"strings_string5\"; "
 712                               "sid:1;)");
 713    if (de_ctx->sig_list == NULL) {
 714        printf("sig parse failed: ");
 715        goto end;
 716    }
 717
 718    SigGroupBuild(de_ctx);
 719    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
 720
 721    /* start the search phase */
 722    det_ctx->sgh = SigMatchSignaturesGetSgh(de_ctx, det_ctx, p);
 723    uint32_t r = PacketPatternSearchWithStreamCtx(det_ctx, p);
 724    if (r != 1) {
 725        printf("expected 1, got %"PRIu32": ", r);
 726        goto end;
 727    }
 728
 729    result = 1;
 730end:
 731    UTHFreePackets(&p, 1);
 732    SigGroupCleanup(de_ctx);
 733    SigCleanSignatures(de_ctx);
 734    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
 735    DetectEngineCtxFree(de_ctx);
 736    return result;
 737}
 738/**
 739 * \test Checks that a fast_pattern is used in the mpm phase, when the payload
 740 *       doesn't contain the fast_pattern string within it.
 741 */
 742int DetectFastPatternTest09(void)
 743{
 744    uint8_t *buf = (uint8_t *) "Dummy is our name.  Oh yes.  From right here "
 745        "right now, all the way to hangover.  right.  no_strings4 _imp now here "
 746        "comes our dark knight strings3.  Yes here is our dark knight";
 747    uint16_t buflen = strlen((char *)buf);
 748    Packet *p = NULL;
 749    ThreadVars th_v;
 750    DetectEngineThreadCtx *det_ctx = NULL;
 751    int result = 0;
 752
 753    memset(&th_v, 0, sizeof(th_v));
 754    p = UTHBuildPacket(buf,buflen,IPPROTO_TCP);
 755
 756    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
 757    if (de_ctx == NULL)
 758        goto end;
 759
 760    de_ctx->flags |= DE_QUIET;
 761
 762    de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
 763                               "(msg:\"fast_pattern test\"; content:\"string1\"; "
 764                               "content:\"string2\"; content:\"strings3\"; "
 765                               "content:\"strings4_imp\"; fast_pattern; "
 766                               "content:\"strings_string5\"; sid:1;)");
 767    if (de_ctx->sig_list == NULL)
 768        goto end;
 769
 770    SigGroupBuild(de_ctx);
 771    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
 772
 773    /* start the search phase */
 774    det_ctx->sgh = SigMatchSignaturesGetSgh(de_ctx, det_ctx, p);
 775    if (PacketPatternSearchWithStreamCtx(det_ctx, p) == 0)
 776        result = 1;
 777
 778    SigGroupCleanup(de_ctx);
 779    SigCleanSignatures(de_ctx);
 780
 781    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
 782
 783end:
 784    UTHFreePackets(&p, 1);
 785    DetectEngineCtxFree(de_ctx);
 786    return result;
 787}
 788
 789/**
 790 * \test Checks that a the SigInit chooses the fast_pattern with better pattern
 791 *       strength, when we have multiple fast_patterns in the Signature.  Also
 792 *       checks that we get a match for the fast_pattern from the mpm phase.
 793 */
 794int DetectFastPatternTest10(void)
 795{
 796    uint8_t *buf = (uint8_t *) "Dummy is our name.  Oh yes.  From right here "
 797        "right now, all the way to hangover.  right.  strings4_imp now here "
 798        "comes our dark knight strings5.  Yes here is our dark knight";
 799    uint16_t buflen = strlen((char *)buf);
 800    Packet *p = NULL;
 801    ThreadVars th_v;
 802    DetectEngineThreadCtx *det_ctx = NULL;
 803    int result = 0;
 804
 805    memset(&th_v, 0, sizeof(th_v));
 806    p = UTHBuildPacket(buf,buflen,IPPROTO_TCP);
 807
 808    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
 809    if (de_ctx == NULL) {
 810        printf("de_ctx init: ");
 811        goto end;
 812    }
 813
 814    de_ctx->flags |= DE_QUIET;
 815
 816    de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
 817                               "(msg:\"fast_pattern test\"; content:\"string1\"; "
 818                               "content:\"string2\"; content:\"strings3\"; "
 819                               "content:\"strings4_imp\"; fast_pattern; "
 820                               "content:\"strings_string5\"; sid:1;)");
 821    if (de_ctx->sig_list == NULL) {
 822        printf("sig parse failed: ");
 823        goto end;
 824    }
 825
 826    SigGroupBuild(de_ctx);
 827    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
 828
 829    /* start the search phase */
 830    det_ctx->sgh = SigMatchSignaturesGetSgh(de_ctx, det_ctx, p);
 831    uint32_t r = PacketPatternSearchWithStreamCtx(det_ctx, p);
 832    if (r != 1) {
 833        printf("expected 1, got %"PRIu32": ", r);
 834        goto end;
 835    }
 836
 837    result = 1;
 838end:
 839    UTHFreePackets(&p, 1);
 840    SigGroupCleanup(de_ctx);
 841    SigCleanSignatures(de_ctx);
 842    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
 843    DetectEngineCtxFree(de_ctx);
 844    return result;
 845}
 846
 847/**
 848 * \test Checks that a the SigInit chooses the fast_pattern with better pattern
 849 *       strength, when we have multiple fast_patterns in the Signature.  Also
 850 *       checks that we get no matches for the fast_pattern from the mpm phase.
 851 */
 852int DetectFastPatternTest11(void)
 853{
 854    uint8_t *buf = (uint8_t *) "Dummy is our name.  Oh yes.  From right here "
 855        "right now, all the way to hangover.  right.  strings5_imp now here "
 856        "comes our dark knight strings5.  Yes here is our dark knight";
 857    uint16_t buflen = strlen((char *)buf);
 858    Packet *p = NULL;
 859    ThreadVars th_v;
 860    DetectEngineThreadCtx *det_ctx = NULL;
 861    int result = 0;
 862
 863    memset(&th_v, 0, sizeof(th_v));
 864    p = UTHBuildPacket(buf,buflen,IPPROTO_TCP);
 865
 866    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
 867    if (de_ctx == NULL)
 868        goto end;
 869
 870    de_ctx->flags |= DE_QUIET;
 871
 872    de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
 873                               "(msg:\"fast_pattern test\"; content:\"string1\"; "
 874                               "content:\"string2\"; content:\"strings3\"; "
 875                               "content:\"strings4_imp\"; fast_pattern; "
 876                               "content:\"strings_string5\"; sid:1;)");
 877    if (de_ctx->sig_list == NULL)
 878        goto end;
 879
 880    SigGroupBuild(de_ctx);
 881    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
 882
 883    /* start the search phase */
 884    det_ctx->sgh = SigMatchSignaturesGetSgh(de_ctx, det_ctx, p);
 885    if (PacketPatternSearchWithStreamCtx(det_ctx, p) == 0)
 886        result = 1;
 887
 888
 889end:
 890    UTHFreePackets(&p, 1);
 891    if (de_ctx != NULL) {
 892        SigGroupCleanup(de_ctx);
 893        SigCleanSignatures(de_ctx);
 894        if (det_ctx != NULL)
 895            DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
 896        DetectEngineCtxFree(de_ctx);
 897    }
 898    return result;
 899}
 900
 901/**
 902 * \test Checks that we don't get a match for the mpm phase.
 903 */
 904int DetectFastPatternTest12(void)
 905{
 906    uint8_t *buf = (uint8_t *) "Dummy is our name.  Oh yes.  From right here "
 907        "right now, all the way to hangover.  right.  strings5_imp now here "
 908        "comes our dark knight strings5.  Yes here is our dark knight";
 909    uint16_t buflen = strlen((char *)buf);
 910    Packet *p = NULL;
 911    ThreadVars th_v;
 912    DetectEngineThreadCtx *det_ctx = NULL;
 913    int result = 0;
 914
 915    memset(&th_v, 0, sizeof(th_v));
 916    p = UTHBuildPacket(buf,buflen,IPPROTO_TCP);
 917
 918    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
 919    if (de_ctx == NULL)
 920        goto end;
 921
 922    de_ctx->flags |= DE_QUIET;
 923
 924    de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
 925                               "(msg:\"fast_pattern test\"; content:\"string1\"; "
 926                               "content:\"string2\"; content:\"strings3\"; "
 927                               "content:\"strings4_imp\"; "
 928                               "content:\"strings_string5\"; sid:1;)");
 929    if (de_ctx->sig_list == NULL)
 930        goto end;
 931
 932    SigGroupBuild(de_ctx);
 933    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
 934
 935    /* start the search phase */
 936    det_ctx->sgh = SigMatchSignaturesGetSgh(de_ctx, det_ctx, p);
 937    if (PacketPatternSearchWithStreamCtx(det_ctx, p) == 0)
 938        result = 1;
 939
 940    SigGroupCleanup(de_ctx);
 941    SigCleanSignatures(de_ctx);
 942
 943    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
 944
 945end:
 946    UTHFreePackets(&p, 1);
 947    DetectEngineCtxFree(de_ctx);
 948    return result;
 949}
 950
 951/**
 952 * \test Checks that a the SigInit chooses the fast_pattern with a better
 953 *       strength from the available patterns, when we don't specify a
 954 *       fast_pattern.  We also check that we get a match from the mpm
 955 *       phase.
 956 */
 957int DetectFastPatternTest13(void)
 958{
 959    uint8_t *buf = (uint8_t *) "Dummy is our name.  Oh yes.  From right here "
 960        "right now, all the way to hangover.  right.  strings5_imp now here "
 961        "comes our dark knight strings_string5.  Yes here is our dark knight";
 962    uint16_t buflen = strlen((char *)buf);
 963    Packet *p = NULL;
 964    ThreadVars th_v;
 965    DetectEngineThreadCtx *det_ctx = NULL;
 966    int result = 0;
 967
 968    memset(&th_v, 0, sizeof(th_v));
 969    p = UTHBuildPacket(buf,buflen,IPPROTO_TCP);
 970
 971    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
 972    if (de_ctx == NULL) {
 973        printf("de_ctx init: ");
 974        goto end;
 975    }
 976
 977    de_ctx->flags |= DE_QUIET;
 978
 979    de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
 980                               "(msg:\"fast_pattern test\"; content:\"string1\"; "
 981                               "content:\"string2\"; content:\"strings3\"; "
 982                               "content:\"strings4_imp\"; "
 983                               "content:\"strings_string5\"; sid:1;)");
 984    if (de_ctx->sig_list == NULL) {
 985        printf("sig parse failed: ");
 986        goto end;
 987    }
 988
 989    SigGroupBuild(de_ctx);
 990    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
 991
 992    /* start the search phase */
 993    det_ctx->sgh = SigMatchSignaturesGetSgh(de_ctx, det_ctx, p);
 994    uint32_t r = PacketPatternSearchWithStreamCtx(det_ctx, p);
 995    if (r != 1) {
 996        printf("expected 1 result, got %"PRIu32": ", r);
 997        goto end;
 998    }
 999
1000    result = 1;
1001end:
1002    UTHFreePackets(&p, 1);
1003    SigGroupCleanup(de_ctx);
1004    SigCleanSignatures(de_ctx);
1005    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1006    DetectEngineCtxFree(de_ctx);
1007    return result;
1008}
1009
1010/**
1011 * \test Checks to make sure that other sigs work that should when fast_pattern is inspecting on the same payload
1012 *
1013 */
1014int DetectFastPatternTest14(void)
1015{
1016    uint8_t *buf = (uint8_t *) "Dummy is our name.  Oh yes.  From right here "
1017        "right now, all the way to hangover.  right.  strings5_imp now here "
1018        "comes our dark knight strings_string5.  Yes here is our dark knight";
1019    uint16_t buflen = strlen((char *)buf);
1020    Packet *p = NULL;
1021    ThreadVars th_v;
1022    DetectEngineThreadCtx *det_ctx = NULL;
1023    int alertcnt = 0;
1024    int result = 0;
1025
1026    memset(&th_v, 0, sizeof(th_v));
1027    p = UTHBuildPacket(buf,buflen,IPPROTO_TCP);
1028
1029    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1030    if (de_ctx == NULL)
1031        goto end;
1032
1033    FlowInitConfig(FLOW_QUIET);
1034
1035    de_ctx->mpm_matcher = MPM_B3G;
1036    de_ctx->flags |= DE_QUIET;
1037
1038    de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
1039                               "(msg:\"fast_pattern test\"; content:\"strings_string5\"; content:\"knight\"; fast_pattern; sid:1;)");
1040    if (de_ctx->sig_list == NULL)
1041        goto end;
1042
1043    de_ctx->sig_list->next = SigInit(de_ctx, "alert tcp any any -> any any "
1044                                     "(msg:\"test different content\"; content:\"Dummy is our name\"; sid:2;)");
1045    if (de_ctx->sig_list->next == NULL)
1046        goto end;
1047
1048    SigGroupBuild(de_ctx);
1049    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1050
1051    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1052    if (PacketAlertCheck(p, 1)){
1053        alertcnt++;
1054    }else{
1055        SCLogInfo("could not match on sig 1 with when fast_pattern is inspecting payload");
1056        goto end;
1057    }
1058    if (PacketAlertCheck(p, 2)){
1059        result = 1;
1060    }else{
1061        SCLogInfo("match on sig 1 fast_pattern no match sig 2 inspecting same payload");
1062    }
1063end:
1064    UTHFreePackets(&p, 1);
1065    SigGroupCleanup(de_ctx);
1066    SigCleanSignatures(de_ctx);
1067
1068    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1069
1070    DetectEngineCtxFree(de_ctx);
1071    FlowShutdown();
1072    return result;
1073}
1074
1075/**
1076 * \test Checks if a fast_pattern is registered in a Signature
1077 */
1078int DetectFastPatternTest15(void)
1079{
1080    SigMatch *sm = NULL;
1081    DetectEngineCtx *de_ctx = NULL;
1082    int result = 0;
1083
1084    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
1085        goto end;
1086
1087    de_ctx->flags |= DE_QUIET;
1088    de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any "
1089                               "(content:\"/one/\"; fast_pattern:only; "
1090                               "msg:\"Testing fast_pattern\"; sid:1;)");
1091    if (de_ctx->sig_list == NULL)
1092        goto end;
1093
1094    result = 0;
1095    sm = de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH];
1096    while (sm != NULL) {
1097        if (sm->type == DETECT_CONTENT) {
1098            if ( ((DetectContentData *)sm->ctx)->flags &
1099                 DETECT_CONTENT_FAST_PATTERN) {
1100                result = 1;
1101                break;
1102            } else {
1103                result = 0;
1104                break;
1105            }
1106        }
1107        sm = sm->next;
1108    }
1109
1110 end:
1111    SigCleanSignatures(de_ctx);
1112    DetectEngineCtxFree(de_ctx);
1113    return result;
1114}
1115
1116/**
1117 * \test Checks if a fast_pattern is registered in a Signature
1118 */
1119int DetectFastPatternTest16(void)
1120{
1121    SigMatch *sm = NULL;
1122    DetectEngineCtx *de_ctx = NULL;
1123    int result = 0;
1124
1125    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
1126        goto end;
1127
1128    de_ctx->flags |= DE_QUIET;
1129    de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any "
1130                               "(content:\"oneoneone\"; fast_pattern:3,4; "
1131                               "msg:\"Testing fast_pattern\"; sid:1;)");
1132    if (de_ctx->sig_list == NULL)
1133        goto end;
1134
1135    result = 0;
1136    sm = de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH];
1137    while (sm != NULL) {
1138        if (sm->type == DETECT_CONTENT) {
1139            if ( ((DetectContentData *)sm->ctx)->flags &
1140                 DETECT_CONTENT_FAST_PATTERN) {
1141                result = 1;
1142                break;
1143            } else {
1144                result = 0;
1145                break;
1146            }
1147        }
1148        sm = sm->next;
1149    }
1150
1151 end:
1152    SigCleanSignatures(de_ctx);
1153    DetectEngineCtxFree(de_ctx);
1154    return result;
1155}
1156
1157int DetectFastPatternTest17(void)
1158{
1159    SigMatch *sm = NULL;
1160    DetectEngineCtx *de_ctx = NULL;
1161    int result = 0;
1162
1163    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
1164        goto end;
1165
1166    de_ctx->flags |= DE_QUIET;
1167    de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any "
1168                               "(content:\"one\"; fast_pattern:only; sid:1;)");
1169    if (de_ctx->sig_list == NULL)
1170        goto end;
1171
1172    result = 0;
1173    sm = de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH];
1174    DetectContentData *cd = sm->ctx;
1175    if (sm->type == DETECT_CONTENT) {
1176        if (cd->flags & DETECT_CONTENT_FAST_PATTERN &&
1177            cd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY &&
1178            !(cd->flags & cd->flags & DETECT_CONTENT_FAST_PATTERN_CHOP) &&
1179            cd->fp_chop_offset == 0 &&
1180            cd->fp_chop_len == 0) {
1181            result = 1;
1182        } else {
1183            result = 0;
1184        }
1185    }
1186
1187 end:
1188    SigCleanSignatures(de_ctx);
1189    DetectEngineCtxFree(de_ctx);
1190    return result;
1191}
1192
1193int DetectFastPatternTest18(void)
1194{
1195    SigMatch *sm = NULL;
1196    DetectEngineCtx *de_ctx = NULL;
1197    int result = 0;
1198
1199    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
1200        goto end;
1201
1202    de_ctx->flags |= DE_QUIET;
1203    de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any "
1204                               "(content:\"oneoneone\"; fast_pattern:3,4; sid:1;)");
1205    if (de_ctx->sig_list == NULL)
1206        goto end;
1207
1208    result = 0;
1209    sm = de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH];
1210    DetectContentData *cd = sm->ctx;
1211    if (sm->type == DETECT_CONTENT) {
1212        if (cd->flags & DETECT_CONTENT_FAST_PATTERN &&
1213            !(cd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) &&
1214            cd->flags & cd->flags & DETECT_CONTENT_FAST_PATTERN_CHOP &&
1215            cd->fp_chop_offset == 3 &&
1216            cd->fp_chop_len == 4) {
1217            result = 1;
1218        } else {
1219            result = 0;
1220        }
1221    }
1222
1223 end:
1224    SigCleanSignatures(de_ctx);
1225    DetectEngineCtxFree(de_ctx);
1226    return result;
1227}
1228
1229int DetectFastPatternTest19(void)
1230{
1231    DetectEngineCtx *de_ctx = NULL;
1232    int result = 0;
1233
1234    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
1235        goto end;
1236
1237    de_ctx->flags |= DE_QUIET;
1238    de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any "
1239                               "(content:\"one\"; content:\"two\"; fast_pattern:only; distance:10; sid:1;)");
1240    if (de_ctx->sig_list != NULL)
1241        goto end;
1242
1243    result = 1;
1244
1245 end:
1246    SigCleanSignatures(de_ctx);
1247    DetectEngineCtxFree(de_ctx);
1248    return result;
1249}
1250
1251int DetectFastPatternTest20(void)
1252{
1253    DetectEngineCtx *de_ctx = NULL;
1254    int result = 0;
1255
1256    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
1257        goto end;
1258
1259    de_ctx->flags |= DE_QUIET;
1260    de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any "
1261                               "(content:\"one\"; content:\"two\"; distance:10; fast_pattern:only; sid:1;)");
1262    if (de_ctx->sig_list != NULL)
1263        goto end;
1264
1265    result = 1;
1266
1267 end:
1268    SigCleanSignatures(de_ctx);
1269    DetectEngineCtxFree(de_ctx);
1270    return result;
1271}
1272
1273int DetectFastPatternTest21(void)
1274{
1275    DetectEngineCtx *de_ctx = NULL;
1276    int result = 0;
1277
1278    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
1279        goto end;
1280
1281    de_ctx->flags |= DE_QUIET;
1282    de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any "
1283                               "(content:\"one\"; content:\"two\"; fast_pattern:only; within:10; sid:1;)");
1284    if (de_ctx->sig_list != NULL)
1285        goto end;
1286
1287    result = 1;
1288
1289 end:
1290    SigCleanSignatures(de_ctx);
1291    DetectEngineCtxFree(de_ctx);
1292    return result;
1293}
1294
1295int DetectFastPatternTest22(void)
1296{
1297    DetectEngineCtx *de_ctx = NULL;
1298    int result = 0;
1299
1300    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
1301        goto end;
1302
1303    de_ctx->flags |= DE_QUIET;
1304    de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any "
1305                               "(content:\"one\"; content:\"two\"; within:10; fast_pattern:only; sid:1;)");
1306    if (de_ctx->sig_list != NULL)
1307        goto end;
1308
1309    result = 1;
1310
1311 end:
1312    SigCleanSignatures(de_ctx);
1313    DetectEngineCtxFree(de_ctx);
1314    return result;
1315}
1316
1317int DetectFastPatternTest23(void)
1318{
1319    DetectEngineCtx *de_ctx = NULL;
1320    int result = 0;
1321
1322    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
1323        goto end;
1324
1325    de_ctx->flags |= DE_QUIET;
1326    de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any "
1327                               "(content:\"one\"; content:\"two\"; fast_pattern:only; offset:10; sid:1;)");
1328    if (de_ctx->sig_list != NULL)
1329        goto end;
1330
1331    result = 1;
1332
1333 end:
1334    SigCleanSignatures(de_ctx);
1335    DetectEngineCtxFree(de_ctx);
1336    return result;
1337}
1338
1339int DetectFastPatternTest24(void)
1340{
1341    DetectEngineCtx *de_ctx = NULL;
1342    int result = 0;
1343
1344    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
1345        goto end;
1346
1347    de_ctx->flags |= DE_QUIET;
1348    de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any "
1349                               "(content:\"one\"; content:\"two\"; offset:10; fast_pattern:only; sid:1;)");
1350    if (de_ctx->sig_list != NULL)
1351        goto end;
1352
1353    result = 1;
1354
1355 end:
1356    SigCleanSignatures(de_ctx);
1357    DetectEngineCtxFree(de_ctx);
1358    return result;
1359}
1360
1361int DetectFastPatternTest25(void)
1362{
1363    DetectEngineCtx *de_ctx = NULL;
1364    int result = 0;
1365
1366    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
1367        goto end;
1368
1369    de_ctx->flags |= DE_QUIET;
1370    de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any "
1371                               "(content:\"one\"; content:\"two\"; fast_pattern:only; depth:10; sid:1;)");
1372    if (de_ctx->sig_list != NULL)
1373        goto end;
1374
1375    result = 1;
1376
1377 end:
1378    SigCleanSignatures(de_ctx);
1379    DetectEngineCtxFree(de_ctx);
1380    return result;
1381}
1382
1383int DetectFastPatternTest26(void)
1384{
1385    DetectEngineCtx *de_ctx = NULL;
1386    int result = 0;
1387
1388    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
1389        goto end;
1390
1391    de_ctx->flags |= DE_QUIET;
1392    de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any "
1393                               "(content:\"one\"; content:\"two\"; depth:10; fast_pattern:only; sid:1;)");
1394    if (de_ctx->sig_list != NULL)
1395        goto end;
1396
1397    result = 1;
1398
1399 end:
1400    SigCleanSignatures(de_ctx);
1401    DetectEngineCtxFree(de_ctx);
1402    return result;
1403}
1404
1405int DetectFastPatternTest27(void)
1406{
1407    DetectEngineCtx *de_ctx = NULL;
1408    int result = 0;
1409
1410    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
1411        goto end;
1412
1413    de_ctx->flags |= DE_QUIET;
1414    de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any "
1415                               "(content:\"one\"; content:!\"two\"; fast_pattern:only; sid:1;)");
1416    if (de_ctx->sig_list != NULL)
1417        goto end;
1418
1419    result = 1;
1420
1421 end:
1422    SigCleanSignatures(de_ctx);
1423    DetectEngineCtxFree(de_ctx);
1424    return result;
1425}
1426
1427int DetectFastPatternTest28(void)
1428{
1429    DetectEngineCtx *de_ctx = NULL;
1430    int result = 0;
1431
1432    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
1433        goto end;
1434
1435    de_ctx->flags |= DE_QUIET;
1436    de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any "
1437                               "(content: \"one\"; content:\"two\"; distance:30; content:\"two\"; fast_pattern:only; sid:1;)");
1438    if (de_ctx->sig_list == NULL)
1439        goto end;
1440
1441    DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx;
1442    if (cd->flags & DETECT_CONTENT_FAST_PATTERN &&
1443        cd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY &&
1444        !(cd->flags & cd->flags & DETECT_CONTENT_FAST_PATTERN_CHOP) &&
1445        cd->fp_chop_offset == 0 &&
1446        cd->fp_chop_len == 0) {
1447        result = 1;
1448    } else {
1449        result = 0;
1450    }
1451
1452 end:
1453    SigCleanSignatures(de_ctx);
1454    DetectEngineCtxFree(de_ctx);
1455    return result;
1456}
1457
1458int DetectFastPatternTest29(void)
1459{
1460    DetectEngineCtx *de_ctx = NULL;
1461    int result = 0;
1462
1463    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
1464        goto end;
1465
1466    de_ctx->flags |= DE_QUIET;
1467    de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any "
1468                               "(content:\"one\"; content:\"two\"; within:30; content:\"two\"; fast_pattern:only; sid:1;)");
1469    if (de_ctx->sig_list == NULL)
1470        goto end;
1471    DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx;
1472    if (cd->flags & DETECT_CONTENT_FAST_PATTERN &&
1473        cd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY &&
1474        !(cd->flags & cd->flags & DETECT_CONTENT_FAST_PATTERN_CHOP) &&
1475        cd->fp_chop_offset == 0 &&
1476        cd->fp_chop_len == 0) {
1477        result = 1;
1478    } else {
1479        result = 0;
1480    }
1481
1482 end:
1483    SigCleanSignatures(de_ctx);
1484    DetectEngineCtxFree(de_ctx);
1485    return result;
1486}
1487
1488int DetectFastPatternTest30(void)
1489{
1490    DetectEngineCtx *de_ctx = NULL;
1491    int result = 0;
1492
1493    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
1494        goto end;
1495
1496    de_ctx->flags |= DE_QUIET;
1497    de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any "
1498                               "(content:\"one\"; content:\"two\"; offset:30; content:\"two\"; fast_pattern:only; sid:1;)");
1499    if (de_ctx->sig_list == NULL)
1500        goto end;
1501    DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx;
1502    if (cd->flags & DETECT_CONTENT_FAST_PATTERN &&
1503        cd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY &&
1504        !(cd->flags & cd->flags & DETECT_CONTENT_FAST_PATTERN_CHOP) &&
1505        cd->fp_chop_offset == 0 &&
1506        cd->fp_chop_len == 0) {
1507        result = 1;
1508    } else {
1509        result = 0;
1510    }
1511
1512 end:
1513    SigCleanSignatures(de_ctx);
1514    DetectEngineCtxFree(de_ctx);
1515    return result;
1516}
1517
1518int DetectFastPatternTest31(void)
1519{
1520    DetectEngineCtx *de_ctx = NULL;
1521    int result = 0;
1522
1523    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
1524        goto end;
1525
1526    de_ctx->flags |= DE_QUIET;
1527    de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any "
1528                               "(content:\"one\"; content:\"two\"; depth:30; content:\"two\"; fast_pattern:only; sid:1;)");
1529    if (de_ctx->sig_list == NULL)
1530        goto end;
1531    DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx;
1532    if (cd->flags & DETECT_CONTENT_FAST_PATTERN &&
1533        cd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY &&
1534        !(cd->flags & cd->flags & DETECT_CONTENT_FAST_PATTERN_CHOP) &&
1535        cd->fp_chop_offset == 0 &&
1536        cd->fp_chop_len == 0) {
1537        result = 1;
1538    } else {
1539        result = 0;
1540    }
1541
1542 end:
1543    SigCleanSignatures(de_ctx);
1544    DetectEngineCtxFree(de_ctx);
1545    return result;
1546}
1547
1548int DetectFastPatternTest32(void)
1549{
1550    DetectEngineCtx *de_ctx = NULL;
1551    int result = 0;
1552
1553    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
1554        goto end;
1555
1556    de_ctx->flags |= DE_QUIET;
1557    de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any "
1558                               "(content:!\"one\"; fast_pattern; content:\"two\"; sid:1;)");
1559    if (de_ctx->sig_list == NULL)
1560        goto end;
1561    DetectContentData *cd = de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->prev->ctx;
1562    if (cd->flags & DETECT_CONTENT_FAST_PATTERN &&
1563        cd->flags & DETECT_CONTENT_NEGATED &&
1564        !(cd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) &&
1565        !(cd->flags & cd->flags & DETECT_CONTENT_FAST_PATTERN_CHOP) &&
1566        cd->fp_chop_offset == 0 &&
1567        cd->fp_chop_len == 0) {
1568        result = 1;
1569    } else {
1570        result = 0;
1571    }
1572
1573 end:
1574    SigCleanSignatures(de_ctx);
1575    DetectEngineCtxFree(de_ctx);
1576    return result;
1577}
1578
1579int DetectFastPatternTest33(void)
1580{
1581    DetectEngineCtx *de_ctx = NULL;
1582    int result = 0;
1583
1584    if ( (de_ctx = DetectEngineCtxInit()) == NULL)
1585        goto end;
1586
1587    de_ctx->flags |= DE_QUIET;
1588    de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any "
1589                               "(content:\"two\"; content:!\"one\"; fast_pattern; distance:20; sid:1;)");
1590    if (de_ctx->sig_list != NULL)
1591        goto end;
1592
1593    result = 1;
1594
1595 end:
1596    SigCleanSignatur

Large files files are truncated, but you can click here to view the full file