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