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