suricata
detect-engine-state.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2013 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_HTTP) {
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  int jump = 0;
127  int i = 0;
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->head;
134 
135  if (store == NULL) {
136  store = DeStateStoreAlloc();
137  if (store != NULL) {
138  dir_state->head = store;
139  dir_state->tail = store;
140  }
141  } else {
142  jump = dir_state->cnt / DE_STATE_CHUNK_SIZE;
143  for (i = 0; i < jump; i++) {
144  store = store->next;
145  }
146  if (store == NULL) {
147  store = DeStateStoreAlloc();
148  if (store != NULL) {
149  dir_state->tail->next = store;
150  dir_state->tail = store;
151  }
152  }
153  }
154 
155  if (store == NULL)
156  return;
157 
158  SigIntId idx = dir_state->cnt++ % DE_STATE_CHUNK_SIZE;
159  store->store[idx].sid = s->num;
160  store->store[idx].flags = inspect_flags;
161 
162  return;
163 }
164 
166 {
168  if (unlikely(d == NULL))
169  return NULL;
170  memset(d, 0, sizeof(DetectEngineState));
171 
172  return d;
173 }
174 
176 {
177  DeStateStore *store;
178  DeStateStore *store_next;
179  int i = 0;
180 
181  for (i = 0; i < 2; i++) {
182  store = state->dir_state[i].head;
183  while (store != NULL) {
184  store_next = store->next;
185  SCFree(store);
186  store = store_next;
187  }
188  }
189  SCFree(state);
190 
191  return;
192 }
193 
194 static void StoreFileNoMatchCnt(DetectEngineState *de_state, uint16_t file_no_match, uint8_t direction)
195 {
196  de_state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].filestore_cnt += file_no_match;
197 
198  return;
199 }
200 
201 static bool StoreFilestoreSigsCantMatch(const SigGroupHead *sgh, const DetectEngineState *de_state, uint8_t direction)
202 {
203  if (de_state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].filestore_cnt == sgh->filestore_cnt)
204  return true;
205  else
206  return false;
207 }
208 
209 static void StoreStateTxHandleFiles(const SigGroupHead *sgh, Flow *f,
210  DetectEngineState *destate, const uint8_t flow_flags,
211  const uint64_t tx_id, const uint16_t file_no_match)
212 {
213  SCLogDebug("tx %"PRIu64", file_no_match %u", tx_id, file_no_match);
214  StoreFileNoMatchCnt(destate, file_no_match, flow_flags);
215  if (StoreFilestoreSigsCantMatch(sgh, destate, flow_flags)) {
217  }
218 }
219 
221  const SigGroupHead *sgh,
222  Flow *f, void *tx, uint64_t tx_id,
223  const Signature *s,
224  uint32_t inspect_flags, uint8_t flow_flags,
225  const uint16_t file_no_match)
226 {
228  if (destate == NULL) {
229  destate = DetectEngineStateAlloc();
230  if (destate == NULL)
231  return;
232  if (AppLayerParserSetTxDetectState(f, tx, destate) < 0) {
233  DetectEngineStateFree(destate);
234  return;
235  }
236  SCLogDebug("destate created for %"PRIu64, tx_id);
237  }
238  DeStateSignatureAppend(destate, s, inspect_flags, flow_flags);
239  StoreStateTxHandleFiles(sgh, f, destate, flow_flags, tx_id, file_no_match);
240 
241  SCLogDebug("Stored for TX %"PRIu64, tx_id);
242 }
243 
244 /** \brief update flow's inspection id's
245  *
246  * \param f unlocked flow
247  * \param flags direction and disruption flags
248  * \param tag_txs_as_inspected if true all 'complete' txs will be marked
249  * 'inspected'
250  *
251  * \note it is possible that f->alstate, f->alparser are NULL */
253  const bool tag_txs_as_inspected)
254 {
255  if (f->alparser && f->alstate) {
257  f->alstate, flags,
258  tag_txs_as_inspected);
259  }
260  return;
261 }
262 
263 /** \brief Reset de state for active tx'
264  * To be used on detect engine reload.
265  * \param f write LOCKED flow
266  */
268 {
269  void *alstate = FlowGetAppState(f);
270  if (!StateIsValid(f->alproto, alstate)) {
271  return;
272  }
273 
276 
277  uint64_t inspect_tx_id = MIN(inspect_ts, inspect_tc);
278 
279  uint64_t total_txs = AppLayerParserGetTxCnt(f, alstate);
280 
281  for ( ; inspect_tx_id < total_txs; inspect_tx_id++) {
282  void *inspect_tx = AppLayerParserGetTx(f->proto, f->alproto, alstate, inspect_tx_id);
283  if (inspect_tx != NULL) {
284  DetectEngineState *tx_de_state = AppLayerParserGetTxDetectState(f->proto, f->alproto, inspect_tx);
285  if (tx_de_state == NULL) {
286  continue;
287  }
288 
289  tx_de_state->dir_state[0].cnt = 0;
290  tx_de_state->dir_state[0].filestore_cnt = 0;
291  tx_de_state->dir_state[0].flags = 0;
292 
293  tx_de_state->dir_state[1].cnt = 0;
294  tx_de_state->dir_state[1].filestore_cnt = 0;
295  tx_de_state->dir_state[1].flags = 0;
296  }
297  }
298 }
299 
300 /*********Unittests*********/
301 
302 #ifdef UNITTESTS
303 
304 static int DeStateTest01(void)
305 {
306  SCLogDebug("sizeof(DetectEngineState)\t\t%"PRIuMAX,
307  (uintmax_t)sizeof(DetectEngineState));
308  SCLogDebug("sizeof(DeStateStore)\t\t\t%"PRIuMAX,
309  (uintmax_t)sizeof(DeStateStore));
310  SCLogDebug("sizeof(DeStateStoreItem)\t\t%"PRIuMAX"",
311  (uintmax_t)sizeof(DeStateStoreItem));
312 
313  return 1;
314 }
315 
316 static int DeStateTest02(void)
317 {
319  FAIL_IF_NULL(state);
320 
321  Signature s;
322  memset(&s, 0x00, sizeof(s));
323 
324  uint8_t direction = STREAM_TOSERVER;
325 
326  s.num = 0;
327  DeStateSignatureAppend(state, &s, 0, direction);
328  s.num = 11;
329  DeStateSignatureAppend(state, &s, 0, direction);
330  s.num = 22;
331  DeStateSignatureAppend(state, &s, 0, direction);
332  s.num = 33;
333  DeStateSignatureAppend(state, &s, 0, direction);
334  s.num = 44;
335  DeStateSignatureAppend(state, &s, 0, direction);
336  s.num = 55;
337  DeStateSignatureAppend(state, &s, 0, direction);
338  s.num = 66;
339  DeStateSignatureAppend(state, &s, 0, direction);
340  s.num = 77;
341  DeStateSignatureAppend(state, &s, 0, direction);
342  s.num = 88;
343  DeStateSignatureAppend(state, &s, 0, direction);
344  s.num = 99;
345  DeStateSignatureAppend(state, &s, 0, direction);
346  s.num = 100;
347  DeStateSignatureAppend(state, &s, 0, direction);
348  s.num = 111;
349  DeStateSignatureAppend(state, &s, 0, direction);
350  s.num = 122;
351  DeStateSignatureAppend(state, &s, 0, direction);
352  s.num = 133;
353  DeStateSignatureAppend(state, &s, 0, direction);
354  s.num = 144;
355  DeStateSignatureAppend(state, &s, 0, direction);
356  s.num = 155;
357  DeStateSignatureAppend(state, &s, 0, direction);
358  s.num = 166;
359  DeStateSignatureAppend(state, &s, 0, direction);
360 
361  FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head == NULL);
362  FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[1].sid != 11);
363  FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->next == NULL);
364  FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[14].sid != 144);
365  FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->next->store[0].sid != 155);
366  FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->next->store[1].sid != 166);
367 
368  DetectEngineStateFree(state);
369 
370  PASS;
371 }
372 
373 static int DeStateTest03(void)
374 {
376  FAIL_IF_NULL(state);
377 
378  Signature s;
379  memset(&s, 0x00, sizeof(s));
380 
381  uint8_t direction = STREAM_TOSERVER;
382 
383  s.num = 11;
384  DeStateSignatureAppend(state, &s, 0, direction);
385  s.num = 22;
386  DeStateSignatureAppend(state, &s, BIT_U32(DE_STATE_FLAG_BASE), direction);
387 
388  FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head == NULL);
389  FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[0].sid != 11);
390  FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[0].flags & BIT_U32(DE_STATE_FLAG_BASE));
391  FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[1].sid != 22);
392  FAIL_IF(!(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[1].flags & BIT_U32(DE_STATE_FLAG_BASE)));
393 
394  DetectEngineStateFree(state);
395  PASS;
396 }
397 
398 static int DeStateSigTest01(void)
399 {
400  DetectEngineThreadCtx *det_ctx = NULL;
401  ThreadVars th_v;
402  Flow f;
403  TcpSession ssn;
404  Packet *p = NULL;
405  uint8_t httpbuf1[] = "POST / HTTP/1.0\r\n";
406  uint8_t httpbuf2[] = "User-Agent: Mozilla/1.0\r\n";
407  uint8_t httpbuf3[] = "Cookie: dummy\r\nContent-Length: 10\r\n\r\n";
408  uint8_t httpbuf4[] = "Http Body!";
409  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
410  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
411  uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
412  uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
413 
416 
417  memset(&th_v, 0, sizeof(th_v));
418  memset(&f, 0, sizeof(f));
419  memset(&ssn, 0, sizeof(ssn));
420 
421  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
422  FAIL_IF_NULL(p);
423 
424  FLOW_INITIALIZE(&f);
425  f.protoctx = (void *)&ssn;
426  f.proto = IPPROTO_TCP;
427  f.flags |= FLOW_IPV4;
428  f.alproto = ALPROTO_HTTP;
429 
430  p->flow = &f;
434 
436 
439  de_ctx->flags |= DE_QUIET;
440 
441  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;)");
442  FAIL_IF_NULL(s);
443 
445  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
446  FAIL_IF_NULL(det_ctx);
447 
448  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
449  STREAM_TOSERVER, httpbuf1, httplen1);
450  FAIL_IF_NOT(r == 0);
451  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
452  FAIL_IF(PacketAlertCheck(p, 1));
453 
455  STREAM_TOSERVER, httpbuf2, httplen2);
456  FAIL_IF_NOT(r == 0);
457  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
458  FAIL_IF(PacketAlertCheck(p, 1));
459 
461  STREAM_TOSERVER, httpbuf3, httplen3);
462  FAIL_IF_NOT(r == 0);
463  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
465 
467  STREAM_TOSERVER, httpbuf4, httplen4);
468  FAIL_IF_NOT(r == 0);
469  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
470  FAIL_IF(PacketAlertCheck(p, 1));
471 
473  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
476  FLOW_DESTROY(&f);
477  UTHFreePacket(p);
478  PASS;
479 }
480 
481 /** \test multiple pipelined http transactions */
482 static int DeStateSigTest02(void)
483 {
484  DetectEngineThreadCtx *det_ctx = NULL;
485  ThreadVars th_v;
486  Flow f;
487  TcpSession ssn;
488  Packet *p = NULL;
489  uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n";
490  uint8_t httpbuf2[] = "User-Agent: Mozilla/1.0\r\nContent-Length: 10\r\n";
491  uint8_t httpbuf3[] = "Cookie: dummy\r\n\r\n";
492  uint8_t httpbuf4[] = "Http Body!";
493  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
494  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
495  uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
496  uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
497  uint8_t httpbuf5[] = "GET /?var=val HTTP/1.1\r\n";
498  uint8_t httpbuf6[] = "User-Agent: Firefox/1.0\r\n";
499  uint8_t httpbuf7[] = "Cookie: dummy2\r\nContent-Length: 10\r\n\r\nHttp Body!";
500  uint32_t httplen5 = sizeof(httpbuf5) - 1; /* minus the \0 */
501  uint32_t httplen6 = sizeof(httpbuf6) - 1; /* minus the \0 */
502  uint32_t httplen7 = sizeof(httpbuf7) - 1; /* minus the \0 */
505 
506  memset(&th_v, 0, sizeof(th_v));
507  memset(&f, 0, sizeof(f));
508  memset(&ssn, 0, sizeof(ssn));
509 
510  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
511 
512  FLOW_INITIALIZE(&f);
513  f.protoctx = (void *)&ssn;
514  f.proto = IPPROTO_TCP;
515  f.flags |= FLOW_IPV4;
516 
517  p->flow = &f;
521  f.alproto = ALPROTO_HTTP;
522 
524 
527 
528  de_ctx->flags |= DE_QUIET;
529 
530  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;)");
531  FAIL_IF_NULL(s);
532  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;)");
533  FAIL_IF_NULL(s);
534 
536  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
537  FAIL_IF_NULL(det_ctx);
538 
539  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
540  STREAM_TOSERVER, httpbuf1, httplen1);
541  FAIL_IF(r != 0);
542  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
543  FAIL_IF(PacketAlertCheck(p, 1));
544 
546  STREAM_TOSERVER, httpbuf2, httplen2);
547  FAIL_IF(r != 0);
548  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
549  FAIL_IF(PacketAlertCheck(p, 1));
550 
552  STREAM_TOSERVER, httpbuf3, httplen3);
553  FAIL_IF(r != 0);
554  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
555  FAIL_IF(PacketAlertCheck(p, 1));
556 
557  void *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP, f.alstate, 0);
558  FAIL_IF_NULL(tx);
559 
560  DetectEngineState *tx_de_state = AppLayerParserGetTxDetectState(IPPROTO_TCP, ALPROTO_HTTP, tx);
561  FAIL_IF_NULL(tx_de_state);
562  FAIL_IF(tx_de_state->dir_state[0].cnt != 1);
563  /* http_header(mpm): 5, uri: 3, method: 6, cookie: 7 */
564  uint32_t expected_flags = (BIT_U32(5) | BIT_U32(3) | BIT_U32(6) |BIT_U32(7));
565  FAIL_IF(tx_de_state->dir_state[0].head->store[0].flags != expected_flags);
566 
568  STREAM_TOSERVER, httpbuf4, httplen4);
569  FAIL_IF(r != 0);
570  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
571  FAIL_IF(!(PacketAlertCheck(p, 1)));
572 
574  STREAM_TOSERVER, httpbuf5, httplen5);
575  FAIL_IF(r != 0);
576  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
577  FAIL_IF(PacketAlertCheck(p, 1));
578 
580  STREAM_TOSERVER, httpbuf6, httplen6);
581  FAIL_IF(r != 0);
582  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
583  FAIL_IF((PacketAlertCheck(p, 1)) || (PacketAlertCheck(p, 2)));
584 
586  STREAM_TOSERVER, httpbuf7, httplen7);
587  FAIL_IF(r != 0);
588  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
589  FAIL_IF(!(PacketAlertCheck(p, 2)));
590 
592  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
595  FLOW_DESTROY(&f);
596  UTHFreePacket(p);
597  PASS;
598 }
599 
600 static int DeStateSigTest03(void)
601 {
602  uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
603  "Host: www.server.lan\r\n"
604  "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
605  "Content-Length: 215\r\n"
606  "\r\n"
607  "-----------------------------277531038314945\r\n"
608  "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n"
609  "Content-Type: image/jpeg\r\n"
610  "\r\n"
611  "filecontent\r\n"
612  "-----------------------------277531038314945--";
613  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
614  ThreadVars th_v;
615  TcpSession ssn;
616  Flow *f = NULL;
617  Packet *p = NULL;
620 
621  memset(&th_v, 0, sizeof(th_v));
622  memset(&ssn, 0, sizeof(ssn));
623 
624  DetectEngineThreadCtx *det_ctx = NULL;
627 
628  de_ctx->flags |= DE_QUIET;
629 
630  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;)");
631  FAIL_IF_NULL(s);
632 
634  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
635 
636  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
637  FAIL_IF_NULL(f);
638  f->protoctx = &ssn;
639  f->proto = IPPROTO_TCP;
640  f->alproto = ALPROTO_HTTP;
641 
642  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
643  FAIL_IF_NULL(p);
644 
645  p->flow = f;
649 
651 
652  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
654  httpbuf1,
655  httplen1);
656  FAIL_IF(r != 0);
657 
658  HtpState *http_state = f->alstate;
659  FAIL_IF_NULL(http_state);
660  FAIL_IF_NULL(http_state->files_ts);
661 
662  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
663  FAIL_IF(!(PacketAlertCheck(p, 1)));
664 
666  FAIL_IF_NULL(files);
667 
668  File *file = files->head;
669  FAIL_IF_NULL(file);
670 
671  FAIL_IF(!(file->flags & FILE_STORE));
672 
674  UTHFreeFlow(f);
675 
676  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
679  PASS;
680 }
681 
682 static int DeStateSigTest04(void)
683 {
684  uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
685  "Host: www.server.lan\r\n"
686  "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
687  "Content-Length: 215\r\n"
688  "\r\n"
689  "-----------------------------277531038314945\r\n"
690  "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n"
691  "Content-Type: image/jpeg\r\n"
692  "\r\n"
693  "filecontent\r\n"
694  "-----------------------------277531038314945--";
695  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
696  ThreadVars th_v;
697  TcpSession ssn;
700 
701  memset(&th_v, 0, sizeof(th_v));
702  memset(&ssn, 0, sizeof(ssn));
703 
704  DetectEngineThreadCtx *det_ctx = NULL;
707  de_ctx->flags |= DE_QUIET;
708 
709  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;)");
710  FAIL_IF_NULL(s);
711 
713  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
714  FAIL_IF_NULL(det_ctx);
715 
716  Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
717  FAIL_IF_NULL(f);
718  f->protoctx = &ssn;
719  f->proto = IPPROTO_TCP;
720  f->alproto = ALPROTO_HTTP;
721 
722  Packet *p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
723  FAIL_IF_NULL(p);
724  p->flow = f;
728 
730 
731  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
733  httpbuf1, httplen1);
734  FAIL_IF(r != 0);
735  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
736  FAIL_IF(PacketAlertCheck(p, 1));
737 
738  HtpState *http_state = f->alstate;
739  FAIL_IF_NULL(http_state);
740  FAIL_IF_NULL(http_state->files_ts);
741 
743  FAIL_IF_NULL(files);
744  File *file = files->head;
745  FAIL_IF_NULL(file);
746 
747  FAIL_IF(file->flags & FILE_STORE);
748 
750  UTHFreeFlow(f);
751  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
754  PASS;
755 }
756 
757 static int DeStateSigTest05(void)
758 {
759  uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
760  "Host: www.server.lan\r\n"
761  "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
762  "Content-Length: 215\r\n"
763  "\r\n"
764  "-----------------------------277531038314945\r\n"
765  "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n"
766  "Content-Type: image/jpeg\r\n"
767  "\r\n"
768  "filecontent\r\n"
769  "-----------------------------277531038314945--";
770  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
771  ThreadVars th_v;
772  TcpSession ssn;
773 
776 
777  memset(&th_v, 0, sizeof(th_v));
778  memset(&ssn, 0, sizeof(ssn));
779 
780  DetectEngineThreadCtx *det_ctx = NULL;
783  de_ctx->flags |= DE_QUIET;
784 
785  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;)");
786  FAIL_IF_NULL(s);
787 
789  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
790 
791  Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
792  FAIL_IF_NULL(f);
793  f->protoctx = &ssn;
794  f->proto = IPPROTO_TCP;
795  f->alproto = ALPROTO_HTTP;
796 
797  Packet *p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
798  FAIL_IF_NULL(p);
799  p->flow = f;
803 
805 
806  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
808  httpbuf1,
809  httplen1);
810  FAIL_IF_NOT(r == 0);
811  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
812  FAIL_IF(PacketAlertCheck(p, 1));
813 
814  HtpState *http_state = f->alstate;
815  FAIL_IF_NULL(http_state);
816  FAIL_IF_NULL(http_state->files_ts);
817 
819  FAIL_IF_NULL(files);
820  File *file = files->head;
821  FAIL_IF_NULL(file);
822 
823  FAIL_IF(!(file->flags & FILE_NOSTORE));
824 
826  UTHFreeFlow(f);
827  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
830  PASS;
831 }
832 
833 static int DeStateSigTest06(void)
834 {
835  uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
836  "Host: www.server.lan\r\n"
837  "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
838  "Content-Length: 215\r\n"
839  "\r\n"
840  "-----------------------------277531038314945\r\n"
841  "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n"
842  "Content-Type: image/jpeg\r\n"
843  "\r\n"
844  "filecontent\r\n"
845  "-----------------------------277531038314945--";
846  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
847  ThreadVars th_v;
848  TcpSession ssn;
849 
852 
853  memset(&th_v, 0, sizeof(th_v));
854  memset(&ssn, 0, sizeof(ssn));
855 
856  DetectEngineThreadCtx *det_ctx = NULL;
859  de_ctx->flags |= DE_QUIET;
860 
861  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;)");
862  FAIL_IF_NULL(s);
863 
865  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
866  FAIL_IF_NULL(det_ctx);
867 
868  Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
869  FAIL_IF_NULL(f);
870  f->protoctx = &ssn;
871  f->proto = IPPROTO_TCP;
872  f->alproto = ALPROTO_HTTP;
873 
874  Packet *p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
875  FAIL_IF_NULL(p);
876  p->flow = f;
880 
882 
883  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
885  httpbuf1,
886  httplen1);
887  FAIL_IF(r != 0);
888  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
889  FAIL_IF(PacketAlertCheck(p, 1));
890 
891  HtpState *http_state = f->alstate;
892  FAIL_IF_NULL(http_state);
893  FAIL_IF_NULL(http_state->files_ts);
894 
896  FAIL_IF_NULL(files);
897  File *file = files->head;
898  FAIL_IF_NULL(file);
899  FAIL_IF(!(file->flags & FILE_NOSTORE));
900 
902  UTHFreeFlow(f);
903  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
906  PASS;
907 }
908 
909 static int DeStateSigTest07(void)
910 {
911  uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
912  "Host: www.server.lan\r\n"
913  "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
914  "Content-Length: 215\r\n"
915  "\r\n"
916  "-----------------------------277531038314945\r\n"
917  "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n"
918  "Content-Type: image/jpeg\r\n"
919  "\r\n";
920 
921  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
922  uint8_t httpbuf2[] = "filecontent\r\n"
923  "-----------------------------277531038314945--";
924  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
925  ThreadVars th_v;
926  TcpSession ssn;
927 
930 
931  memset(&th_v, 0, sizeof(th_v));
932  memset(&ssn, 0, sizeof(ssn));
933 
934  DetectEngineThreadCtx *det_ctx = NULL;
937  de_ctx->flags |= DE_QUIET;
938 
939  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;)");
940  FAIL_IF_NULL(s);
941 
943  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
944 
945  Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
946  FAIL_IF_NULL(f);
947  f->protoctx = &ssn;
948  f->proto = IPPROTO_TCP;
949  f->alproto = ALPROTO_HTTP;
950 
951  Packet *p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
952  FAIL_IF_NULL(p);
953  p->flow = f;
957 
959 
960  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
961  STREAM_TOSERVER | STREAM_START, httpbuf1,
962  httplen1);
963  FAIL_IF(r != 0);
964  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
965  FAIL_IF(PacketAlertCheck(p, 1));
966 
968  STREAM_TOSERVER | STREAM_EOF, httpbuf2, httplen2);
969  FAIL_IF(r != 0);
970  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
971  FAIL_IF(PacketAlertCheck(p, 1));
972 
973  HtpState *http_state = f->alstate;
974  FAIL_IF_NULL(http_state);
975  FAIL_IF_NULL(http_state->files_ts);
976 
978  FAIL_IF_NULL(files);
979  File *file = files->head;
980  FAIL_IF_NULL(file);
981  FAIL_IF(file->flags & FILE_STORE);
982 
984  UTHFreeFlow(f);
985  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
988  PASS;
989 }
990 
991 /**
992  * \test multiple files in a tx
993  */
994 static int DeStateSigTest08(void)
995 {
996  uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
997  "Host: www.server.lan\r\n"
998  "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
999  "Content-Length: 440\r\n"
1000  "\r\n"
1001  "-----------------------------277531038314945\r\n"
1002  "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"AAAApicture1.jpg\"\r\n"
1003  "Content-Type: image/jpeg\r\n"
1004  "\r\n";
1005 
1006  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1007  uint8_t httpbuf2[] = "file";
1008  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1009  uint8_t httpbuf3[] = "content\r\n"
1010  "-----------------------------277531038314945\r\n";
1011  uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
1012 
1013  uint8_t httpbuf4[] = "Content-Disposition: form-data; name=\"uploadfile_1\"; filename=\"BBBBpicture2.jpg\"\r\n"
1014  "Content-Type: image/jpeg\r\n"
1015  "\r\n"
1016  "filecontent2\r\n"
1017  "-----------------------------277531038314945--";
1018  uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
1019 
1020  ThreadVars th_v;
1021  TcpSession ssn;
1022 
1025 
1026  memset(&th_v, 0, sizeof(th_v));
1027  memset(&ssn, 0, sizeof(ssn));
1028 
1029  DetectEngineThreadCtx *det_ctx = NULL;
1032  de_ctx->flags |= DE_QUIET;
1033 
1034  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;)");
1035  FAIL_IF_NULL(s);
1036 
1038  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1039 
1040  Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
1041  FAIL_IF_NULL(f);
1042  f->protoctx = &ssn;
1043  f->proto = IPPROTO_TCP;
1044  f->alproto = ALPROTO_HTTP;
1045 
1046  Packet *p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1047  FAIL_IF_NULL(p);
1048  p->flow = f;
1052 
1054 
1055  /* HTTP request with 1st part of the multipart body */
1056 
1057  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
1058  STREAM_TOSERVER | STREAM_START, httpbuf1,
1059  httplen1);
1060  FAIL_IF(r != 0);
1061  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1062  FAIL_IF(PacketAlertCheck(p, 1));
1063 
1065  STREAM_TOSERVER, httpbuf2, httplen2);
1066  FAIL_IF(r != 0);
1067  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1068  FAIL_IF(PacketAlertCheck(p, 1));
1069 
1070  HtpState *http_state = f->alstate;
1071  FAIL_IF_NULL(http_state);
1072  FAIL_IF_NULL(http_state->files_ts);
1073 
1075  FAIL_IF_NULL(files);
1076  File *file = files->head;
1077  FAIL_IF_NULL(file);
1078  FAIL_IF(file->flags & FILE_STORE);
1079 
1080  /* 2nd multipart body file */
1081 
1083  STREAM_TOSERVER, httpbuf3, httplen3);
1084  FAIL_IF(r != 0);
1085  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1086  FAIL_IF(PacketAlertCheck(p, 1));
1087 
1089  STREAM_TOSERVER | STREAM_EOF, httpbuf4, httplen4);
1090  FAIL_IF(r != 0);
1091  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1093 
1094  http_state = f->alstate;
1095  FAIL_IF_NULL(http_state);
1096  FAIL_IF_NULL(http_state->files_ts);
1097 
1099  FAIL_IF_NULL(files);
1100  file = files->head;
1101  FAIL_IF_NULL(file);
1102  file = file->next;
1103  FAIL_IF_NULL(file);
1104  FAIL_IF_NOT(file->flags & FILE_STORE);
1105 
1107  UTHFreeFlow(f);
1108  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1111  PASS;
1112 }
1113 
1114 /**
1115  * \test multiple files in a tx. Both files should match
1116  */
1117 static int DeStateSigTest09(void)
1118 {
1119  uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
1120  "Host: www.server.lan\r\n"
1121  "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
1122  "Content-Length: 440\r\n"
1123  "\r\n"
1124  "-----------------------------277531038314945\r\n"
1125  "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n"
1126  "Content-Type: image/jpeg\r\n"
1127  "\r\n";
1128 
1129  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1130  uint8_t httpbuf2[] = "file";
1131  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1132  uint8_t httpbuf3[] = "content\r\n"
1133  "-----------------------------277531038314945\r\n";
1134  uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
1135 
1136  uint8_t httpbuf4[] = "Content-Disposition: form-data; name=\"uploadfile_1\"; filename=\"somepicture2.jpg\"\r\n"
1137  "Content-Type: image/jpeg\r\n"
1138  "\r\n"
1139  "filecontent2\r\n"
1140  "-----------------------------277531038314945--";
1141  uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
1142 
1143  ThreadVars th_v;
1144  TcpSession ssn;
1145 
1148 
1149  memset(&th_v, 0, sizeof(th_v));
1150  memset(&ssn, 0, sizeof(ssn));
1151 
1152  DetectEngineThreadCtx *det_ctx = NULL;
1155  de_ctx->flags |= DE_QUIET;
1156 
1157  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;)");
1158  FAIL_IF_NULL(s);
1159 
1161  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1162 
1163  Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
1164  FAIL_IF_NULL(f);
1165  f->protoctx = &ssn;
1166  f->proto = IPPROTO_TCP;
1167  f->alproto = ALPROTO_HTTP;
1168 
1169  Packet *p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1170  FAIL_IF_NULL(p);
1171  p->flow = f;
1175 
1177 
1178  /* HTTP request with 1st part of the multipart body */
1179 
1180  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
1181  STREAM_TOSERVER | STREAM_START, httpbuf1,
1182  httplen1);
1183  FAIL_IF(r != 0);
1184  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1186 
1188  STREAM_TOSERVER, httpbuf2, httplen2);
1189  FAIL_IF(r != 0);
1190  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1191  FAIL_IF(PacketAlertCheck(p, 1));
1192 
1193  HtpState *http_state = f->alstate;
1194  FAIL_IF_NULL(http_state);
1195  FAIL_IF_NULL(http_state->files_ts);
1196 
1198  FAIL_IF_NULL(files);
1199  File *file = files->head;
1200  FAIL_IF_NULL(file);
1201  FAIL_IF_NOT(file->flags & FILE_STORE);
1202 
1203  /* 2nd multipart body file */
1204 
1206  STREAM_TOSERVER, httpbuf3, httplen3);
1207  FAIL_IF(r != 0);
1208  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1209  FAIL_IF(PacketAlertCheck(p, 1));
1210 
1212  STREAM_TOSERVER | STREAM_EOF, httpbuf4, httplen4);
1213  FAIL_IF(r != 0);
1214  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1216 
1217  http_state = f->alstate;
1218  FAIL_IF_NULL(http_state);
1219  FAIL_IF_NULL(http_state->files_ts);
1220 
1222  FAIL_IF_NULL(files);
1223  file = files->head;
1224  FAIL_IF_NULL(file);
1225  FAIL_IF_NOT(file->flags & FILE_STORE);
1226 
1228  UTHFreeFlow(f);
1229  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1232  PASS;
1233 }
1234 
1235 /**
1236  * \test multiple files in a tx. Both files should match. No other matches.
1237  */
1238 static int DeStateSigTest10(void)
1239 {
1240  uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
1241  "Host: www.server.lan\r\n"
1242  "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
1243  "Content-Length: 440\r\n"
1244  "\r\n"
1245  "-----------------------------277531038314945\r\n"
1246  "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n"
1247  "Content-Type: image/jpeg\r\n"
1248  "\r\n";
1249 
1250  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1251  uint8_t httpbuf2[] = "file";
1252  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1253  uint8_t httpbuf3[] = "content\r\n"
1254  "-----------------------------277531038314945\r\n";
1255  uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
1256 
1257  uint8_t httpbuf4[] = "Content-Disposition: form-data; name=\"uploadfile_1\"; filename=\"somepicture2.jpg\"\r\n"
1258  "Content-Type: image/jpeg\r\n"
1259  "\r\n"
1260  "filecontent2\r\n"
1261  "-----------------------------277531038314945--";
1262  uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
1263 
1264  ThreadVars th_v;
1265  TcpSession ssn;
1266 
1269 
1270  memset(&th_v, 0, sizeof(th_v));
1271  memset(&ssn, 0, sizeof(ssn));
1272 
1273  DetectEngineThreadCtx *det_ctx = NULL;
1276  de_ctx->flags |= DE_QUIET;
1277 
1278  Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any (filename:\"somepicture\"; filestore; sid:1; rev:1;)");
1279  FAIL_IF_NULL(s);
1280 
1282  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1283 
1284  Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
1285  FAIL_IF_NULL(f);
1286  f->protoctx = &ssn;
1287  f->proto = IPPROTO_TCP;
1288  f->alproto = ALPROTO_HTTP;
1289 
1290  Packet *p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1291  FAIL_IF_NULL(p);
1292  p->flow = f;
1296 
1298 
1299  /* HTTP request with 1st part of the multipart body */
1300 
1301  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
1302  STREAM_TOSERVER | STREAM_START, httpbuf1,
1303  httplen1);
1304  FAIL_IF(r != 0);
1305  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1307 
1309  STREAM_TOSERVER, httpbuf2, httplen2);
1310  FAIL_IF(r != 0);
1311  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1312  FAIL_IF(PacketAlertCheck(p, 1));
1313 
1314  HtpState *http_state = f->alstate;
1315  FAIL_IF_NULL(http_state);
1316  FAIL_IF_NULL(http_state->files_ts);
1317 
1319  FAIL_IF_NULL(files);
1320  File *file = files->head;
1321  FAIL_IF_NULL(file);
1322  FAIL_IF_NOT(file->flags & FILE_STORE);
1323 
1324  /* 2nd multipart body file */
1325 
1327  STREAM_TOSERVER, httpbuf3, httplen3);
1328  FAIL_IF(r != 0);
1329  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1330  FAIL_IF(PacketAlertCheck(p, 1));
1331 
1333  STREAM_TOSERVER | STREAM_EOF, httpbuf4, httplen4);
1334  FAIL_IF(r != 0);
1335  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1337 
1338  http_state = f->alstate;
1339  FAIL_IF_NULL(http_state);
1340  FAIL_IF_NULL(http_state->files_ts);
1341 
1343  FAIL_IF_NULL(files);
1344  file = files->head;
1345  FAIL_IF_NULL(file);
1346  FAIL_IF_NOT(file->flags & FILE_STORE);
1347 
1349  UTHFreeFlow(f);
1350  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1353  PASS;
1354 }
1355 
1356 #endif
1357 
1359 {
1360 #ifdef UNITTESTS
1361  UtRegisterTest("DeStateTest01", DeStateTest01);
1362  UtRegisterTest("DeStateTest02", DeStateTest02);
1363  UtRegisterTest("DeStateTest03", DeStateTest03);
1364  UtRegisterTest("DeStateSigTest01", DeStateSigTest01);
1365  UtRegisterTest("DeStateSigTest02", DeStateSigTest02);
1366  UtRegisterTest("DeStateSigTest03", DeStateSigTest03);
1367  UtRegisterTest("DeStateSigTest04", DeStateSigTest04);
1368  UtRegisterTest("DeStateSigTest05", DeStateSigTest05);
1369  UtRegisterTest("DeStateSigTest06", DeStateSigTest06);
1370  UtRegisterTest("DeStateSigTest07", DeStateSigTest07);
1371  UtRegisterTest("DeStateSigTest08", DeStateSigTest08);
1372  UtRegisterTest("DeStateSigTest09", DeStateSigTest09);
1373  UtRegisterTest("DeStateSigTest10", DeStateSigTest10);
1374 #endif
1375 
1376  return;
1377 }
1378 
1379 /**
1380  * @}
1381  */
app-layer-dcerpc.h
FileContainer_
Definition: util-file.h:100
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:88
PKT_HAS_FLOW
#define PKT_HAS_FLOW
Definition: decode.h:1109
flow-util.h
DetectEngineState_
Definition: detect-engine-state.h:92
Signature_::num
SigIntId num
Definition: detect.h:538
stream-tcp.h
SigGroupHead_
Container for matching data for a signature group.
Definition: detect.h:1347
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:727
DetectEngineStateDirection_::cnt
SigIntId cnt
Definition: detect-engine-state.h:86
Flow_::proto
uint8_t proto
Definition: flow.h:365
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:347
SigInit
Signature * SigInit(DetectEngineCtx *, const char *)
Parses a signature and adds it to the Detection Engine Context.
Definition: detect-parse.c:2051
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:767
FILE_STORE
#define FILE_STORE
Definition: util-file.h:46
FileDisableStoringForTransaction
void FileDisableStoringForTransaction(Flow *f, uint8_t direction, uint64_t tx_id)
disable file storing for files in a transaction
Definition: util-file.c:1169
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2093
DetectEngineState_::dir_state
DetectEngineStateDirection dir_state[2]
Definition: detect-engine-state.h:93
AppLayerParserThreadCtxFree
void AppLayerParserThreadCtxFree(AppLayerParserThreadCtx *tctx)
Destroys the app layer parser thread context obtained using AppLayerParserThreadCtxAlloc().
Definition: app-layer-parser.c:278
FLOW_PKT_TOSERVER
#define FLOW_PKT_TOSERVER
Definition: flow.h:219
MIN
#define MIN(x, y)
Definition: suricata-common.h:377
AppLayerParserGetFiles
FileContainer * AppLayerParserGetFiles(const Flow *f, const uint8_t direction)
Definition: app-layer-parser.c:858
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:445
Flow_::protoctx
void * protoctx
Definition: flow.h:441
DeStateStoreItem_::sid
SigIntId sid
Definition: detect-engine-state.h:75
FLOW_IPV4
#define FLOW_IPV4
Definition: flow.h:95
AppLayerParserGetTransactionInspectId
uint64_t AppLayerParserGetTransactionInspectId(AppLayerParserState *pstate, uint8_t direction)
Definition: app-layer-parser.c:696
util-unittest.h
HtpState_
Definition: app-layer-htp.h:243
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:220
Flow_::alparser
AppLayerParserState * alparser
Definition: flow.h:475
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
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:1010
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:252
BIT_U32
#define BIT_U32(n)
Definition: suricata-common.h:386
STREAM_TOSERVER
#define STREAM_TOSERVER
Definition: stream.h:31
alp_tctx
AppLayerParserThreadCtx * alp_tctx
Definition: fuzz_applayerparserparse.c:19
FileContainer_::head
File * head
Definition: util-file.h:101
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:247
app-layer-parser.h
TRUE
#define TRUE
Definition: suricata-common.h:33
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:282
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:165
Packet_
Definition: decode.h:414
DE_STATE_FLAG_BASE
#define DE_STATE_FLAG_BASE
Definition: detect-engine-state.h:64
StreamTcpFreeConfig
void StreamTcpFreeConfig(char quiet)
Definition: stream-tcp.c:668
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:1032
DetectEngineStateFree
void DetectEngineStateFree(DetectEngineState *state)
Frees a DetectEngineState object.
Definition: detect-engine-state.c:175
SigGroupBuild
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
Definition: detect-engine-build.c:1884
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:252
File_::flags
uint16_t flags
Definition: util-file.h:64
DetectEngineStateDirection_::head
DeStateStore * head
Definition: detect-engine-state.h:84
File_
Definition: util-file.h:63
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:2356
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:267
DetectEngineThreadCtxInit
TmEcode DetectEngineThreadCtxInit(ThreadVars *, void *, void **)
initialize thread specific detection engine context
Definition: detect-engine.c:2797
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:1178
suricata-common.h
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *, void *)
Definition: detect-engine.c:3005
DeStateStore_
Definition: detect-engine-state.h:78
File_::next
struct File_ * next
Definition: util-file.h:77
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:773
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
DetectEngineStateDirection_::filestore_cnt
uint16_t filestore_cnt
Definition: detect-engine-state.h:87
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:476
DeStateStore_::store
DeStateStoreItem store[DE_STATE_CHUNK_SIZE]
Definition: detect-engine-state.h:79
Flow_::flags
uint32_t flags
Definition: flow.h:421
detect-parse.h
Signature_
Signature container.
Definition: detect.h:528
ALPROTO_HTTP
@ ALPROTO_HTTP
Definition: app-layer-protos.h:30
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:1112
FLOW_PKT_ESTABLISHED
#define FLOW_PKT_ESTABLISHED
Definition: flow.h:221
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2048
STREAM_EOF
#define STREAM_EOF
Definition: stream.h:30
AppLayerParserSetTxDetectState
int AppLayerParserSetTxDetectState(const Flow *f, void *tx, DetectEngineState *s)
Definition: app-layer-parser.c:1120
app-layer-protos.h
HtpState_::files_ts
FileContainer * files_ts
Definition: app-layer-htp.h:251
FILE_NOSTORE
#define FILE_NOSTORE
Definition: util-file.h:45
DetectEngineCtx_::flags
uint8_t flags
Definition: detect.h:768
AppLayerParserThreadCtx_
Definition: app-layer-parser.c:87
TcpSession_
Definition: stream-tcp-private.h:261
SigIntId
#define SigIntId
Definition: suricata-common.h:297
DeStateStoreItem_
Definition: detect-engine-state.h:73
Flow_::alproto
AppProto alproto
application level protocol
Definition: flow.h:450
DeStateRegisterTests
void DeStateRegisterTests(void)
Definition: detect-engine-state.c:1358
detect-engine-dcepayload.h
SigGroupHead_::filestore_cnt
uint16_t filestore_cnt
Definition: detect.h:1363
AppLayerParserGetTxCnt
uint64_t AppLayerParserGetTxCnt(const Flow *f, void *alstate)
Definition: app-layer-parser.c:1023
DetectEngineStateDirection_::tail
DeStateStore * tail
Definition: detect-engine-state.h:85
FLOW_DESTROY
#define FLOW_DESTROY(f)
Definition: flow-util.h:130
PKT_STREAM_EST
#define PKT_STREAM_EST
Definition: decode.h:1107
app-layer.h