/src/detect-fast-pattern.c

https://github.com/decanio/suricata-tilera · C · 19997 lines · 16405 code · 3297 blank · 295 comment · 4164 complexity · 8f001207f0544d429199869e0b3116f1 MD5 · raw file

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