suricata
app-layer-htp-file.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2011 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  * \file
20  *
21  * \author Victor Julien <victor@inliniac.net>
22  *
23  * This file provides HTTP protocol file handling support for the engine
24  * using HTP library.
25  */
26 
27 #include "suricata.h"
28 #include "suricata-common.h"
29 #include "debug.h"
30 #include "decode.h"
31 #include "threads.h"
32 
33 #include "util-print.h"
34 #include "util-pool.h"
35 #include "util-radix-tree.h"
36 
37 #include "stream-tcp-private.h"
38 #include "stream-tcp-reassemble.h"
39 #include "stream-tcp.h"
40 #include "stream.h"
41 
42 #include "app-layer.h"
43 #include "app-layer-protos.h"
44 #include "app-layer-parser.h"
45 #include "app-layer-htp.h"
46 #include "app-layer-htp-file.h"
47 
48 #include "util-spm.h"
49 #include "util-debug.h"
50 #include "util-time.h"
51 
52 #include "util-unittest.h"
53 #include "util-unittest-helper.h"
54 #include "flow-util.h"
55 
56 #include "detect-engine.h"
57 #include "detect-engine-state.h"
58 #include "detect-parse.h"
59 
60 #include "conf.h"
61 
62 #include "util-memcmp.h"
63 
64 /**
65  * \brief Open the file with "filename" and pass the first chunk
66  * of data if any.
67  *
68  * \param s http state
69  * \param filename name of the file
70  * \param filename_len length of the name
71  * \param data data chunk (if any)
72  * \param data_len length of the data portion
73  * \param direction flow direction
74  *
75  * \retval 0 ok
76  * \retval -1 error
77  * \retval -2 not handling files on this flow
78  */
79 int HTPFileOpen(HtpState *s, const uint8_t *filename, uint16_t filename_len,
80  const uint8_t *data, uint32_t data_len,
81  uint64_t txid, uint8_t direction)
82 {
83  int retval = 0;
84  uint16_t flags = 0;
85  FileContainer *files = NULL;
86  const StreamingBufferConfig *sbcfg = NULL;
87 
88  SCLogDebug("data %p data_len %"PRIu32, data, data_len);
89 
90  if (s == NULL) {
91  SCReturnInt(-1);
92  }
93 
94  if (direction & STREAM_TOCLIENT) {
95  if (s->files_tc == NULL) {
97  if (s->files_tc == NULL) {
98  retval = -1;
99  goto end;
100  }
101  }
102 
103  files = s->files_tc;
104 
105  flags = FileFlowToFlags(s->f, STREAM_TOCLIENT);
106 
107  if ((s->flags & HTP_FLAG_STORE_FILES_TS) ||
108  ((s->flags & HTP_FLAG_STORE_FILES_TX_TS) && txid == s->store_tx_id)) {
109  flags |= FILE_STORE;
110  flags &= ~FILE_NOSTORE;
111  } else if (!(flags & FILE_STORE) && (s->f->file_flags & FLOWFILE_NO_STORE_TC)) {
112  flags |= FILE_NOSTORE;
113  }
114 
115  sbcfg = &s->cfg->response.sbcfg;
116 
117  } else {
118  if (s->files_ts == NULL) {
120  if (s->files_ts == NULL) {
121  retval = -1;
122  goto end;
123  }
124  }
125 
126  files = s->files_ts;
127 
128  flags = FileFlowToFlags(s->f, STREAM_TOSERVER);
129  if ((s->flags & HTP_FLAG_STORE_FILES_TC) ||
130  ((s->flags & HTP_FLAG_STORE_FILES_TX_TC) && txid == s->store_tx_id)) {
131  flags |= FILE_STORE;
132  flags &= ~FILE_NOSTORE;
133  } else if (!(flags & FILE_STORE) && (s->f->file_flags & FLOWFILE_NO_STORE_TS)) {
134  flags |= FILE_NOSTORE;
135  }
136 
137  sbcfg = &s->cfg->request.sbcfg;
138  }
139 
140  if (FileOpenFileWithId(files, sbcfg, s->file_track_id++,
141  filename, filename_len,
142  data, data_len, flags) != 0)
143  {
144  retval = -1;
145  }
146 
147  FileSetTx(files->tail, txid);
148 
149  FilePrune(files);
150 end:
151  SCReturnInt(retval);
152 }
153 
154 /**
155  * Performs parsing of the content-range value
156  *
157  * @param[in] rawvalue
158  * @param[out] range
159  *
160  * @return HTP_OK on success, HTP_ERROR on failure.
161  */
162 int HTPParseContentRange(bstr * rawvalue, HtpContentRange *range)
163 {
164  unsigned char *data = bstr_ptr(rawvalue);
165  size_t len = bstr_len(rawvalue);
166  size_t pos = 0;
167  size_t last_pos;
168 
169  // skip spaces and units
170  while (pos < len && data[pos] == ' ')
171  pos++;
172  while (pos < len && data[pos] != ' ')
173  pos++;
174  while (pos < len && data[pos] == ' ')
175  pos++;
176 
177  // initialize to unseen
178  range->start = -1;
179  range->end = -1;
180  range->size = -1;
181 
182  if (pos == len) {
183  // missing data
184  return -1;
185  }
186 
187  if (data[pos] == '*') {
188  // case with size only
189  if (len <= pos + 1 || data[pos+1] != '/') {
190  range->size = -1;
191  return -1;
192  }
193  pos += 2;
194  range->size = bstr_util_mem_to_pint(data + pos, len - pos, 10, &last_pos);
195  } else {
196  // case with start and end
197  range->start = bstr_util_mem_to_pint(data + pos, len - pos, 10, &last_pos);
198  pos += last_pos;
199  if (len <= pos + 1 || data[pos] != '-') {
200  return -1;
201  }
202  pos++;
203  range->end = bstr_util_mem_to_pint(data + pos, len - pos, 10, &last_pos);
204  pos += last_pos;
205  if (len <= pos + 1 || data[pos] != '/') {
206  return -1;
207  }
208  pos++;
209  if (data[pos] != '*') {
210  // case with size
211  range->size = bstr_util_mem_to_pint(data + pos, len - pos, 10, &last_pos);
212  }
213  }
214 
215  return 0;
216 }
217 
218 /**
219  * \brief Sets range for a file
220  *
221  * \param s http state
222  * \param rawvalue raw header value
223  *
224  * \retval 0 ok
225  * \retval -1 error
226  * \retval -2 error parsing
227  * \retval -3 error negative end in range
228  */
229 int HTPFileSetRange(HtpState *s, bstr *rawvalue)
230 {
231  SCEnter();
232 
233  if (s == NULL) {
234  SCReturnInt(-1);
235  }
236 
237  FileContainer * files = s->files_tc;
238  if (files == NULL) {
239  SCLogDebug("no files in state");
240  SCReturnInt(-1);
241  }
242 
243  HtpContentRange crparsed;
244  if (HTPParseContentRange(rawvalue, &crparsed) != 0) {
245  SCLogDebug("parsing range failed");
246  SCReturnInt(-2);
247  }
248  if (crparsed.end <= 0) {
249  SCLogDebug("negative end in range");
250  SCReturnInt(-3);
251  }
252  int retval = FileSetRange(files, crparsed.start, crparsed.end);
253  if (retval == -1) {
254  SCLogDebug("set range failed");
255  }
256  SCReturnInt(retval);
257 }
258 
259 /**
260  * \brief Store a chunk of data in the flow
261  *
262  * \param s http state
263  * \param data data chunk (if any)
264  * \param data_len length of the data portion
265  * \param direction flow direction
266  *
267  * \retval 0 ok
268  * \retval -1 error
269  * \retval -2 file doesn't need storing
270  */
271 int HTPFileStoreChunk(HtpState *s, const uint8_t *data, uint32_t data_len,
272  uint8_t direction)
273 {
274  SCEnter();
275 
276  int retval = 0;
277  int result = 0;
278  FileContainer *files = NULL;
279 
280  if (s == NULL) {
281  SCReturnInt(-1);
282  }
283 
284  if (direction & STREAM_TOCLIENT) {
285  files = s->files_tc;
286  } else {
287  files = s->files_ts;
288  }
289 
290  if (files == NULL) {
291  SCLogDebug("no files in state");
292  retval = -1;
293  goto end;
294  }
295 
296  result = FileAppendData(files, data, data_len);
297  if (result == -1) {
298  SCLogDebug("appending data failed");
299  retval = -1;
300  } else if (result == -2) {
301  retval = -2;
302  }
303 
304  FilePrune(files);
305 end:
306  SCReturnInt(retval);
307 }
308 
309 /**
310  * \brief Close the file in the flow
311  *
312  * \param s http state
313  * \param data data chunk if any
314  * \param data_len length of the data portion
315  * \param flags flags to indicate events
316  * \param direction flow direction
317  *
318  * Currently on the FLOW_FILE_TRUNCATED flag is implemented, indicating
319  * that the file isn't complete but we're stopping storing it.
320  *
321  * \retval 0 ok
322  * \retval -1 error
323  * \retval -2 not storing files on this flow/tx
324  */
325 int HTPFileClose(HtpState *s, const uint8_t *data, uint32_t data_len,
326  uint8_t flags, uint8_t direction)
327 {
328  SCEnter();
329 
330  int retval = 0;
331  int result = 0;
332  FileContainer *files = NULL;
333 
334  if (s == NULL) {
335  SCReturnInt(-1);
336  }
337 
338  if (direction & STREAM_TOCLIENT) {
339  files = s->files_tc;
340  } else {
341  files = s->files_ts;
342  }
343 
344  if (files == NULL) {
345  retval = -1;
346  goto end;
347  }
348 
349  result = FileCloseFile(files, data, data_len, flags);
350  if (result == -1) {
351  retval = -1;
352  } else if (result == -2) {
353  retval = -2;
354  }
355 
356  FilePrune(files);
357 end:
358  SCReturnInt(retval);
359 }
360 
361 #ifdef UNITTESTS
362 static int HTPFileParserTest01(void)
363 {
364  int result = 0;
365  Flow *f = NULL;
366  uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
367  "Host: www.server.lan\r\n"
368  "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
369  "Content-Length: 215\r\n"
370  "\r\n"
371  "-----------------------------277531038314945\r\n"
372  "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n"
373  "Content-Type: image/jpeg\r\n"
374  "\r\n";
375 
376  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
377  uint8_t httpbuf2[] = "filecontent\r\n"
378  "-----------------------------277531038314945--";
379  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
380 
381  TcpSession ssn;
383  HtpState *http_state = NULL;
384  memset(&ssn, 0, sizeof(ssn));
385 
386  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
387  if (f == NULL)
388  goto end;
389  f->protoctx = &ssn;
390  f->proto = IPPROTO_TCP;
391  f->alproto = ALPROTO_HTTP;
392 
394 
395  SCLogDebug("\n>>>> processing chunk 1 <<<<\n");
396  FLOWLOCK_WRLOCK(f);
397  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
398  STREAM_TOSERVER | STREAM_START, httpbuf1,
399  httplen1);
400  if (r != 0) {
401  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
402  result = 0;
403  FLOWLOCK_UNLOCK(f);
404  goto end;
405  }
406  FLOWLOCK_UNLOCK(f);
407 
408  SCLogDebug("\n>>>> processing chunk 2 size %u <<<<\n", httplen2);
409  FLOWLOCK_WRLOCK(f);
410  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
411  STREAM_TOSERVER | STREAM_EOF, httpbuf2, httplen2);
412  if (r != 0) {
413  printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
414  result = 0;
415  FLOWLOCK_UNLOCK(f);
416  goto end;
417  }
418  FLOWLOCK_UNLOCK(f);
419 
420  http_state = f->alstate;
421  if (http_state == NULL) {
422  printf("no http state: ");
423  result = 0;
424  goto end;
425  }
426 
427  htp_tx_t *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP, http_state, 0);
428  if (tx == NULL) {
429  goto end;
430  }
431 
432  if (tx->request_method == NULL || memcmp(bstr_util_strdup_to_c(tx->request_method), "POST", 4) != 0)
433  {
434  printf("expected method POST, got %s \n", bstr_util_strdup_to_c(tx->request_method));
435  goto end;
436  }
437 
438  result = 1;
439 end:
440  if (alp_tctx != NULL)
441  AppLayerParserThreadCtxFree(alp_tctx);
443  UTHFreeFlow(f);
444  return result;
445 }
446 
447 static int HTPFileParserTest02(void)
448 {
449  int result = 0;
450  Flow *f = NULL;
451  uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
452  "Host: www.server.lan\r\n"
453  "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
454  "Content-Length: 337\r\n"
455  "\r\n";
456  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
457 
458  uint8_t httpbuf2[] = "-----------------------------277531038314945\r\n"
459  "Content-Disposition: form-data; name=\"email\"\r\n"
460  "\r\n"
461  "someaddress@somedomain.lan\r\n";
462  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
463 
464  uint8_t httpbuf3[] = "-----------------------------277531038314945\r\n"
465  "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n"
466  "Content-Type: image/jpeg\r\n"
467  "\r\n";
468  uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
469 
470  uint8_t httpbuf4[] = "filecontent\r\n"
471  "-----------------------------277531038314945--";
472  uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
473 
474  TcpSession ssn;
475  HtpState *http_state = NULL;
477 
478  memset(&ssn, 0, sizeof(ssn));
479 
480  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
481  if (f == NULL)
482  goto end;
483  f->protoctx = &ssn;
484  f->proto = IPPROTO_TCP;
485  f->alproto = ALPROTO_HTTP;
486 
488 
489  SCLogDebug("\n>>>> processing chunk 1 <<<<\n");
490  FLOWLOCK_WRLOCK(f);
491  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
492  STREAM_TOSERVER | STREAM_START, httpbuf1,
493  httplen1);
494  if (r != 0) {
495  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
496  result = 0;
497  FLOWLOCK_UNLOCK(f);
498  goto end;
499  }
500  FLOWLOCK_UNLOCK(f);
501 
502  SCLogDebug("\n>>>> processing chunk 2 size %u <<<<\n", httplen2);
503  FLOWLOCK_WRLOCK(f);
504  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
505  STREAM_TOSERVER | STREAM_EOF, httpbuf2, httplen2);
506  if (r != 0) {
507  printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
508  result = 0;
509  FLOWLOCK_UNLOCK(f);
510  goto end;
511  }
512  FLOWLOCK_UNLOCK(f);
513 
514  SCLogDebug("\n>>>> processing chunk 3 size %u <<<<\n", httplen3);
515  FLOWLOCK_WRLOCK(f);
516  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
517  STREAM_TOSERVER | STREAM_EOF, httpbuf3, httplen3);
518  if (r != 0) {
519  printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
520  result = 0;
521  FLOWLOCK_UNLOCK(f);
522  goto end;
523  }
524  FLOWLOCK_UNLOCK(f);
525 
526  SCLogDebug("\n>>>> processing chunk 4 size %u <<<<\n", httplen4);
527  FLOWLOCK_WRLOCK(f);
528  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
529  STREAM_TOSERVER | STREAM_EOF, httpbuf4, httplen4);
530  if (r != 0) {
531  printf("toserver chunk 4 returned %" PRId32 ", expected 0: ", r);
532  result = 0;
533  FLOWLOCK_UNLOCK(f);
534  goto end;
535  }
536  FLOWLOCK_UNLOCK(f);
537 
538  http_state = f->alstate;
539  if (http_state == NULL) {
540  printf("no http state: ");
541  result = 0;
542  goto end;
543  }
544 
545  htp_tx_t *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP, http_state, 0);
546  if (tx == NULL) {
547  goto end;
548  }
549 
550  if (tx->request_method == NULL || memcmp(bstr_util_strdup_to_c(tx->request_method), "POST", 4) != 0)
551  {
552  printf("expected method POST, got %s \n", bstr_util_strdup_to_c(tx->request_method));
553  goto end;
554  }
555 
556  if (http_state->files_ts == NULL || http_state->files_ts->tail == NULL ||
557  http_state->files_ts->tail->state != FILE_STATE_CLOSED) {
558  goto end;
559  }
560 
561  result = 1;
562 end:
563  if (alp_tctx != NULL)
564  AppLayerParserThreadCtxFree(alp_tctx);
566  UTHFreeFlow(f);
567  return result;
568 }
569 
570 static int HTPFileParserTest03(void)
571 {
572  int result = 0;
573  Flow *f = NULL;
574  uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
575  "Host: www.server.lan\r\n"
576  "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
577  "Content-Length: 337\r\n"
578  "\r\n";
579  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
580 
581  uint8_t httpbuf2[] = "-----------------------------277531038314945\r\n"
582  "Content-Disposition: form-data; name=\"email\"\r\n"
583  "\r\n"
584  "someaddress@somedomain.lan\r\n";
585  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
586 
587  uint8_t httpbuf3[] = "-----------------------------277531038314945\r\n"
588  "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n"
589  "Content-Type: image/jpeg\r\n"
590  "\r\n";
591  uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
592 
593  uint8_t httpbuf4[] = "file";
594  uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
595 
596  uint8_t httpbuf5[] = "content\r\n";
597  uint32_t httplen5 = sizeof(httpbuf5) - 1; /* minus the \0 */
598 
599  uint8_t httpbuf6[] = "-----------------------------277531038314945--";
600  uint32_t httplen6 = sizeof(httpbuf6) - 1; /* minus the \0 */
601 
602  TcpSession ssn;
603  HtpState *http_state = NULL;
605 
606  memset(&ssn, 0, sizeof(ssn));
607 
608  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
609  if (f == NULL)
610  goto end;
611  f->protoctx = &ssn;
612  f->proto = IPPROTO_TCP;
613  f->alproto = ALPROTO_HTTP;
614 
616 
617  SCLogDebug("\n>>>> processing chunk 1 <<<<\n");
618  FLOWLOCK_WRLOCK(f);
619  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
620  STREAM_TOSERVER | STREAM_START, httpbuf1,
621  httplen1);
622  if (r != 0) {
623  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
624  result = 0;
625  FLOWLOCK_UNLOCK(f);
626  goto end;
627  }
628  FLOWLOCK_UNLOCK(f);
629 
630  SCLogDebug("\n>>>> processing chunk 2 size %u <<<<\n", httplen2);
631  FLOWLOCK_WRLOCK(f);
632  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
633  STREAM_TOSERVER | STREAM_EOF, httpbuf2, httplen2);
634  if (r != 0) {
635  printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
636  result = 0;
637  FLOWLOCK_UNLOCK(f);
638  goto end;
639  }
640  FLOWLOCK_UNLOCK(f);
641 
642  SCLogDebug("\n>>>> processing chunk 3 size %u <<<<\n", httplen3);
643  FLOWLOCK_WRLOCK(f);
644  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
645  STREAM_TOSERVER | STREAM_EOF, httpbuf3, httplen3);
646  if (r != 0) {
647  printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
648  result = 0;
649  FLOWLOCK_UNLOCK(f);
650  goto end;
651  }
652  FLOWLOCK_UNLOCK(f);
653 
654  SCLogDebug("\n>>>> processing chunk 4 size %u <<<<\n", httplen4);
655  FLOWLOCK_WRLOCK(f);
656  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
657  STREAM_TOSERVER | STREAM_EOF, httpbuf4, httplen4);
658  if (r != 0) {
659  printf("toserver chunk 4 returned %" PRId32 ", expected 0: ", r);
660  result = 0;
661  FLOWLOCK_UNLOCK(f);
662  goto end;
663  }
664  FLOWLOCK_UNLOCK(f);
665 
666  SCLogDebug("\n>>>> processing chunk 5 size %u <<<<\n", httplen5);
667  FLOWLOCK_WRLOCK(f);
668  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
669  STREAM_TOSERVER | STREAM_EOF, httpbuf5, httplen5);
670  if (r != 0) {
671  printf("toserver chunk 5 returned %" PRId32 ", expected 0: ", r);
672  result = 0;
673  FLOWLOCK_UNLOCK(f);
674  goto end;
675  }
676  FLOWLOCK_UNLOCK(f);
677 
678  SCLogDebug("\n>>>> processing chunk 6 size %u <<<<\n", httplen6);
679  FLOWLOCK_WRLOCK(f);
680  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
681  STREAM_TOSERVER | STREAM_EOF, httpbuf6, httplen6);
682  if (r != 0) {
683  printf("toserver chunk 6 returned %" PRId32 ", expected 0: ", r);
684  result = 0;
685  FLOWLOCK_UNLOCK(f);
686  goto end;
687  }
688  FLOWLOCK_UNLOCK(f);
689 
690  http_state = f->alstate;
691  if (http_state == NULL) {
692  printf("no http state: ");
693  result = 0;
694  goto end;
695  }
696 
697  htp_tx_t *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP, http_state, 0);
698  if (tx == NULL) {
699  goto end;
700  }
701 
702  if (tx->request_method == NULL || memcmp(bstr_util_strdup_to_c(tx->request_method), "POST", 4) != 0)
703  {
704  printf("expected method POST, got %s \n", bstr_util_strdup_to_c(tx->request_method));
705  goto end;
706  }
707 
708  if (http_state->files_ts == NULL || http_state->files_ts->tail == NULL ||
709  http_state->files_ts->tail->state != FILE_STATE_CLOSED) {
710  goto end;
711  }
712 
713  if (http_state->files_ts->head == NULL ||
714  FileDataSize(http_state->files_ts->head) != 11)
715  {
716  if (http_state->files_ts->head != NULL)
717  printf("filedata len not 11 but %"PRIu64": ",
718  FileDataSize(http_state->files_ts->head));
719  goto end;
720  }
721 
722  result = 1;
723 end:
724  if (alp_tctx != NULL)
725  AppLayerParserThreadCtxFree(alp_tctx);
727  UTHFreeFlow(f);
728  return result;
729 }
730 
731 static int HTPFileParserTest04(void)
732 {
733  int result = 0;
734  Flow *f = NULL;
735  uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
736  "Host: www.server.lan\r\n"
737  "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
738  "Content-Length: 373\r\n"
739  "\r\n";
740  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
741 
742  uint8_t httpbuf2[] = "-----------------------------277531038314945\r\n"
743  "Content-Disposition: form-data; name=\"email\"\r\n"
744  "\r\n"
745  "someaddress@somedomain.lan\r\n";
746  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
747 
748  uint8_t httpbuf3[] = "-----------------------------277531038314945\r\n"
749  "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n"
750  "Content-Type: image/jpeg\r\n"
751  "\r\n";
752  uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
753 
754  uint8_t httpbuf4[] = "file0123456789abcdefghijklmnopqrstuvwxyz";
755  uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
756 
757  uint8_t httpbuf5[] = "content\r\n";
758  uint32_t httplen5 = sizeof(httpbuf5) - 1; /* minus the \0 */
759 
760  uint8_t httpbuf6[] = "-----------------------------277531038314945--";
761  uint32_t httplen6 = sizeof(httpbuf6) - 1; /* minus the \0 */
762 
763  TcpSession ssn;
764  HtpState *http_state = NULL;
766 
767  memset(&ssn, 0, sizeof(ssn));
768 
769  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
770  if (f == NULL)
771  goto end;
772  f->protoctx = &ssn;
773  f->proto = IPPROTO_TCP;
774  f->alproto = ALPROTO_HTTP;
775 
777 
778  SCLogDebug("\n>>>> processing chunk 1 <<<<\n");
779  FLOWLOCK_WRLOCK(f);
780  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
781  STREAM_TOSERVER | STREAM_START, httpbuf1,
782  httplen1);
783  if (r != 0) {
784  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
785  result = 0;
786  FLOWLOCK_UNLOCK(f);
787  goto end;
788  }
789  FLOWLOCK_UNLOCK(f);
790 
791  SCLogDebug("\n>>>> processing chunk 2 size %u <<<<\n", httplen2);
792  FLOWLOCK_WRLOCK(f);
793  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
794  STREAM_TOSERVER | STREAM_EOF, httpbuf2, httplen2);
795  if (r != 0) {
796  printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
797  result = 0;
798  FLOWLOCK_UNLOCK(f);
799  goto end;
800  }
801  FLOWLOCK_UNLOCK(f);
802 
803  SCLogDebug("\n>>>> processing chunk 3 size %u <<<<\n", httplen3);
804  FLOWLOCK_WRLOCK(f);
805  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
806  STREAM_TOSERVER | STREAM_EOF, httpbuf3, httplen3);
807  if (r != 0) {
808  printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
809  result = 0;
810  FLOWLOCK_UNLOCK(f);
811  goto end;
812  }
813  FLOWLOCK_UNLOCK(f);
814 
815  SCLogDebug("\n>>>> processing chunk 4 size %u <<<<\n", httplen4);
816  FLOWLOCK_WRLOCK(f);
817  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
818  STREAM_TOSERVER | STREAM_EOF, httpbuf4, httplen4);
819  if (r != 0) {
820  printf("toserver chunk 4 returned %" PRId32 ", expected 0: ", r);
821  result = 0;
822  FLOWLOCK_UNLOCK(f);
823  goto end;
824  }
825  FLOWLOCK_UNLOCK(f);
826 
827  SCLogDebug("\n>>>> processing chunk 5 size %u <<<<\n", httplen5);
828  FLOWLOCK_WRLOCK(f);
829  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
830  STREAM_TOSERVER | STREAM_EOF, httpbuf5, httplen5);
831  if (r != 0) {
832  printf("toserver chunk 5 returned %" PRId32 ", expected 0: ", r);
833  result = 0;
834  FLOWLOCK_UNLOCK(f);
835  goto end;
836  }
837  FLOWLOCK_UNLOCK(f);
838 
839  SCLogDebug("\n>>>> processing chunk 6 size %u <<<<\n", httplen6);
840  FLOWLOCK_WRLOCK(f);
841  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
842  STREAM_TOSERVER | STREAM_EOF, httpbuf6, httplen6);
843  if (r != 0) {
844  printf("toserver chunk 6 returned %" PRId32 ", expected 0: ", r);
845  result = 0;
846  FLOWLOCK_UNLOCK(f);
847  goto end;
848  }
849  FLOWLOCK_UNLOCK(f);
850 
851  http_state = f->alstate;
852  if (http_state == NULL) {
853  printf("no http state: ");
854  result = 0;
855  goto end;
856  }
857 
858  htp_tx_t *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP, http_state, 0);
859  if (tx == NULL) {
860  goto end;
861  }
862 
863  if (tx->request_method == NULL || memcmp(bstr_util_strdup_to_c(tx->request_method), "POST", 4) != 0)
864  {
865  printf("expected method POST, got %s: ", bstr_util_strdup_to_c(tx->request_method));
866  goto end;
867  }
868 
869  if (http_state->files_ts == NULL || http_state->files_ts->tail == NULL ||
870  http_state->files_ts->tail->state != FILE_STATE_CLOSED) {
871  goto end;
872  }
873 
874  result = 1;
875 end:
876  if (alp_tctx != NULL)
877  AppLayerParserThreadCtxFree(alp_tctx);
879  UTHFreeFlow(f);
880  return result;
881 }
882 
883 static int HTPFileParserTest05(void)
884 {
885  int result = 0;
886  Flow *f = NULL;
887  uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
888  "Host: www.server.lan\r\n"
889  "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
890  "Content-Length: 544\r\n"
891  "\r\n"
892  "-----------------------------277531038314945\r\n"
893  "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n"
894  "Content-Type: image/jpeg\r\n"
895  "\r\n"
896  "filecontent\r\n"
897  "-----------------------------277531038314945\r\n";
898  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
899  uint8_t httpbuf2[] = "Content-Disposition: form-data; name=\"uploadfile_1\"; filename=\"somepicture2.jpg\"\r\n"
900  "Content-Type: image/jpeg\r\n"
901  "\r\n"
902  "FILECONTENT\r\n"
903  "-----------------------------277531038314945--";
904  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
905 
906  TcpSession ssn;
907  HtpState *http_state = NULL;
909 
910  memset(&ssn, 0, sizeof(ssn));
911 
912  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
913  if (f == NULL)
914  goto end;
915  f->protoctx = &ssn;
916  f->proto = IPPROTO_TCP;
917  f->alproto = ALPROTO_HTTP;
918 
920 
921  SCLogDebug("\n>>>> processing chunk 1 size %u <<<<\n", httplen1);
922  FLOWLOCK_WRLOCK(f);
923  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
924  STREAM_TOSERVER | STREAM_START, httpbuf1,
925  httplen1);
926  if (r != 0) {
927  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
928  result = 0;
929  FLOWLOCK_UNLOCK(f);
930  goto end;
931  }
932  FLOWLOCK_UNLOCK(f);
933 
934  SCLogDebug("\n>>>> processing chunk 2 size %u <<<<\n", httplen2);
935  FLOWLOCK_WRLOCK(f);
936  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
937  STREAM_TOSERVER | STREAM_EOF, httpbuf2, httplen2);
938  if (r != 0) {
939  printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
940  result = 0;
941  FLOWLOCK_UNLOCK(f);
942  goto end;
943  }
944  FLOWLOCK_UNLOCK(f);
945 
946  http_state = f->alstate;
947  if (http_state == NULL) {
948  printf("no http state: ");
949  result = 0;
950  goto end;
951  }
952 
953  htp_tx_t *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP, http_state, 0);
954  if (tx == NULL) {
955  goto end;
956  }
957 
958  if (tx->request_method == NULL || memcmp(bstr_util_strdup_to_c(tx->request_method), "POST", 4) != 0)
959  {
960  printf("expected method POST, got %s \n", bstr_util_strdup_to_c(tx->request_method));
961  goto end;
962  }
963 
964  if (http_state->files_ts == NULL || http_state->files_ts->tail == NULL ||
965  http_state->files_ts->tail->state != FILE_STATE_CLOSED) {
966  goto end;
967  }
968 
969  if (http_state->files_ts->head == http_state->files_ts->tail)
970  goto end;
971 
972  if (http_state->files_ts->head->next != http_state->files_ts->tail)
973  goto end;
974 
975  if (StreamingBufferCompareRawData(http_state->files_ts->head->sb,
976  (uint8_t *)"filecontent", 11) != 1)
977  {
978  goto end;
979  }
980 
981  if (StreamingBufferCompareRawData(http_state->files_ts->tail->sb,
982  (uint8_t *)"FILECONTENT", 11) != 1)
983  {
984  goto end;
985  }
986 
987  result = 1;
988 end:
989  if (alp_tctx != NULL)
990  AppLayerParserThreadCtxFree(alp_tctx);
992  UTHFreeFlow(f);
993  return result;
994 }
995 
996 /** \test first multipart part contains file but doesn't end in first chunk */
997 static int HTPFileParserTest06(void)
998 {
999  int result = 0;
1000  Flow *f = NULL;
1001  uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
1002  "Host: www.server.lan\r\n"
1003  "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
1004  "Content-Length: 544\r\n"
1005  "\r\n"
1006  "-----------------------------277531038314945\r\n"
1007  "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n"
1008  "Content-Type: image/jpeg\r\n"
1009  "\r\n"
1010  "filecontent\r\n"
1011  "-----------------------------27753103831494";
1012  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1013  uint8_t httpbuf2[] = "5\r\nContent-Disposition: form-data; name=\"uploadfile_1\"; filename=\"somepicture2.jpg\"\r\n"
1014  "Content-Type: image/jpeg\r\n"
1015  "\r\n"
1016  "FILECONTENT\r\n"
1017  "-----------------------------277531038314945--";
1018  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1019 
1020  TcpSession ssn;
1021  HtpState *http_state = NULL;
1023 
1024  memset(&ssn, 0, sizeof(ssn));
1025 
1026  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
1027  if (f == NULL)
1028  goto end;
1029  f->protoctx = &ssn;
1030  f->proto = IPPROTO_TCP;
1031  f->alproto = ALPROTO_HTTP;
1032 
1034 
1035  SCLogDebug("\n>>>> processing chunk 1 size %u <<<<\n", httplen1);
1036  FLOWLOCK_WRLOCK(f);
1037  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
1038  STREAM_TOSERVER | STREAM_START, httpbuf1,
1039  httplen1);
1040  if (r != 0) {
1041  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
1042  result = 0;
1043  FLOWLOCK_UNLOCK(f);
1044  goto end;
1045  }
1046  FLOWLOCK_UNLOCK(f);
1047 
1048  SCLogDebug("\n>>>> processing chunk 2 size %u <<<<\n", httplen2);
1049  FLOWLOCK_WRLOCK(f);
1050  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
1051  STREAM_TOSERVER | STREAM_EOF, httpbuf2, httplen2);
1052  if (r != 0) {
1053  printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
1054  result = 0;
1055  FLOWLOCK_UNLOCK(f);
1056  goto end;
1057  }
1058  FLOWLOCK_UNLOCK(f);
1059 
1060  http_state = f->alstate;
1061  if (http_state == NULL) {
1062  printf("no http state: ");
1063  result = 0;
1064  goto end;
1065  }
1066 
1067  htp_tx_t *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP, http_state, 0);
1068  if (tx == NULL) {
1069  goto end;
1070  }
1071 
1072  if (tx->request_method == NULL || memcmp(bstr_util_strdup_to_c(tx->request_method), "POST", 4) != 0)
1073  {
1074  printf("expected method POST, got %s \n", bstr_util_strdup_to_c(tx->request_method));
1075  goto end;
1076  }
1077 
1078  if (http_state->files_ts == NULL || http_state->files_ts->tail == NULL ||
1079  http_state->files_ts->tail->state != FILE_STATE_CLOSED) {
1080  goto end;
1081  }
1082 
1083  if (http_state->files_ts->head == http_state->files_ts->tail)
1084  goto end;
1085 
1086  if (http_state->files_ts->head->next != http_state->files_ts->tail)
1087  goto end;
1088 
1089  if (StreamingBufferCompareRawData(http_state->files_ts->head->sb,
1090  (uint8_t *)"filecontent", 11) != 1)
1091  {
1092  goto end;
1093  }
1094 
1095  if (StreamingBufferCompareRawData(http_state->files_ts->tail->sb,
1096  (uint8_t *)"FILECONTENT", 11) != 1)
1097  {
1098  goto end;
1099  }
1100 
1101  result = 1;
1102 end:
1103  if (alp_tctx != NULL)
1104  AppLayerParserThreadCtxFree(alp_tctx);
1106  UTHFreeFlow(f);
1107  return result;
1108 }
1109 
1110 /** \test POST, but not multipart */
1111 static int HTPFileParserTest07(void)
1112 {
1113  int result = 0;
1114  Flow *f = NULL;
1115  uint8_t httpbuf1[] = "POST /filename HTTP/1.1\r\n"
1116  "Host: www.server.lan\r\n"
1117  "Content-Length: 11\r\n"
1118  "\r\n";
1119  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1120  uint8_t httpbuf2[] = "FILECONTENT";
1121  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1122 
1123  TcpSession ssn;
1124  HtpState *http_state = NULL;
1126 
1127  memset(&ssn, 0, sizeof(ssn));
1128 
1129  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
1130  if (f == NULL)
1131  goto end;
1132  f->protoctx = &ssn;
1133  f->proto = IPPROTO_TCP;
1134  f->alproto = ALPROTO_HTTP;
1135 
1137 
1138  SCLogDebug("\n>>>> processing chunk 1 size %u <<<<\n", httplen1);
1139  FLOWLOCK_WRLOCK(f);
1140  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
1141  STREAM_TOSERVER | STREAM_START, httpbuf1,
1142  httplen1);
1143  if (r != 0) {
1144  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
1145  result = 0;
1146  FLOWLOCK_UNLOCK(f);
1147  goto end;
1148  }
1149  FLOWLOCK_UNLOCK(f);
1150 
1151  SCLogDebug("\n>>>> processing chunk 2 size %u <<<<\n", httplen2);
1152  FLOWLOCK_WRLOCK(f);
1153  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
1154  STREAM_TOSERVER | STREAM_EOF, httpbuf2, httplen2);
1155  if (r != 0) {
1156  printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
1157  result = 0;
1158  FLOWLOCK_UNLOCK(f);
1159  goto end;
1160  }
1161  FLOWLOCK_UNLOCK(f);
1162 
1163  http_state = f->alstate;
1164  if (http_state == NULL) {
1165  printf("no http state: ");
1166  result = 0;
1167  goto end;
1168  }
1169 
1170  htp_tx_t *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP, http_state, 0);
1171  if (tx == NULL) {
1172  goto end;
1173  }
1174 
1175  if (tx->request_method == NULL || memcmp(bstr_util_strdup_to_c(tx->request_method), "POST", 4) != 0)
1176  {
1177  printf("expected method POST, got %s \n", bstr_util_strdup_to_c(tx->request_method));
1178  goto end;
1179  }
1180 
1181  if (http_state->files_ts == NULL || http_state->files_ts->tail == NULL ||
1182  http_state->files_ts->tail->state != FILE_STATE_CLOSED) {
1183  printf("state != FILE_STATE_CLOSED");
1184  goto end;
1185  }
1186 
1187  if (StreamingBufferCompareRawData(http_state->files_ts->tail->sb,
1188  (uint8_t *)"FILECONTENT", 11) != 1)
1189  {
1190  goto end;
1191  }
1192 
1193  result = 1;
1194 end:
1195  if (alp_tctx != NULL)
1196  AppLayerParserThreadCtxFree(alp_tctx);
1198  UTHFreeFlow(f);
1199  return result;
1200 }
1201 
1202 static int HTPFileParserTest08(void)
1203 {
1204  int result = 0;
1205  Flow *f = NULL;
1206  uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
1207  "Host: www.server.lan\r\n"
1208  "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
1209  "Content-Length: 215\r\n"
1210  "\r\n"
1211  "-----------------------------277531038314945\r\n"
1212  "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n"
1213  "Content-Type: image/jpeg\r\n";
1214 
1215  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1216  uint8_t httpbuf2[] = "filecontent\r\n\r\n"
1217  "-----------------------------277531038314945--";
1218  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1219 
1220  TcpSession ssn;
1222  HtpState *http_state = NULL;
1223  memset(&ssn, 0, sizeof(ssn));
1224 
1225  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
1226  if (f == NULL)
1227  goto end;
1228  f->protoctx = &ssn;
1229  f->proto = IPPROTO_TCP;
1230  f->alproto = ALPROTO_HTTP;
1231 
1233 
1234  SCLogDebug("\n>>>> processing chunk 1 <<<<\n");
1235  FLOWLOCK_WRLOCK(f);
1236  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
1237  STREAM_TOSERVER | STREAM_START, httpbuf1,
1238  httplen1);
1239  if (r != 0) {
1240  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
1241  result = 0;
1242  FLOWLOCK_UNLOCK(f);
1243  goto end;
1244  }
1245  FLOWLOCK_UNLOCK(f);
1246 
1247  SCLogDebug("\n>>>> processing chunk 2 size %u <<<<\n", httplen2);
1248  FLOWLOCK_WRLOCK(f);
1249  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
1250  STREAM_TOSERVER | STREAM_EOF, httpbuf2, httplen2);
1251  if (r != 0) {
1252  printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
1253  result = 0;
1254  FLOWLOCK_UNLOCK(f);
1255  goto end;
1256  }
1257  FLOWLOCK_UNLOCK(f);
1258 
1259  http_state = f->alstate;
1260  if (http_state == NULL) {
1261  printf("no http state: ");
1262  result = 0;
1263  goto end;
1264  }
1265 
1266  FLOWLOCK_WRLOCK(f);
1267  void *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP,f->alstate, 0);
1268  AppLayerDecoderEvents *decoder_events = AppLayerParserGetEventsByTx(IPPROTO_TCP, ALPROTO_HTTP, tx);
1269  if (decoder_events == NULL) {
1270  printf("no app events: ");
1271  FLOWLOCK_UNLOCK(f);
1272  goto end;
1273  }
1274  FLOWLOCK_UNLOCK(f);
1275 
1276  if (decoder_events->cnt != 2) {
1277  printf("expected 2 events: ");
1278  goto end;
1279  }
1280 
1281  result = 1;
1282 end:
1283  if (alp_tctx != NULL)
1284  AppLayerParserThreadCtxFree(alp_tctx);
1286  UTHFreeFlow(f);
1287  return result;
1288 }
1289 
1290 /** \test invalid header: Somereallylongheaderstr: has no value */
1291 static int HTPFileParserTest09(void)
1292 {
1293  int result = 0;
1294  Flow *f = NULL;
1295  uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
1296  "Host: www.server.lan\r\n"
1297  "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
1298  "Content-Length: 337\r\n"
1299  "\r\n";
1300  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1301 
1302  uint8_t httpbuf2[] = "-----------------------------277531038314945\r\n"
1303  "Content-Disposition: form-data; name=\"email\"\r\n"
1304  "\r\n"
1305  "someaddress@somedomain.lan\r\n";
1306  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1307 
1308  uint8_t httpbuf3[] = "-----------------------------277531038314945\r\n"
1309  "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n"
1310  "Somereallylongheaderstr:\r\n"
1311  "\r\n";
1312  uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
1313 
1314  uint8_t httpbuf4[] = "filecontent\r\n"
1315  "-----------------------------277531038314945--";
1316  uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
1317 
1318  TcpSession ssn;
1319  HtpState *http_state = NULL;
1321 
1322  memset(&ssn, 0, sizeof(ssn));
1323 
1324  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
1325  if (f == NULL)
1326  goto end;
1327  f->protoctx = &ssn;
1328  f->proto = IPPROTO_TCP;
1329  f->alproto = ALPROTO_HTTP;
1330 
1332 
1333  SCLogDebug("\n>>>> processing chunk 1 <<<<\n");
1334  FLOWLOCK_WRLOCK(f);
1335  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
1336  STREAM_TOSERVER | STREAM_START, httpbuf1,
1337  httplen1);
1338  if (r != 0) {
1339  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
1340  result = 0;
1341  FLOWLOCK_UNLOCK(f);
1342  goto end;
1343  }
1344  FLOWLOCK_UNLOCK(f);
1345 
1346  SCLogDebug("\n>>>> processing chunk 2 size %u <<<<\n", httplen2);
1347  FLOWLOCK_WRLOCK(f);
1348  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
1349  STREAM_TOSERVER | STREAM_EOF, httpbuf2, httplen2);
1350  if (r != 0) {
1351  printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
1352  result = 0;
1353  FLOWLOCK_UNLOCK(f);
1354  goto end;
1355  }
1356  FLOWLOCK_UNLOCK(f);
1357 
1358  SCLogDebug("\n>>>> processing chunk 3 size %u <<<<\n", httplen3);
1359  FLOWLOCK_WRLOCK(f);
1360  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
1361  STREAM_TOSERVER | STREAM_EOF, httpbuf3, httplen3);
1362  if (r != 0) {
1363  printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
1364  result = 0;
1365  FLOWLOCK_UNLOCK(f);
1366  goto end;
1367  }
1368  FLOWLOCK_UNLOCK(f);
1369 
1370  SCLogDebug("\n>>>> processing chunk 4 size %u <<<<\n", httplen4);
1371  FLOWLOCK_WRLOCK(f);
1372  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
1373  STREAM_TOSERVER | STREAM_EOF, httpbuf4, httplen4);
1374  if (r != 0) {
1375  printf("toserver chunk 4 returned %" PRId32 ", expected 0: ", r);
1376  result = 0;
1377  FLOWLOCK_UNLOCK(f);
1378  goto end;
1379  }
1380  FLOWLOCK_UNLOCK(f);
1381 
1382  http_state = f->alstate;
1383  if (http_state == NULL) {
1384  printf("no http state: ");
1385  result = 0;
1386  goto end;
1387  }
1388 
1389  FLOWLOCK_WRLOCK(f);
1390  void *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP,f->alstate, 0);
1391  AppLayerDecoderEvents *decoder_events = AppLayerParserGetEventsByTx(IPPROTO_TCP, ALPROTO_HTTP, tx);
1392  if (decoder_events == NULL) {
1393  printf("no app events: ");
1394  FLOWLOCK_UNLOCK(f);
1395  goto end;
1396  }
1397  FLOWLOCK_UNLOCK(f);
1398 
1399  if (decoder_events->cnt != 1) {
1400  printf("expected 1 event: ");
1401  goto end;
1402  }
1403 
1404  result = 1;
1405 end:
1406  if (alp_tctx != NULL)
1407  AppLayerParserThreadCtxFree(alp_tctx);
1409  UTHFreeFlow(f);
1410  return result;
1411 }
1412 
1413 /** \test empty entries */
1414 static int HTPFileParserTest10(void)
1415 {
1416  int result = 0;
1417  Flow *f = NULL;
1418  uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
1419  "Host: www.server.lan\r\n"
1420  "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
1421  "Content-Length: 337\r\n"
1422  "\r\n";
1423  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1424 
1425  uint8_t httpbuf2[] = "-----------------------------277531038314945\r\n"
1426  "\r\n";
1427  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1428 
1429  uint8_t httpbuf3[] = "-----------------------------277531038314945\r\n"
1430  "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n"
1431  "Somereallylongheaderstr: with a good value\r\n"
1432  "\r\n";
1433  uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
1434 
1435  uint8_t httpbuf4[] = "filecontent\r\n"
1436  "-----------------------------277531038314945--";
1437  uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
1438 
1439  TcpSession ssn;
1440  HtpState *http_state = NULL;
1442 
1443  memset(&ssn, 0, sizeof(ssn));
1444 
1445  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
1446  if (f == NULL)
1447  goto end;
1448  f->protoctx = &ssn;
1449  f->proto = IPPROTO_TCP;
1450  f->alproto = ALPROTO_HTTP;
1451 
1453 
1454  SCLogDebug("\n>>>> processing chunk 1 <<<<\n");
1455  FLOWLOCK_WRLOCK(f);
1456  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
1457  STREAM_TOSERVER | STREAM_START, httpbuf1,
1458  httplen1);
1459  if (r != 0) {
1460  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
1461  result = 0;
1462  FLOWLOCK_UNLOCK(f);
1463  goto end;
1464  }
1465  FLOWLOCK_UNLOCK(f);
1466 
1467  SCLogDebug("\n>>>> processing chunk 2 size %u <<<<\n", httplen2);
1468  FLOWLOCK_WRLOCK(f);
1469  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
1470  STREAM_TOSERVER | STREAM_EOF, httpbuf2, httplen2);
1471  if (r != 0) {
1472  printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
1473  result = 0;
1474  FLOWLOCK_UNLOCK(f);
1475  goto end;
1476  }
1477  FLOWLOCK_UNLOCK(f);
1478 
1479  SCLogDebug("\n>>>> processing chunk 3 size %u <<<<\n", httplen3);
1480  FLOWLOCK_WRLOCK(f);
1481  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
1482  STREAM_TOSERVER | STREAM_EOF, httpbuf3, httplen3);
1483  if (r != 0) {
1484  printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
1485  result = 0;
1486  FLOWLOCK_UNLOCK(f);
1487  goto end;
1488  }
1489  FLOWLOCK_UNLOCK(f);
1490 
1491  SCLogDebug("\n>>>> processing chunk 4 size %u <<<<\n", httplen4);
1492  FLOWLOCK_WRLOCK(f);
1493  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
1494  STREAM_TOSERVER | STREAM_EOF, httpbuf4, httplen4);
1495  if (r != 0) {
1496  printf("toserver chunk 4 returned %" PRId32 ", expected 0: ", r);
1497  result = 0;
1498  FLOWLOCK_UNLOCK(f);
1499  goto end;
1500  }
1501  FLOWLOCK_UNLOCK(f);
1502 
1503  http_state = f->alstate;
1504  if (http_state == NULL) {
1505  printf("no http state: ");
1506  result = 0;
1507  goto end;
1508  }
1509 
1510  FLOWLOCK_WRLOCK(f);
1511  void *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP,f->alstate, 0);
1512  AppLayerDecoderEvents *decoder_events = AppLayerParserGetEventsByTx(IPPROTO_TCP, ALPROTO_HTTP, tx);
1513  if (decoder_events != NULL) {
1514  printf("app events: ");
1515  FLOWLOCK_UNLOCK(f);
1516  goto end;
1517  }
1518  FLOWLOCK_UNLOCK(f);
1519 
1520  result = 1;
1521 end:
1522  if (alp_tctx != NULL)
1523  AppLayerParserThreadCtxFree(alp_tctx);
1525  UTHFreeFlow(f);
1526  return result;
1527 }
1528 
1529 /** \test filedata cut in two pieces */
1530 static int HTPFileParserTest11(void)
1531 {
1532  int result = 0;
1533  Flow *f = NULL;
1534  uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
1535  "Host: www.server.lan\r\n"
1536  "Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryBRDbP74mBhBxsIdo\r\n"
1537  "Content-Length: 1102\r\n"
1538  "\r\n";
1539  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1540 
1541  uint8_t httpbuf2[] = "------WebKitFormBoundaryBRDbP74mBhBxsIdo\r\n";
1542  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1543 
1544  uint8_t httpbuf3[] = "Content-Disposition: form-data; name=\"PROGRESS_URL\"\r\n"
1545  "\r\n"
1546  "http://somserver.com/progress.php?UPLOAD_IDENTIFIER=XXXXXXXXX.XXXXXXXXXX.XXXXXXXX.XX.X\r\n"
1547  "------WebKitFormBoundaryBRDbP74mBhBxsIdo\r\n"
1548  "Content-Disposition: form-data; name=\"DESTINATION_DIR\"\r\n"
1549  "\r\n"
1550  "10\r\n"
1551  "------WebKitFormBoundaryBRDbP74mBhBxsIdo\r\n"
1552  "Content-Disposition: form-data; name=\"js_enabled\"\r\n"
1553  "\r\n"
1554  "1"
1555  "------WebKitFormBoundaryBRDbP74mBhBxsIdo\r\n"
1556  "Content-Disposition: form-data; name=\"signature\"\r\n"
1557  "\r\n"
1558  "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n"
1559  "------WebKitFormBoundaryBRDbP74mBhBxsIdo\r\n"
1560  "Content-Disposition: form-data; name=\"upload_files\"\r\n"
1561  "\r\n"
1562  "------WebKitFormBoundaryBRDbP74mBhBxsIdo\r\n"
1563  "Content-Disposition: form-data; name=\"terms\"\r\n"
1564  "\r\n"
1565  "1"
1566  "------WebKitFormBoundaryBRDbP74mBhBxsIdo\r\n"
1567  "Content-Disposition: form-data; name=\"file[]\"\r\n"
1568  "\r\n"
1569  "------WebKitFormBoundaryBRDbP74mBhBxsIdo\r\n"
1570  "Content-Disposition: form-data; name=\"description[]\"\r\n"
1571  "\r\n"
1572  "------WebKitFormBoundaryBRDbP74mBhBxsIdo\r\n"
1573  "Content-Disposition: form-data; name=\"upload_file[]\"; filename=\"filename.doc\"\r\n"
1574  "Content-Type: application/msword\r\n"
1575  "\r\n"
1576  "FILE";
1577  uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
1578 
1579  uint8_t httpbuf4[] = "CONTENT\r\n"
1580  "------WebKitFormBoundaryBRDbP74mBhBxsIdo--";
1581  uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
1582 
1583  TcpSession ssn;
1584  HtpState *http_state = NULL;
1586 
1587  memset(&ssn, 0, sizeof(ssn));
1588 
1589  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
1590  if (f == NULL)
1591  goto end;
1592  f->protoctx = &ssn;
1593  f->proto = IPPROTO_TCP;
1594  f->alproto = ALPROTO_HTTP;
1595 
1597 
1598  SCLogDebug("\n>>>> processing chunk 1 <<<<\n");
1599  FLOWLOCK_WRLOCK(f);
1600  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
1601  STREAM_TOSERVER | STREAM_START, httpbuf1,
1602  httplen1);
1603  if (r != 0) {
1604  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
1605  FLOWLOCK_UNLOCK(f);
1606  goto end;
1607  }
1608  FLOWLOCK_UNLOCK(f);
1609 
1610  SCLogDebug("\n>>>> processing chunk 2 size %u <<<<\n", httplen2);
1611  FLOWLOCK_WRLOCK(f);
1612  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP, STREAM_TOSERVER,
1613  httpbuf2, httplen2);
1614  if (r != 0) {
1615  printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
1616  FLOWLOCK_UNLOCK(f);
1617  goto end;
1618  }
1619  FLOWLOCK_UNLOCK(f);
1620 
1621  SCLogDebug("\n>>>> processing chunk 3 size %u <<<<\n", httplen3);
1622  FLOWLOCK_WRLOCK(f);
1623  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP, STREAM_TOSERVER,
1624  httpbuf3, httplen3);
1625  if (r != 0) {
1626  printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
1627  FLOWLOCK_UNLOCK(f);
1628  goto end;
1629  }
1630  FLOWLOCK_UNLOCK(f);
1631 
1632  SCLogDebug("\n>>>> processing chunk 4 size %u <<<<\n", httplen4);
1633  FLOWLOCK_WRLOCK(f);
1634  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
1635  STREAM_TOSERVER | STREAM_EOF, httpbuf4, httplen4);
1636  if (r != 0) {
1637  printf("toserver chunk 4 returned %" PRId32 ", expected 0: ", r);
1638  FLOWLOCK_UNLOCK(f);
1639  goto end;
1640  }
1641  FLOWLOCK_UNLOCK(f);
1642 
1643  http_state = f->alstate;
1644  if (http_state == NULL) {
1645  printf("no http state: ");
1646  goto end;
1647  }
1648 
1649  FLOWLOCK_WRLOCK(f);
1650  void *txtmp = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP,f->alstate, 0);
1651  AppLayerDecoderEvents *decoder_events = AppLayerParserGetEventsByTx(IPPROTO_TCP, ALPROTO_HTTP, txtmp);
1652  if (decoder_events != NULL) {
1653  printf("app events: ");
1654  FLOWLOCK_UNLOCK(f);
1655  goto end;
1656  }
1657  FLOWLOCK_UNLOCK(f);
1658 
1659  htp_tx_t *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP, http_state, 0);
1660  if (tx == NULL) {
1661  goto end;
1662  }
1663 
1664  if (tx->request_method == NULL || memcmp(bstr_util_strdup_to_c(tx->request_method), "POST", 4) != 0)
1665  {
1666  printf("expected method POST, got %s \n", bstr_util_strdup_to_c(tx->request_method));
1667  goto end;
1668  }
1669 
1670  if (http_state->files_ts == NULL || http_state->files_ts->tail == NULL ||
1671  http_state->files_ts->tail->state != FILE_STATE_CLOSED) {
1672  printf("state != FILE_STATE_CLOSED: ");
1673  goto end;
1674  }
1675 
1676  if (StreamingBufferCompareRawData(http_state->files_ts->head->sb,
1677  (uint8_t *)"FILECONTENT", 11) != 1)
1678  {
1679  goto end;
1680  }
1681 
1682  result = 1;
1683 end:
1684  if (alp_tctx != NULL)
1685  AppLayerParserThreadCtxFree(alp_tctx);
1687  UTHFreeFlow(f);
1688  return result;
1689 }
1690 
1691 void AppLayerHtpFileRegisterTests (void);
1692 #include "tests/app-layer-htp-file.c"
1693 #endif /* UNITTESTS */
1694 
1696 {
1697 #ifdef UNITTESTS
1698  UtRegisterTest("HTPFileParserTest01", HTPFileParserTest01);
1699  UtRegisterTest("HTPFileParserTest02", HTPFileParserTest02);
1700  UtRegisterTest("HTPFileParserTest03", HTPFileParserTest03);
1701  UtRegisterTest("HTPFileParserTest04", HTPFileParserTest04);
1702  UtRegisterTest("HTPFileParserTest05", HTPFileParserTest05);
1703  UtRegisterTest("HTPFileParserTest06", HTPFileParserTest06);
1704  UtRegisterTest("HTPFileParserTest07", HTPFileParserTest07);
1705  UtRegisterTest("HTPFileParserTest08", HTPFileParserTest08);
1706  UtRegisterTest("HTPFileParserTest09", HTPFileParserTest09);
1707  UtRegisterTest("HTPFileParserTest10", HTPFileParserTest10);
1708  UtRegisterTest("HTPFileParserTest11", HTPFileParserTest11);
1709 #endif /* UNITTESTS */
1710 }
uint16_t flags
void AppLayerHtpFileRegisterTests(void)
this function registers unit tests for AppLayerHtpFile
int StreamingBufferCompareRawData(const StreamingBuffer *sb, const uint8_t *rawdata, uint32_t rawdata_len)
#define SCLogDebug(...)
Definition: util-debug.h:335
uint16_t flags
uint8_t proto
Definition: flow.h:344
FileContainer * FileContainerAlloc(void)
allocate a FileContainer
Definition: util-file.c:380
HTPCfgDir response
#define FLOWLOCK_UNLOCK(fb)
Definition: flow.h:243
const struct HTPCfgRec_ * cfg
uint64_t FileDataSize(const File *file)
get the size of the file data
Definition: util-file.c:277
int HTPFileClose(HtpState *s, const uint8_t *data, uint32_t data_len, uint8_t flags, uint8_t direction)
Close the file in the flow.
void AppLayerParserThreadCtxFree(AppLayerParserThreadCtx *tctx)
Destroys the app layer parser thread context obtained using AppLayerParserThreadCtxAlloc().
void StreamTcpFreeConfig(char quiet)
Definition: stream-tcp.c:669
#define HTP_FLAG_STORE_FILES_TX_TC
Definition: app-layer-htp.h:70
#define FLOWLOCK_WRLOCK(fb)
Definition: flow.h:240
#define HTP_FLAG_STORE_FILES_TX_TS
Definition: app-layer-htp.h:69
AppLayerDecoderEvents * AppLayerParserGetEventsByTx(uint8_t ipproto, AppProto alproto, void *tx)
#define FILE_STORE
Definition: util-file.h:46
struct File_ * next
Definition: util-file.h:79
#define TRUE
void * protoctx
Definition: flow.h:400
StreamingBuffer * sb
Definition: util-file.h:68
void * alstate
Definition: flow.h:438
Flow * UTHBuildFlow(int family, const char *src, const char *dst, Port sp, Port dp)
Data structure to store app layer decoder events.
void * AppLayerParserGetTx(uint8_t ipproto, AppProto alproto, void *alstate, uint64_t tx_id)
HTPCfgDir request
Data structures and function prototypes for keeping state for the detection engine.
uint32_t file_track_id
#define STREAM_EOF
Definition: stream.h:30
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
#define SCEnter(...)
Definition: util-debug.h:337
void StreamTcpInitConfig(char)
To initialize the stream global configuration data.
Definition: stream-tcp.c:365
int FileSetRange(FileContainer *ffc, uint64_t start, uint64_t end)
Sets the offset range for a file.
Definition: util-file.c:751
#define STREAM_TOCLIENT
Definition: stream.h:32
AppLayerParserThreadCtx * AppLayerParserThreadCtxAlloc(void)
Gets a new app layer protocol&#39;s parser thread context.
#define HTP_FLAG_STORE_FILES_TC
Definition: app-layer-htp.h:68
#define SCReturnInt(x)
Definition: util-debug.h:341
void FilePrune(FileContainer *ffc)
Definition: util-file.c:345
int HTPParseContentRange(bstr *rawvalue, HtpContentRange *range)
int HTPFileOpen(HtpState *s, const uint8_t *filename, uint16_t filename_len, const uint8_t *data, uint32_t data_len, uint64_t txid, uint8_t direction)
Open the file with "filename" and pass the first chunk of data if any.
int HTPFileStoreChunk(HtpState *s, const uint8_t *data, uint32_t data_len, uint8_t direction)
Store a chunk of data in the flow.
FileContainer * files_ts
StreamingBufferConfig sbcfg
FileContainer * files_tc
#define FLOWFILE_NO_STORE_TS
Definition: flow.h:115
#define STREAM_START
Definition: stream.h:29
#define STREAM_TOSERVER
Definition: stream.h:31
FileState state
Definition: util-file.h:67
int FileOpenFileWithId(FileContainer *ffc, const StreamingBufferConfig *sbcfg, uint32_t track_id, const uint8_t *name, uint16_t name_len, const uint8_t *data, uint32_t data_len, uint16_t flags)
Open a new File.
Definition: util-file.c:868
int FileCloseFile(FileContainer *ffc, const uint8_t *data, uint32_t data_len, uint16_t flags)
Close a File.
Definition: util-file.c:963
int FileSetTx(File *ff, uint64_t txid)
Set the TX id for a file.
Definition: util-file.c:523
uint16_t FileFlowToFlags(const Flow *flow, uint8_t direction)
Definition: util-file.c:217
uint64_t store_tx_id
void HTPFileParserRegisterTests(void)
uint8_t len
uint16_t file_flags
Definition: flow.h:381
AppProto alproto
application level protocol
Definition: flow.h:409
int FileAppendData(FileContainer *ffc, const uint8_t *data, uint32_t data_len)
Store/handle a chunk of file data in the File structure The last file in the FileContainer will be us...
Definition: util-file.c:663
#define HTP_FLAG_STORE_FILES_TS
Definition: app-layer-htp.h:67
#define FILE_NOSTORE
Definition: util-file.h:45
#define FLOWFILE_NO_STORE_TC
Definition: flow.h:116
Flow data structure.
Definition: flow.h:325
int HTPFileSetRange(HtpState *s, bstr *rawvalue)
Sets range for a file.
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)