suricata
detect-engine-state.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2021 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  * \defgroup sigstate State support
20  *
21  * State is stored in the ::DetectEngineState structure. This is
22  * basically a containter for storage item of type ::DeStateStore.
23  * They contains an array of ::DeStateStoreItem which store the
24  * state of match for an individual signature identified by
25  * DeStateStoreItem::sid.
26  *
27  * @{
28  */
29 
30 /**
31  * \file
32  *
33  * \author Victor Julien <victor@inliniac.net>
34  * \author Anoop Saldanha <anoopsaldanha@gmail.com>
35  *
36  * \brief State based signature handling.
37  */
38 
39 #include "suricata-common.h"
40 
41 #include "decode.h"
42 
43 #include "detect.h"
44 #include "detect-engine.h"
45 #include "detect-parse.h"
46 #include "detect-engine-state.h"
48 
49 #include "detect-flowvar.h"
50 
51 #include "stream-tcp.h"
52 #include "stream-tcp-private.h"
53 #include "stream-tcp-reassemble.h"
54 
55 #include "app-layer.h"
56 #include "app-layer-parser.h"
57 #include "app-layer-protos.h"
58 #include "app-layer-htp.h"
60 
61 #include "util-unittest.h"
62 #include "util-unittest-helper.h"
63 #include "util-profiling.h"
64 
65 #include "flow-util.h"
66 
67 /** convert enum to string */
68 #define CASE_CODE(E) case E: return #E
69 
70 static inline int StateIsValid(uint16_t alproto, void *alstate)
71 {
72  if (alstate != NULL) {
73  if (alproto == ALPROTO_HTTP1) {
74  HtpState *htp_state = (HtpState *)alstate;
75  if (htp_state->conn != NULL) {
76  return 1;
77  }
78  } else {
79  return 1;
80  }
81  }
82  return 0;
83 }
84 
85 static DeStateStore *DeStateStoreAlloc(void)
86 {
87  DeStateStore *d = SCMalloc(sizeof(DeStateStore));
88  if (unlikely(d == NULL))
89  return NULL;
90  memset(d, 0, sizeof(DeStateStore));
91 
92  return d;
93 }
94 
95 #ifdef DEBUG_VALIDATION
96 static int DeStateSearchState(DetectEngineState *state, uint8_t direction, SigIntId num)
97 {
98  DetectEngineStateDirection *dir_state = &state->dir_state[direction & STREAM_TOSERVER ? 0 : 1];
99  DeStateStore *tx_store = dir_state->head;
100  SigIntId store_cnt;
101  SigIntId state_cnt = 0;
102 
103  for (; tx_store != NULL; tx_store = tx_store->next) {
104  SCLogDebug("tx_store %p", tx_store);
105  for (store_cnt = 0;
106  store_cnt < DE_STATE_CHUNK_SIZE && state_cnt < dir_state->cnt;
107  store_cnt++, state_cnt++)
108  {
109  DeStateStoreItem *item = &tx_store->store[store_cnt];
110  if (item->sid == num) {
111  SCLogDebug("sid %u already in state: %p %p %p %u %u, direction %s",
112  num, state, dir_state, tx_store, state_cnt,
113  store_cnt, direction & STREAM_TOSERVER ? "toserver" : "toclient");
114  return 1;
115  }
116  }
117  }
118  return 0;
119 }
120 #endif
121 
122 static void DeStateSignatureAppend(DetectEngineState *state,
123  const Signature *s, uint32_t inspect_flags, uint8_t direction)
124 {
125  SCEnter();
126 
127  DetectEngineStateDirection *dir_state = &state->dir_state[direction & STREAM_TOSERVER ? 0 : 1];
128 
129 #ifdef DEBUG_VALIDATION
130  BUG_ON(DeStateSearchState(state, direction, s->num));
131 #endif
132  DeStateStore *store = dir_state->tail;
133  if (store == NULL) {
134  store = DeStateStoreAlloc();
135  dir_state->head = store;
136  dir_state->cur = store;
137  dir_state->tail = store;
138  } else if (dir_state->cur) {
139  store = dir_state->cur;
140  } else {
141  store = DeStateStoreAlloc();
142  if (store != NULL) {
143  dir_state->tail->next = store;
144  dir_state->tail = store;
145  dir_state->cur = store;
146  }
147  }
148  if (store == NULL)
149  SCReturn;
150 
151  SigIntId idx = dir_state->cnt % DE_STATE_CHUNK_SIZE;
152  store->store[idx].sid = s->num;
153  store->store[idx].flags = inspect_flags;
154  dir_state->cnt++;
155  /* if current chunk is full, progress cur */
156  if (dir_state->cnt % DE_STATE_CHUNK_SIZE == 0) {
157  dir_state->cur = dir_state->cur->next;
158  }
159 
160  SCReturn;
161 }
162 
164 {
166  if (unlikely(d == NULL))
167  return NULL;
168  memset(d, 0, sizeof(DetectEngineState));
169 
170  return d;
171 }
172 
174 {
175  DeStateStore *store;
176  DeStateStore *store_next;
177  int i = 0;
178 
179  for (i = 0; i < 2; i++) {
180  store = state->dir_state[i].head;
181  while (store != NULL) {
182  store_next = store->next;
183  SCFree(store);
184  store = store_next;
185  }
186  }
187  SCFree(state);
188 
189  return;
190 }
191 
192 static void StoreFileNoMatchCnt(DetectEngineState *de_state, uint16_t file_no_match, uint8_t direction)
193 {
194  de_state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].filestore_cnt += file_no_match;
195 
196  return;
197 }
198 
199 static bool StoreFilestoreSigsCantMatch(const SigGroupHead *sgh, const DetectEngineState *de_state, uint8_t direction)
200 {
201  if (de_state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].filestore_cnt == sgh->filestore_cnt)
202  return true;
203  else
204  return false;
205 }
206 
207 static void StoreStateTxHandleFiles(const SigGroupHead *sgh, Flow *f,
208  DetectEngineState *destate, const uint8_t flow_flags,
209  const uint64_t tx_id, const uint16_t file_no_match)
210 {
211  SCLogDebug("tx %"PRIu64", file_no_match %u", tx_id, file_no_match);
212  StoreFileNoMatchCnt(destate, file_no_match, flow_flags);
213  if (StoreFilestoreSigsCantMatch(sgh, destate, flow_flags)) {
215  }
216 }
217 
219  const SigGroupHead *sgh,
220  Flow *f, void *tx, uint64_t tx_id,
221  const Signature *s,
222  uint32_t inspect_flags, uint8_t flow_flags,
223  const uint16_t file_no_match)
224 {
226  if (destate == NULL) {
227  destate = DetectEngineStateAlloc();
228  if (destate == NULL)
229  return;
230  if (AppLayerParserSetTxDetectState(f, tx, destate) < 0) {
231  DetectEngineStateFree(destate);
232  return;
233  }
234  SCLogDebug("destate created for %"PRIu64, tx_id);
235  }
236  DeStateSignatureAppend(destate, s, inspect_flags, flow_flags);
237  StoreStateTxHandleFiles(sgh, f, destate, flow_flags, tx_id, file_no_match);
238 
239  SCLogDebug("Stored for TX %"PRIu64, tx_id);
240 }
241 
242 /** \brief update flow's inspection id's
243  *
244  * \param f unlocked flow
245  * \param flags direction and disruption flags
246  * \param tag_txs_as_inspected if true all 'complete' txs will be marked
247  * 'inspected'
248  *
249  * \note it is possible that f->alstate, f->alparser are NULL */
251  const bool tag_txs_as_inspected)
252 {
253  if (f->alparser && f->alstate) {
255  f->alstate, flags,
256  tag_txs_as_inspected);
257  }
258  return;
259 }
260 
261 static inline void ResetTxState(DetectEngineState *s)
262 {
263  if (s) {
264  s->dir_state[0].cnt = 0;
265  s->dir_state[0].filestore_cnt = 0;
266  s->dir_state[0].flags = 0;
267  /* reset 'cur' back to the list head */
268  s->dir_state[0].cur = s->dir_state[0].head;
269 
270  s->dir_state[1].cnt = 0;
271  s->dir_state[1].filestore_cnt = 0;
272  s->dir_state[1].flags = 0;
273  /* reset 'cur' back to the list head */
274  s->dir_state[1].cur = s->dir_state[1].head;
275  }
276 }
277 
278 /** \brief Reset de state for active tx'
279  * To be used on detect engine reload.
280  * \param f write LOCKED flow
281  */
283 {
284  void *alstate = FlowGetAppState(f);
285  if (!StateIsValid(f->alproto, alstate)) {
286  return;
287  }
288 
291 
292  uint64_t inspect_tx_id = MIN(inspect_ts, inspect_tc);
293 
294  uint64_t total_txs = AppLayerParserGetTxCnt(f, alstate);
295 
296  for ( ; inspect_tx_id < total_txs; inspect_tx_id++) {
297  void *inspect_tx = AppLayerParserGetTx(f->proto, f->alproto, alstate, inspect_tx_id);
298  if (inspect_tx != NULL) {
299  DetectEngineState *tx_de_state = AppLayerParserGetTxDetectState(f->proto, f->alproto, inspect_tx);
300  ResetTxState(tx_de_state);
301  }
302  }
303 }
304 
305 /*********Unittests*********/
306 
307 #ifdef UNITTESTS
308 
309 static int DeStateTest01(void)
310 {
311  SCLogDebug("sizeof(DetectEngineState)\t\t%"PRIuMAX,
312  (uintmax_t)sizeof(DetectEngineState));
313  SCLogDebug("sizeof(DeStateStore)\t\t\t%"PRIuMAX,
314  (uintmax_t)sizeof(DeStateStore));
315  SCLogDebug("sizeof(DeStateStoreItem)\t\t%"PRIuMAX"",
316  (uintmax_t)sizeof(DeStateStoreItem));
317 
318  return 1;
319 }
320 
321 static int DeStateTest02(void)
322 {
323  uint8_t direction = STREAM_TOSERVER;
325  FAIL_IF_NULL(state);
326  FAIL_IF_NOT_NULL(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head);
327 
328  Signature s;
329  memset(&s, 0x00, sizeof(s));
330 
331  s.num = 0;
332  DeStateSignatureAppend(state, &s, 0, direction);
333  s.num = 11;
334  DeStateSignatureAppend(state, &s, 0, direction);
335  s.num = 22;
336  DeStateSignatureAppend(state, &s, 0, direction);
337  s.num = 33;
338  DeStateSignatureAppend(state, &s, 0, direction);
339  s.num = 44;
340  DeStateSignatureAppend(state, &s, 0, direction);
341  s.num = 55;
342  DeStateSignatureAppend(state, &s, 0, direction);
343  s.num = 66;
344  DeStateSignatureAppend(state, &s, 0, direction);
345  s.num = 77;
346  DeStateSignatureAppend(state, &s, 0, direction);
347  s.num = 88;
348  DeStateSignatureAppend(state, &s, 0, direction);
349  s.num = 99;
350  DeStateSignatureAppend(state, &s, 0, direction);
351  s.num = 100;
352  DeStateSignatureAppend(state, &s, 0, direction);
353  s.num = 111;
354  DeStateSignatureAppend(state, &s, 0, direction);
355  s.num = 122;
356  DeStateSignatureAppend(state, &s, 0, direction);
357  s.num = 133;
358  DeStateSignatureAppend(state, &s, 0, direction);
359  FAIL_IF_NOT(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head ==
360  state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].cur);
361 
362  s.num = 144;
363  DeStateSignatureAppend(state, &s, 0, direction);
364 
365  FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[14].sid != 144);
366  FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head ==
367  state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].cur);
368  FAIL_IF_NOT(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].cur == NULL);
369 
370  s.num = 155;
371  DeStateSignatureAppend(state, &s, 0, direction);
372 
373  FAIL_IF_NOT(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].tail ==
374  state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].cur);
375 
376  s.num = 166;
377  DeStateSignatureAppend(state, &s, 0, direction);
378 
379  FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head == NULL);
380  FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[1].sid != 11);
381  FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->next == NULL);
382  FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[14].sid != 144);
383  FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->next->store[0].sid != 155);
384  FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->next->store[1].sid != 166);
385 
386  ResetTxState(state);
387 
388  FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head == NULL);
389  FAIL_IF_NOT(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head ==
390  state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].cur);
391 
392  s.num = 0;
393  DeStateSignatureAppend(state, &s, 0, direction);
394  s.num = 11;
395  DeStateSignatureAppend(state, &s, 0, direction);
396  s.num = 22;
397  DeStateSignatureAppend(state, &s, 0, direction);
398  s.num = 33;
399  DeStateSignatureAppend(state, &s, 0, direction);
400  s.num = 44;
401  DeStateSignatureAppend(state, &s, 0, direction);
402  s.num = 55;
403  DeStateSignatureAppend(state, &s, 0, direction);
404  s.num = 66;
405  DeStateSignatureAppend(state, &s, 0, direction);
406  s.num = 77;
407  DeStateSignatureAppend(state, &s, 0, direction);
408  s.num = 88;
409  DeStateSignatureAppend(state, &s, 0, direction);
410  s.num = 99;
411  DeStateSignatureAppend(state, &s, 0, direction);
412  s.num = 100;
413  DeStateSignatureAppend(state, &s, 0, direction);
414  s.num = 111;
415  DeStateSignatureAppend(state, &s, 0, direction);
416  s.num = 122;
417  DeStateSignatureAppend(state, &s, 0, direction);
418  s.num = 133;
419  DeStateSignatureAppend(state, &s, 0, direction);
420  FAIL_IF_NOT(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head ==
421  state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].cur);
422  s.num = 144;
423  DeStateSignatureAppend(state, &s, 0, direction);
424  FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[14].sid != 144);
425  FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head ==
426  state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].cur);
427  FAIL_IF_NOT(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].tail ==
428  state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].cur);
429  s.num = 155;
430  DeStateSignatureAppend(state, &s, 0, direction);
431  s.num = 166;
432  DeStateSignatureAppend(state, &s, 0, direction);
433 
434  FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head == NULL);
435  FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[1].sid != 11);
436  FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->next == NULL);
437  FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[14].sid != 144);
438  FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->next->store[0].sid != 155);
439  FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->next->store[1].sid != 166);
440 
441  DetectEngineStateFree(state);
442 
443  PASS;
444 }
445 
446 static int DeStateTest03(void)
447 {
449  FAIL_IF_NULL(state);
450 
451  Signature s;
452  memset(&s, 0x00, sizeof(s));
453 
454  uint8_t direction = STREAM_TOSERVER;
455 
456  s.num = 11;
457  DeStateSignatureAppend(state, &s, 0, direction);
458  s.num = 22;
459  DeStateSignatureAppend(state, &s, BIT_U32(DE_STATE_FLAG_BASE), direction);
460 
461  FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head == NULL);
462  FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[0].sid != 11);
463  FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[0].flags & BIT_U32(DE_STATE_FLAG_BASE));
464  FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[1].sid != 22);
465  FAIL_IF(!(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[1].flags & BIT_U32(DE_STATE_FLAG_BASE)));
466 
467  DetectEngineStateFree(state);
468  PASS;
469 }
470 
471 static int DeStateSigTest01(void)
472 {
473  DetectEngineThreadCtx *det_ctx = NULL;
474  ThreadVars th_v;
475  Flow f;
476  TcpSession ssn;
477  Packet *p = NULL;
478  uint8_t httpbuf1[] = "POST / HTTP/1.0\r\n";
479  uint8_t httpbuf2[] = "User-Agent: Mozilla/1.0\r\n";
480  uint8_t httpbuf3[] = "Cookie: dummy\r\nContent-Length: 10\r\n\r\n";
481  uint8_t httpbuf4[] = "Http Body!";
482  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
483  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
484  uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
485  uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
486 
489 
490  memset(&th_v, 0, sizeof(th_v));
491  memset(&f, 0, sizeof(f));
492  memset(&ssn, 0, sizeof(ssn));
493 
494  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
495  FAIL_IF_NULL(p);
496 
497  FLOW_INITIALIZE(&f);
498  f.protoctx = (void *)&ssn;
499  f.proto = IPPROTO_TCP;
500  f.flags |= FLOW_IPV4;
502 
503  p->flow = &f;
507 
508  StreamTcpInitConfig(true);
509 
512  de_ctx->flags |= DE_QUIET;
513 
514  Signature *s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any (content:\"POST\"; http_method; content:\"dummy\"; http_cookie; sid:1; rev:1;)");
515  FAIL_IF_NULL(s);
516 
518  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
519  FAIL_IF_NULL(det_ctx);
520 
521  int r = AppLayerParserParse(
522  NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
523  FAIL_IF_NOT(r == 0);
524  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
525  FAIL_IF(PacketAlertCheck(p, 1));
526 
527  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
528  FAIL_IF_NOT(r == 0);
529  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
530  FAIL_IF(PacketAlertCheck(p, 1));
531 
532  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf3, httplen3);
533  FAIL_IF_NOT(r == 0);
534  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
536 
537  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf4, httplen4);
538  FAIL_IF_NOT(r == 0);
539  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
540  FAIL_IF(PacketAlertCheck(p, 1));
541 
543  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
545  StreamTcpFreeConfig(true);
546  FLOW_DESTROY(&f);
547  UTHFreePacket(p);
548  PASS;
549 }
550 
551 /** \test multiple pipelined http transactions */
552 static int DeStateSigTest02(void)
553 {
554  DetectEngineThreadCtx *det_ctx = NULL;
555  ThreadVars th_v;
556  Flow f;
557  TcpSession ssn;
558  Packet *p = NULL;
559  uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n";
560  uint8_t httpbuf2[] = "User-Agent: Mozilla/1.0\r\nContent-Length: 10\r\n";
561  uint8_t httpbuf3[] = "Cookie: dummy\r\n\r\n";
562  uint8_t httpbuf4[] = "Http Body!";
563  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
564  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
565  uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
566  uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
567  uint8_t httpbuf5[] = "GET /?var=val HTTP/1.1\r\n";
568  uint8_t httpbuf6[] = "User-Agent: Firefox/1.0\r\n";
569  uint8_t httpbuf7[] = "Cookie: dummy2\r\nContent-Length: 10\r\n\r\nHttp Body!";
570  uint32_t httplen5 = sizeof(httpbuf5) - 1; /* minus the \0 */
571  uint32_t httplen6 = sizeof(httpbuf6) - 1; /* minus the \0 */
572  uint32_t httplen7 = sizeof(httpbuf7) - 1; /* minus the \0 */
575 
576  memset(&th_v, 0, sizeof(th_v));
577  memset(&f, 0, sizeof(f));
578  memset(&ssn, 0, sizeof(ssn));
579 
580  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
581 
582  FLOW_INITIALIZE(&f);
583  f.protoctx = (void *)&ssn;
584  f.proto = IPPROTO_TCP;
585  f.flags |= FLOW_IPV4;
586 
587  p->flow = &f;
592 
593  StreamTcpInitConfig(true);
594 
597 
598  de_ctx->flags |= DE_QUIET;
599 
600  Signature *s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (flow:to_server; content:\"POST\"; http_method; content:\"/\"; http_uri; content:\"Mozilla\"; http_header; content:\"dummy\"; http_cookie; content:\"body\"; nocase; http_client_body; sid:1; rev:1;)");
601  FAIL_IF_NULL(s);
602  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (flow:to_server; content:\"GET\"; http_method; content:\"Firefox\"; http_header; content:\"dummy2\"; http_cookie; sid:2; rev:1;)");
603  FAIL_IF_NULL(s);
604 
606  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
607  FAIL_IF_NULL(det_ctx);
608 
609  int r = AppLayerParserParse(
610  NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
611  FAIL_IF(r != 0);
612  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
613  FAIL_IF(PacketAlertCheck(p, 1));
614 
615  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
616  FAIL_IF(r != 0);
617  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
618  FAIL_IF(PacketAlertCheck(p, 1));
619 
620  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf3, httplen3);
621  FAIL_IF(r != 0);
622  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
623  FAIL_IF(PacketAlertCheck(p, 1));
624 
625  void *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, f.alstate, 0);
626  FAIL_IF_NULL(tx);
627 
628  DetectEngineState *tx_de_state = AppLayerParserGetTxDetectState(IPPROTO_TCP, ALPROTO_HTTP1, tx);
629  FAIL_IF_NULL(tx_de_state);
630  FAIL_IF(tx_de_state->dir_state[0].cnt != 1);
631  /* http_header(mpm): 5, uri: 3, method: 6, cookie: 7 */
632  uint32_t expected_flags = (BIT_U32(5) | BIT_U32(3) | BIT_U32(6) |BIT_U32(7));
633  FAIL_IF(tx_de_state->dir_state[0].head->store[0].flags != expected_flags);
634 
635  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf4, httplen4);
636  FAIL_IF(r != 0);
637  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
638  FAIL_IF(!(PacketAlertCheck(p, 1)));
639 
640  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf5, httplen5);
641  FAIL_IF(r != 0);
642  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
643  FAIL_IF(PacketAlertCheck(p, 1));
644 
645  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf6, httplen6);
646  FAIL_IF(r != 0);
647  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
648  FAIL_IF((PacketAlertCheck(p, 1)) || (PacketAlertCheck(p, 2)));
649 
650  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf7, httplen7);
651  FAIL_IF(r != 0);
652  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
653  FAIL_IF(!(PacketAlertCheck(p, 2)));
654 
656  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
658  StreamTcpFreeConfig(true);
659  FLOW_DESTROY(&f);
660  UTHFreePacket(p);
661  PASS;
662 }
663 
664 static int DeStateSigTest03(void)
665 {
666  uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
667  "Host: www.server.lan\r\n"
668  "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
669  "Content-Length: 215\r\n"
670  "\r\n"
671  "-----------------------------277531038314945\r\n"
672  "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n"
673  "Content-Type: image/jpeg\r\n"
674  "\r\n"
675  "filecontent\r\n"
676  "-----------------------------277531038314945--";
677  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
678  ThreadVars th_v;
679  TcpSession ssn;
680  Flow *f = NULL;
681  Packet *p = NULL;
684 
685  memset(&th_v, 0, sizeof(th_v));
686  memset(&ssn, 0, sizeof(ssn));
687 
688  DetectEngineThreadCtx *det_ctx = NULL;
691 
692  de_ctx->flags |= DE_QUIET;
693 
694  Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any (flow:to_server; content:\"POST\"; http_method; content:\"upload.cgi\"; http_uri; filestore; sid:1; rev:1;)");
695  FAIL_IF_NULL(s);
696 
698  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
699 
700  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
701  FAIL_IF_NULL(f);
702  f->protoctx = &ssn;
703  f->proto = IPPROTO_TCP;
704  f->alproto = ALPROTO_HTTP1;
705 
706  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
707  FAIL_IF_NULL(p);
708 
709  p->flow = f;
713 
714  StreamTcpInitConfig(true);
715 
716  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1,
717  STREAM_TOSERVER | STREAM_START | STREAM_EOF, httpbuf1, httplen1);
718  FAIL_IF(r != 0);
719 
720  HtpState *http_state = f->alstate;
721  FAIL_IF_NULL(http_state);
722  FAIL_IF_NULL(http_state->files_ts);
723 
724  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
725  FAIL_IF(!(PacketAlertCheck(p, 1)));
726 
728  FAIL_IF_NULL(files);
729 
730  File *file = files->head;
731  FAIL_IF_NULL(file);
732 
733  FAIL_IF(!(file->flags & FILE_STORE));
734 
736  UTHFreeFlow(f);
737 
738  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
740  StreamTcpFreeConfig(true);
741  PASS;
742 }
743 
744 static int DeStateSigTest04(void)
745 {
746  uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
747  "Host: www.server.lan\r\n"
748  "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
749  "Content-Length: 215\r\n"
750  "\r\n"
751  "-----------------------------277531038314945\r\n"
752  "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n"
753  "Content-Type: image/jpeg\r\n"
754  "\r\n"
755  "filecontent\r\n"
756  "-----------------------------277531038314945--";
757  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
758  ThreadVars th_v;
759  TcpSession ssn;
762 
763  memset(&th_v, 0, sizeof(th_v));
764  memset(&ssn, 0, sizeof(ssn));
765 
766  DetectEngineThreadCtx *det_ctx = NULL;
769  de_ctx->flags |= DE_QUIET;
770 
771  Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any (content:\"GET\"; http_method; content:\"upload.cgi\"; http_uri; filestore; sid:1; rev:1;)");
772  FAIL_IF_NULL(s);
773 
775  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
776  FAIL_IF_NULL(det_ctx);
777 
778  Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
779  FAIL_IF_NULL(f);
780  f->protoctx = &ssn;
781  f->proto = IPPROTO_TCP;
782  f->alproto = ALPROTO_HTTP1;
783 
784  Packet *p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
785  FAIL_IF_NULL(p);
786  p->flow = f;
790 
791  StreamTcpInitConfig(true);
792 
793  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1,
794  STREAM_TOSERVER | STREAM_START | STREAM_EOF, httpbuf1, httplen1);
795  FAIL_IF(r != 0);
796  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
797  FAIL_IF(PacketAlertCheck(p, 1));
798 
799  HtpState *http_state = f->alstate;
800  FAIL_IF_NULL(http_state);
801  FAIL_IF_NULL(http_state->files_ts);
802 
804  FAIL_IF_NULL(files);
805  File *file = files->head;
806  FAIL_IF_NULL(file);
807 
808  FAIL_IF(file->flags & FILE_STORE);
809 
811  UTHFreeFlow(f);
812  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
814  StreamTcpFreeConfig(true);
815  PASS;
816 }
817 
818 static int DeStateSigTest05(void)
819 {
820  uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
821  "Host: www.server.lan\r\n"
822  "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
823  "Content-Length: 215\r\n"
824  "\r\n"
825  "-----------------------------277531038314945\r\n"
826  "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n"
827  "Content-Type: image/jpeg\r\n"
828  "\r\n"
829  "filecontent\r\n"
830  "-----------------------------277531038314945--";
831  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
832  ThreadVars th_v;
833  TcpSession ssn;
834 
837 
838  memset(&th_v, 0, sizeof(th_v));
839  memset(&ssn, 0, sizeof(ssn));
840 
841  DetectEngineThreadCtx *det_ctx = NULL;
844  de_ctx->flags |= DE_QUIET;
845 
846  Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any (content:\"GET\"; http_method; content:\"upload.cgi\"; http_uri; filename:\"nomatch\"; sid:1; rev:1;)");
847  FAIL_IF_NULL(s);
848 
850  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
851 
852  Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
853  FAIL_IF_NULL(f);
854  f->protoctx = &ssn;
855  f->proto = IPPROTO_TCP;
856  f->alproto = ALPROTO_HTTP1;
857 
858  Packet *p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
859  FAIL_IF_NULL(p);
860  p->flow = f;
864 
865  StreamTcpInitConfig(true);
866 
867  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1,
868  STREAM_TOSERVER | STREAM_START | STREAM_EOF, httpbuf1, httplen1);
869  FAIL_IF_NOT(r == 0);
870  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
871  FAIL_IF(PacketAlertCheck(p, 1));
872 
873  HtpState *http_state = f->alstate;
874  FAIL_IF_NULL(http_state);
875  FAIL_IF_NULL(http_state->files_ts);
876 
878  FAIL_IF_NULL(files);
879  File *file = files->head;
880  FAIL_IF_NULL(file);
881 
882  FAIL_IF(!(file->flags & FILE_NOSTORE));
883 
885  UTHFreeFlow(f);
886  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
888  StreamTcpFreeConfig(true);
889  PASS;
890 }
891 
892 static int DeStateSigTest06(void)
893 {
894  uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
895  "Host: www.server.lan\r\n"
896  "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
897  "Content-Length: 215\r\n"
898  "\r\n"
899  "-----------------------------277531038314945\r\n"
900  "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n"
901  "Content-Type: image/jpeg\r\n"
902  "\r\n"
903  "filecontent\r\n"
904  "-----------------------------277531038314945--";
905  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
906  ThreadVars th_v;
907  TcpSession ssn;
908 
911 
912  memset(&th_v, 0, sizeof(th_v));
913  memset(&ssn, 0, sizeof(ssn));
914 
915  DetectEngineThreadCtx *det_ctx = NULL;
918  de_ctx->flags |= DE_QUIET;
919 
920  Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any (content:\"POST\"; http_method; content:\"upload.cgi\"; http_uri; filename:\"nomatch\"; filestore; sid:1; rev:1;)");
921  FAIL_IF_NULL(s);
922 
924  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
925  FAIL_IF_NULL(det_ctx);
926 
927  Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
928  FAIL_IF_NULL(f);
929  f->protoctx = &ssn;
930  f->proto = IPPROTO_TCP;
931  f->alproto = ALPROTO_HTTP1;
932 
933  Packet *p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
934  FAIL_IF_NULL(p);
935  p->flow = f;
939 
940  StreamTcpInitConfig(true);
941 
942  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1,
943  STREAM_TOSERVER | STREAM_START | STREAM_EOF, httpbuf1, httplen1);
944  FAIL_IF(r != 0);
945  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
946  FAIL_IF(PacketAlertCheck(p, 1));
947 
948  HtpState *http_state = f->alstate;
949  FAIL_IF_NULL(http_state);
950  FAIL_IF_NULL(http_state->files_ts);
951 
953  FAIL_IF_NULL(files);
954  File *file = files->head;
955  FAIL_IF_NULL(file);
956  FAIL_IF(!(file->flags & FILE_NOSTORE));
957 
959  UTHFreeFlow(f);
960  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
962  StreamTcpFreeConfig(true);
963  PASS;
964 }
965 
966 static int DeStateSigTest07(void)
967 {
968  uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
969  "Host: www.server.lan\r\n"
970  "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
971  "Content-Length: 215\r\n"
972  "\r\n"
973  "-----------------------------277531038314945\r\n"
974  "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n"
975  "Content-Type: image/jpeg\r\n"
976  "\r\n";
977 
978  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
979  uint8_t httpbuf2[] = "filecontent\r\n"
980  "-----------------------------277531038314945--";
981  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
982  ThreadVars th_v;
983  TcpSession ssn;
984 
987 
988  memset(&th_v, 0, sizeof(th_v));
989  memset(&ssn, 0, sizeof(ssn));
990 
991  DetectEngineThreadCtx *det_ctx = NULL;
994  de_ctx->flags |= DE_QUIET;
995 
996  Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any (content:\"GET\"; http_method; content:\"upload.cgi\"; http_uri; filestore; sid:1; rev:1;)");
997  FAIL_IF_NULL(s);
998 
1000  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1001 
1002  Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
1003  FAIL_IF_NULL(f);
1004  f->protoctx = &ssn;
1005  f->proto = IPPROTO_TCP;
1006  f->alproto = ALPROTO_HTTP1;
1007 
1008  Packet *p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1009  FAIL_IF_NULL(p);
1010  p->flow = f;
1014 
1015  StreamTcpInitConfig(true);
1016 
1017  int r = AppLayerParserParse(
1018  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_START, httpbuf1, httplen1);
1019  FAIL_IF(r != 0);
1020  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1021  FAIL_IF(PacketAlertCheck(p, 1));
1022 
1023  r = AppLayerParserParse(
1024  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_EOF, httpbuf2, httplen2);
1025  FAIL_IF(r != 0);
1026  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1027  FAIL_IF(PacketAlertCheck(p, 1));
1028 
1029  HtpState *http_state = f->alstate;
1030  FAIL_IF_NULL(http_state);
1031  FAIL_IF_NULL(http_state->files_ts);
1032 
1034  FAIL_IF_NULL(files);
1035  File *file = files->head;
1036  FAIL_IF_NULL(file);
1037  FAIL_IF(file->flags & FILE_STORE);
1038 
1040  UTHFreeFlow(f);
1041  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1043  StreamTcpFreeConfig(true);
1044  PASS;
1045 }
1046 
1047 /**
1048  * \test multiple files in a tx
1049  */
1050 static int DeStateSigTest08(void)
1051 {
1052  uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
1053  "Host: www.server.lan\r\n"
1054  "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
1055  "Content-Length: 440\r\n"
1056  "\r\n"
1057  "-----------------------------277531038314945\r\n"
1058  "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"AAAApicture1.jpg\"\r\n"
1059  "Content-Type: image/jpeg\r\n"
1060  "\r\n";
1061 
1062  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1063  uint8_t httpbuf2[] = "file";
1064  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1065  uint8_t httpbuf3[] = "content\r\n"
1066  "-----------------------------277531038314945\r\n";
1067  uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
1068 
1069  uint8_t httpbuf4[] = "Content-Disposition: form-data; name=\"uploadfile_1\"; filename=\"BBBBpicture2.jpg\"\r\n"
1070  "Content-Type: image/jpeg\r\n"
1071  "\r\n"
1072  "filecontent2\r\n"
1073  "-----------------------------277531038314945--";
1074  uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
1075 
1076  ThreadVars th_v;
1077  TcpSession ssn;
1078 
1081 
1082  memset(&th_v, 0, sizeof(th_v));
1083  memset(&ssn, 0, sizeof(ssn));
1084 
1085  DetectEngineThreadCtx *det_ctx = NULL;
1088  de_ctx->flags |= DE_QUIET;
1089 
1090  Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any (content:\"POST\"; http_method; content:\"upload.cgi\"; http_uri; filename:\"BBBBpicture\"; filestore; sid:1; rev:1;)");
1091  FAIL_IF_NULL(s);
1092 
1094  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1095 
1096  Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
1097  FAIL_IF_NULL(f);
1098  f->protoctx = &ssn;
1099  f->proto = IPPROTO_TCP;
1100  f->alproto = ALPROTO_HTTP1;
1101 
1102  Packet *p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1103  FAIL_IF_NULL(p);
1104  p->flow = f;
1108 
1109  StreamTcpInitConfig(true);
1110 
1111  /* HTTP request with 1st part of the multipart body */
1112 
1113  int r = AppLayerParserParse(
1114  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_START, httpbuf1, httplen1);
1115  FAIL_IF(r != 0);
1116  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1117  FAIL_IF(PacketAlertCheck(p, 1));
1118 
1119  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
1120  FAIL_IF(r != 0);
1121  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1122  FAIL_IF(PacketAlertCheck(p, 1));
1123 
1124  HtpState *http_state = f->alstate;
1125  FAIL_IF_NULL(http_state);
1126  FAIL_IF_NULL(http_state->files_ts);
1127 
1129  FAIL_IF_NULL(files);
1130  File *file = files->head;
1131  FAIL_IF_NULL(file);
1132  FAIL_IF(file->flags & FILE_STORE);
1133 
1134  /* 2nd multipart body file */
1135 
1136  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf3, httplen3);
1137  FAIL_IF(r != 0);
1138  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1139  FAIL_IF(PacketAlertCheck(p, 1));
1140 
1141  r = AppLayerParserParse(
1142  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_EOF, httpbuf4, httplen4);
1143  FAIL_IF(r != 0);
1144  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1146 
1147  http_state = f->alstate;
1148  FAIL_IF_NULL(http_state);
1149  FAIL_IF_NULL(http_state->files_ts);
1150 
1152  FAIL_IF_NULL(files);
1153  file = files->head;
1154  FAIL_IF_NULL(file);
1155  file = file->next;
1156  FAIL_IF_NULL(file);
1157  FAIL_IF_NOT(file->flags & FILE_STORE);
1158 
1160  UTHFreeFlow(f);
1161  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1163  StreamTcpFreeConfig(true);
1164  PASS;
1165 }
1166 
1167 /**
1168  * \test multiple files in a tx. Both files should match
1169  */
1170 static int DeStateSigTest09(void)
1171 {
1172  uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
1173  "Host: www.server.lan\r\n"
1174  "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
1175  "Content-Length: 440\r\n"
1176  "\r\n"
1177  "-----------------------------277531038314945\r\n"
1178  "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n"
1179  "Content-Type: image/jpeg\r\n"
1180  "\r\n";
1181 
1182  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1183  uint8_t httpbuf2[] = "file";
1184  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1185  uint8_t httpbuf3[] = "content\r\n"
1186  "-----------------------------277531038314945\r\n";
1187  uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
1188 
1189  uint8_t httpbuf4[] = "Content-Disposition: form-data; name=\"uploadfile_1\"; filename=\"somepicture2.jpg\"\r\n"
1190  "Content-Type: image/jpeg\r\n"
1191  "\r\n"
1192  "filecontent2\r\n"
1193  "-----------------------------277531038314945--";
1194  uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
1195 
1196  ThreadVars th_v;
1197  TcpSession ssn;
1198 
1201 
1202  memset(&th_v, 0, sizeof(th_v));
1203  memset(&ssn, 0, sizeof(ssn));
1204 
1205  DetectEngineThreadCtx *det_ctx = NULL;
1208  de_ctx->flags |= DE_QUIET;
1209 
1210  Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any (content:\"POST\"; http_method; content:\"upload.cgi\"; http_uri; filename:\"somepicture\"; filestore; sid:1; rev:1;)");
1211  FAIL_IF_NULL(s);
1212 
1214  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1215 
1216  Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
1217  FAIL_IF_NULL(f);
1218  f->protoctx = &ssn;
1219  f->proto = IPPROTO_TCP;
1220  f->alproto = ALPROTO_HTTP1;
1221 
1222  Packet *p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1223  FAIL_IF_NULL(p);
1224  p->flow = f;
1228 
1229  StreamTcpInitConfig(true);
1230 
1231  /* HTTP request with 1st part of the multipart body */
1232 
1233  int r = AppLayerParserParse(
1234  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_START, httpbuf1, httplen1);
1235  FAIL_IF(r != 0);
1236  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1238 
1239  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
1240  FAIL_IF(r != 0);
1241  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1242  FAIL_IF(PacketAlertCheck(p, 1));
1243 
1244  HtpState *http_state = f->alstate;
1245  FAIL_IF_NULL(http_state);
1246  FAIL_IF_NULL(http_state->files_ts);
1247 
1249  FAIL_IF_NULL(files);
1250  File *file = files->head;
1251  FAIL_IF_NULL(file);
1252  FAIL_IF_NOT(file->flags & FILE_STORE);
1253 
1254  /* 2nd multipart body file */
1255 
1256  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf3, httplen3);
1257  FAIL_IF(r != 0);
1258  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1259  FAIL_IF(PacketAlertCheck(p, 1));
1260 
1261  r = AppLayerParserParse(
1262  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_EOF, httpbuf4, httplen4);
1263  FAIL_IF(r != 0);
1264  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1266 
1267  http_state = f->alstate;
1268  FAIL_IF_NULL(http_state);
1269  FAIL_IF_NULL(http_state->files_ts);
1270 
1272  FAIL_IF_NULL(files);
1273  file = files->head;
1274  FAIL_IF_NULL(file);
1275  FAIL_IF_NOT(file->flags & FILE_STORE);
1276 
1278  UTHFreeFlow(f);
1279  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1281  StreamTcpFreeConfig(true);
1282  PASS;
1283 }
1284 
1285 /**
1286  * \test multiple files in a tx. Both files should match. No other matches.
1287  */
1288 static int DeStateSigTest10(void)
1289 {
1290  uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
1291  "Host: www.server.lan\r\n"
1292  "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
1293  "Content-Length: 440\r\n"
1294  "\r\n"
1295  "-----------------------------277531038314945\r\n"
1296  "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n"
1297  "Content-Type: image/jpeg\r\n"
1298  "\r\n";
1299 
1300  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1301  uint8_t httpbuf2[] = "file";
1302  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1303  uint8_t httpbuf3[] = "content\r\n"
1304  "-----------------------------277531038314945\r\n";
1305  uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
1306 
1307  uint8_t httpbuf4[] = "Content-Disposition: form-data; name=\"uploadfile_1\"; filename=\"somepicture2.jpg\"\r\n"
1308  "Content-Type: image/jpeg\r\n"
1309  "\r\n"
1310  "filecontent2\r\n"
1311  "-----------------------------277531038314945--";
1312  uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
1313 
1314  ThreadVars th_v;
1315  TcpSession ssn;
1316 
1319 
1320  memset(&th_v, 0, sizeof(th_v));
1321  memset(&ssn, 0, sizeof(ssn));
1322 
1323  DetectEngineThreadCtx *det_ctx = NULL;
1326  de_ctx->flags |= DE_QUIET;
1327 
1328  Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any (filename:\"somepicture\"; filestore; sid:1; rev:1;)");
1329  FAIL_IF_NULL(s);
1330 
1332  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1333 
1334  Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
1335  FAIL_IF_NULL(f);
1336  f->protoctx = &ssn;
1337  f->proto = IPPROTO_TCP;
1338  f->alproto = ALPROTO_HTTP1;
1339 
1340  Packet *p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1341  FAIL_IF_NULL(p);
1342  p->flow = f;
1346 
1347  StreamTcpInitConfig(true);
1348 
1349  /* HTTP request with 1st part of the multipart body */
1350 
1351  int r = AppLayerParserParse(
1352  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_START, httpbuf1, httplen1);
1353  FAIL_IF(r != 0);
1354  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1356 
1357  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
1358  FAIL_IF(r != 0);
1359  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1360  FAIL_IF(PacketAlertCheck(p, 1));
1361 
1362  HtpState *http_state = f->alstate;
1363  FAIL_IF_NULL(http_state);
1364  FAIL_IF_NULL(http_state->files_ts);
1365 
1367  FAIL_IF_NULL(files);
1368  File *file = files->head;
1369  FAIL_IF_NULL(file);
1370  FAIL_IF_NOT(file->flags & FILE_STORE);
1371 
1372  /* 2nd multipart body file */
1373 
1374  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf3, httplen3);
1375  FAIL_IF(r != 0);
1376  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1377  FAIL_IF(PacketAlertCheck(p, 1));
1378 
1379  r = AppLayerParserParse(
1380  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_EOF, httpbuf4, httplen4);
1381  FAIL_IF(r != 0);
1382  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1384 
1385  http_state = f->alstate;
1386  FAIL_IF_NULL(http_state);
1387  FAIL_IF_NULL(http_state->files_ts);
1388 
1390  FAIL_IF_NULL(files);
1391  file = files->head;
1392  FAIL_IF_NULL(file);
1393  FAIL_IF_NOT(file->flags & FILE_STORE);
1394 
1396  UTHFreeFlow(f);
1397  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1399  StreamTcpFreeConfig(true);
1400  PASS;
1401 }
1402 
1403 #endif
1404 
1406 {
1407 #ifdef UNITTESTS
1408  UtRegisterTest("DeStateTest01", DeStateTest01);
1409  UtRegisterTest("DeStateTest02", DeStateTest02);
1410  UtRegisterTest("DeStateTest03", DeStateTest03);
1411  UtRegisterTest("DeStateSigTest01", DeStateSigTest01);
1412  UtRegisterTest("DeStateSigTest02", DeStateSigTest02);
1413  UtRegisterTest("DeStateSigTest03", DeStateSigTest03);
1414  UtRegisterTest("DeStateSigTest04", DeStateSigTest04);
1415  UtRegisterTest("DeStateSigTest05", DeStateSigTest05);
1416  UtRegisterTest("DeStateSigTest06", DeStateSigTest06);
1417  UtRegisterTest("DeStateSigTest07", DeStateSigTest07);
1418  UtRegisterTest("DeStateSigTest08", DeStateSigTest08);
1419  UtRegisterTest("DeStateSigTest09", DeStateSigTest09);
1420  UtRegisterTest("DeStateSigTest10", DeStateSigTest10);
1421 #endif
1422 
1423  return;
1424 }
1425 
1426 /**
1427  * @}
1428  */
FileContainer_
Definition: util-file.h:107
DE_STATE_CHUNK_SIZE
#define DE_STATE_CHUNK_SIZE
Definition: detect-engine-state.h:53
detect-engine.h
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
DetectEngineStateDirection_::flags
uint8_t flags
Definition: detect-engine-state.h:89
PKT_HAS_FLOW
#define PKT_HAS_FLOW
Definition: decode.h:1152
flow-util.h
DetectEngineState_
Definition: detect-engine-state.h:93
Signature_::num
SigIntId num
Definition: detect.h:528
stream-tcp.h
SigGroupHead_
Container for matching data for a signature group.
Definition: detect.h:1346
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:298
AppLayerParserSetTransactionInspectId
void AppLayerParserSetTransactionInspectId(const Flow *f, AppLayerParserState *pstate, void *alstate, const uint8_t flags, bool tag_txs_as_inspected)
Definition: app-layer-parser.c:730
DetectEngineStateDirection_::cnt
SigIntId cnt
Definition: detect-engine-state.h:87
Flow_::proto
uint8_t proto
Definition: flow.h:375
PacketAlertCheck
int PacketAlertCheck(Packet *p, uint32_t sid)
Check if a certain sid alerted, this is used in the test functions.
Definition: detect-engine-alert.c:138
Packet_::flags
uint32_t flags
Definition: decode.h:449
Flow_
Flow data structure.
Definition: flow.h:353
SigInit
Signature * SigInit(DetectEngineCtx *, const char *)
Parses a signature and adds it to the Detection Engine Context.
Definition: detect-parse.c:2076
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:758
FILE_STORE
#define FILE_STORE
Definition: util-file.h:55
FileDisableStoringForTransaction
void FileDisableStoringForTransaction(Flow *f, uint8_t direction, uint64_t tx_id)
disable file storing for files in a transaction
Definition: util-file.c:1146
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2068
DetectEngineState_::dir_state
DetectEngineStateDirection dir_state[2]
Definition: detect-engine-state.h:94
AppLayerParserThreadCtxFree
void AppLayerParserThreadCtxFree(AppLayerParserThreadCtx *tctx)
Destroys the app layer parser thread context obtained using AppLayerParserThreadCtxAlloc().
Definition: app-layer-parser.c:277
FLOW_PKT_TOSERVER
#define FLOW_PKT_TOSERVER
Definition: flow.h:225
MIN
#define MIN(x, y)
Definition: suricata-common.h:368
AppLayerParserGetFiles
FileContainer * AppLayerParserGetFiles(const Flow *f, const uint8_t direction)
Definition: app-layer-parser.c:861
DE_QUIET
#define DE_QUIET
Definition: detect.h:294
stream-tcp-reassemble.h
UTHBuildPacket
Packet * UTHBuildPacket(uint8_t *payload, uint16_t payload_len, uint8_t ipproto)
UTHBuildPacket is a wrapper that build packets with default ip and port fields.
Definition: util-unittest-helper.c:337
SigMatchSignatures
void SigMatchSignatures(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:1653
Packet_::flowflags
uint8_t flowflags
Definition: decode.h:445
Flow_::protoctx
void * protoctx
Definition: flow.h:451
DeStateStoreItem_::sid
SigIntId sid
Definition: detect-engine-state.h:75
FLOW_IPV4
#define FLOW_IPV4
Definition: flow.h:98
AppLayerParserGetTransactionInspectId
uint64_t AppLayerParserGetTransactionInspectId(AppLayerParserState *pstate, uint8_t direction)
Definition: app-layer-parser.c:699
util-unittest.h
DetectEngineStateDirection_::cur
DeStateStore * cur
Definition: detect-engine-state.h:85
HtpState_
Definition: app-layer-htp.h:248
FlowGetAppState
void * FlowGetAppState(const Flow *f)
Definition: flow.c:1109
util-unittest-helper.h
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression to true.
Definition: util-unittest.h:82
STREAM_START
#define STREAM_START
Definition: stream.h:29
detect-flowvar.h
DetectRunStoreStateTx
void DetectRunStoreStateTx(const SigGroupHead *sgh, Flow *f, void *tx, uint64_t tx_id, const Signature *s, uint32_t inspect_flags, uint8_t flow_flags, const uint16_t file_no_match)
Definition: detect-engine-state.c:218
Flow_::alparser
AppLayerParserState * alparser
Definition: flow.h:485
StreamTcpInitConfig
void StreamTcpInitConfig(bool)
To initialize the stream global configuration data.
Definition: stream-tcp.c:365
UTHBuildFlow
Flow * UTHBuildFlow(int family, const char *src, const char *dst, Port sp, Port dp)
Definition: util-unittest-helper.c:521
FLOW_INITIALIZE
#define FLOW_INITIALIZE(f)
Definition: flow-util.h:39
app-layer-htp.h
decode.h
FAIL_IF_NOT_NULL
#define FAIL_IF_NOT_NULL(expr)
Fail a test if expression evaluates to non-NULL.
Definition: util-unittest.h:96
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:17
DetectEngineThreadCtx_
Definition: detect.h:1003
DeStateStoreItem_::flags
uint32_t flags
Definition: detect-engine-state.h:74
DeStateUpdateInspectTransactionId
void DeStateUpdateInspectTransactionId(Flow *f, const uint8_t flags, const bool tag_txs_as_inspected)
update flow's inspection id's
Definition: detect-engine-state.c:250
BIT_U32
#define BIT_U32(n)
Definition: suricata-common.h:377
STREAM_TOSERVER
#define STREAM_TOSERVER
Definition: stream.h:31
alp_tctx
AppLayerParserThreadCtx * alp_tctx
Definition: fuzz_applayerparserparse.c:20
SCEnter
#define SCEnter(...)
Definition: util-debug.h:300
FileContainer_::head
File * head
Definition: util-file.h:108
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
DeStateStore_::next
struct DeStateStore_ * next
Definition: detect-engine-state.h:80
HtpState_::conn
htp_conn_t * conn
Definition: app-layer-htp.h:252
app-layer-parser.h
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:277
util-profiling.h
DetectEngineStateAlloc
DetectEngineState * DetectEngineStateAlloc(void)
Alloc a DetectEngineState object.
Definition: detect-engine-state.c:163
SCReturn
#define SCReturn
Definition: util-debug.h:302
Packet_
Definition: decode.h:414
DE_STATE_FLAG_BASE
#define DE_STATE_FLAG_BASE
Definition: detect-engine-state.h:64
app-layer-dcerpc-common.h
stream-tcp-private.h
detect-engine-state.h
Data structures and function prototypes for keeping state for the detection engine.
AppLayerParserGetTx
void * AppLayerParserGetTx(uint8_t ipproto, AppProto alproto, void *alstate, uint64_t tx_id)
Definition: app-layer-parser.c:1090
DetectEngineStateFree
void DetectEngineStateFree(DetectEngineState *state)
Frees a DetectEngineState object.
Definition: detect-engine-state.c:173
SigGroupBuild
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
Definition: detect-engine-build.c:1932
UTHFreeFlow
void UTHFreeFlow(Flow *flow)
Definition: util-unittest-helper.c:526
AppLayerParserThreadCtxAlloc
AppLayerParserThreadCtx * AppLayerParserThreadCtxAlloc(void)
Gets a new app layer protocol's parser thread context.
Definition: app-layer-parser.c:251
File_::flags
uint16_t flags
Definition: util-file.h:73
DetectEngineStateDirection_::head
DeStateStore * head
Definition: detect-engine-state.h:84
File_
Definition: util-file.h:72
DetectEngineAppendSig
Signature * DetectEngineAppendSig(DetectEngineCtx *de_ctx, const char *sigstr)
Parse and append a Signature into the Detection Engine Context signature list.
Definition: detect-parse.c:2381
Packet_::flow
struct Flow_ * flow
Definition: decode.h:451
DetectEngineStateResetTxs
void DetectEngineStateResetTxs(Flow *f)
Reset de state for active tx' To be used on detect engine reload.
Definition: detect-engine-state.c:282
DetectEngineThreadCtxInit
TmEcode DetectEngineThreadCtxInit(ThreadVars *, void *, void **)
initialize thread specific detection engine context
Definition: detect-engine.c:2772
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:71
StreamTcpFreeConfig
void StreamTcpFreeConfig(bool quiet)
Definition: stream-tcp.c:670
flags
uint8_t flags
Definition: decode-gre.h:0
AppLayerParserParse
int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto, uint8_t flags, const uint8_t *input, uint32_t input_len)
Definition: app-layer-parser.c:1211
suricata-common.h
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *, void *)
Definition: detect-engine.c:2980
DeStateStore_
Definition: detect-engine-state.h:78
ALPROTO_HTTP1
@ ALPROTO_HTTP1
Definition: app-layer-protos.h:30
File_::next
struct File_ * next
Definition: util-file.h:86
STREAM_TOCLIENT
#define STREAM_TOCLIENT
Definition: stream.h:32
DetectEngineStateDirection_
Definition: detect-engine-state.h:83
DetectEngineCtx_::sig_list
Signature * sig_list
Definition: detect.h:764
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
DetectEngineStateDirection_::filestore_cnt
uint16_t filestore_cnt
Definition: detect-engine-state.h:88
SCFree
#define SCFree(p)
Definition: util-mem.h:61
UTHFreePacket
void UTHFreePacket(Packet *p)
UTHFreePacket: function to release the allocated data from UTHBuildPacket and the packet itself.
Definition: util-unittest-helper.c:485
Flow_::alstate
void * alstate
Definition: flow.h:486
DeStateStore_::store
DeStateStoreItem store[DE_STATE_CHUNK_SIZE]
Definition: detect-engine-state.h:79
Flow_::flags
uint32_t flags
Definition: flow.h:431
detect-parse.h
Signature_
Signature container.
Definition: detect.h:517
AppLayerParserGetTxDetectState
DetectEngineState * AppLayerParserGetTxDetectState(uint8_t ipproto, AppProto alproto, void *tx)
Definition: app-layer-parser.c:1162
FLOW_PKT_ESTABLISHED
#define FLOW_PKT_ESTABLISHED
Definition: flow.h:227
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2023
STREAM_EOF
#define STREAM_EOF
Definition: stream.h:30
AppLayerParserSetTxDetectState
int AppLayerParserSetTxDetectState(const Flow *f, void *tx, DetectEngineState *s)
Definition: app-layer-parser.c:1169
app-layer-protos.h
HtpState_::files_ts
FileContainer * files_ts
Definition: app-layer-htp.h:256
FILE_NOSTORE
#define FILE_NOSTORE
Definition: util-file.h:54
DetectEngineCtx_::flags
uint8_t flags
Definition: detect.h:759
AppLayerParserThreadCtx_
Definition: app-layer-parser.c:85
TcpSession_
Definition: stream-tcp-private.h:260
SigIntId
#define SigIntId
Definition: suricata-common.h:292
DeStateStoreItem_
Definition: detect-engine-state.h:73
Flow_::alproto
AppProto alproto
application level protocol
Definition: flow.h:460
DeStateRegisterTests
void DeStateRegisterTests(void)
Definition: detect-engine-state.c:1405
detect-engine-dcepayload.h
SigGroupHead_::filestore_cnt
uint16_t filestore_cnt
Definition: detect.h:1359
AppLayerParserGetTxCnt
uint64_t AppLayerParserGetTxCnt(const Flow *f, void *alstate)
Definition: app-layer-parser.c:1083
DetectEngineStateDirection_::tail
DeStateStore * tail
Definition: detect-engine-state.h:86
FLOW_DESTROY
#define FLOW_DESTROY(f)
Definition: flow-util.h:130
PKT_STREAM_EST
#define PKT_STREAM_EST
Definition: decode.h:1149
app-layer.h