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