suricata
app-layer-htp.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2024 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  * \ingroup httplayer
20  *
21  * @{
22  */
23 
24 /**
25  * \file
26  *
27  * \author Victor Julien <victor@inliniac.net>
28  * \author Gurvinder Singh <gurvindersinghdahiya@gmail.com>
29  * \author Pablo Rincon <pablo.rincon.crespo@gmail.com>
30  * \author Brian Rectanus <brectanu@gmail.com>
31  * \author Anoop Saldanha <anoopsaldanha@gmail.com>
32  *
33  * This file provides a HTTP protocol support for the engine using HTP library.
34  */
35 
36 #include "suricata.h"
37 #include "suricata-common.h"
38 #include "conf.h"
39 #include "decode.h"
40 
41 #include "util-print.h"
42 #include "util-byte.h"
43 
44 #include "stream-tcp.h"
45 
46 #include "app-layer-protos.h"
47 #include "app-layer-parser.h"
48 
49 #include "app-layer.h"
50 #include "app-layer-detect-proto.h"
51 #include "app-layer-frames.h"
52 #include "app-layer-htp.h"
53 #include "app-layer-htp-body.h"
54 #include "app-layer-htp-file.h"
55 #include "app-layer-htp-libhtp.h"
56 #include "app-layer-htp-xff.h"
57 #include "app-layer-htp-range.h"
58 #include "app-layer-htp-mem.h"
59 
60 #include "util-debug.h"
61 #include "util-misc.h"
62 
63 #include "util-unittest.h"
64 #include "util-unittest-helper.h"
65 #include "flow-util.h"
66 
67 #include "detect-engine.h"
68 #include "detect-engine-build.h"
69 #include "detect-engine-state.h"
70 #include "detect-parse.h"
71 
72 #include "util-memcmp.h"
73 #include "util-random.h"
74 #include "util-validate.h"
75 
76 //#define PRINT
77 
78 /** Fast lookup tree (radix) for the various HTP configurations */
79 static struct HTPConfigTree {
80  SCRadix4Tree ipv4;
81  SCRadix6Tree ipv6;
82 } cfgtree = {
85 };
86 SCRadix4Config htp_radix4_cfg = { NULL, NULL };
87 SCRadix6Config htp_radix6_cfg = { NULL, NULL };
88 
89 /** List of HTP configurations. */
90 static HTPCfgRec cfglist;
91 
93 
94 /** Limit to the number of libhtp messages that can be handled */
95 #define HTP_MAX_MESSAGES 512
96 
97 SC_ATOMIC_DECLARE(uint32_t, htp_config_flags);
98 
99 #ifdef DEBUG
100 static SCMutex htp_state_mem_lock = SCMUTEX_INITIALIZER;
101 static uint64_t htp_state_memuse = 0;
102 static uint64_t htp_state_memcnt = 0;
103 #endif
104 
106  { "UNKNOWN_ERROR", HTP_LOG_CODE_UNKNOWN },
107  { "GZIP_DECOMPRESSION_FAILED", HTP_LOG_CODE_GZIP_DECOMPRESSION_FAILED },
108  { "REQUEST_FIELD_MISSING_COLON", HTP_LOG_CODE_REQUEST_FIELD_MISSING_COLON },
109  { "RESPONSE_FIELD_MISSING_COLON", HTP_LOG_CODE_RESPONSE_FIELD_MISSING_COLON },
110  { "INVALID_REQUEST_CHUNK_LEN", HTP_LOG_CODE_INVALID_REQUEST_CHUNK_LEN },
111  { "INVALID_RESPONSE_CHUNK_LEN", HTP_LOG_CODE_INVALID_RESPONSE_CHUNK_LEN },
112  { "INVALID_TRANSFER_ENCODING_VALUE_IN_REQUEST",
114  { "INVALID_TRANSFER_ENCODING_VALUE_IN_RESPONSE",
116  { "INVALID_CONTENT_LENGTH_FIELD_IN_REQUEST",
118  { "INVALID_CONTENT_LENGTH_FIELD_IN_RESPONSE",
120  { "DUPLICATE_CONTENT_LENGTH_FIELD_IN_REQUEST",
122  { "DUPLICATE_CONTENT_LENGTH_FIELD_IN_RESPONSE",
124  { "100_CONTINUE_ALREADY_SEEN", HTP_LOG_CODE_CONTINUE_ALREADY_SEEN },
125  { "UNABLE_TO_MATCH_RESPONSE_TO_REQUEST", HTP_LOG_CODE_UNABLE_TO_MATCH_RESPONSE_TO_REQUEST },
126  { "INVALID_SERVER_PORT_IN_REQUEST", HTP_LOG_CODE_INVALID_SERVER_PORT_IN_REQUEST },
127  { "INVALID_AUTHORITY_PORT", HTP_LOG_CODE_INVALID_AUTHORITY_PORT },
128  { "REQUEST_HEADER_INVALID", HTP_LOG_CODE_REQUEST_HEADER_INVALID },
129  { "RESPONSE_HEADER_INVALID", HTP_LOG_CODE_RESPONSE_HEADER_INVALID },
130  { "MISSING_HOST_HEADER", HTP_LOG_CODE_MISSING_HOST_HEADER },
131  { "HOST_HEADER_AMBIGUOUS", HTP_LOG_CODE_HOST_HEADER_AMBIGUOUS },
132  { "INVALID_REQUEST_FIELD_FOLDING", HTP_LOG_CODE_INVALID_REQUEST_FIELD_FOLDING },
133  { "INVALID_RESPONSE_FIELD_FOLDING", HTP_LOG_CODE_INVALID_RESPONSE_FIELD_FOLDING },
134  { "REQUEST_FIELD_TOO_LONG", HTP_LOG_CODE_REQUEST_FIELD_TOO_LONG },
135  { "RESPONSE_FIELD_TOO_LONG", HTP_LOG_CODE_RESPONSE_FIELD_TOO_LONG },
136  { "FILE_NAME_TOO_LONG", HTP_LOG_CODE_FILE_NAME_TOO_LONG },
137  { "REQUEST_LINE_INVALID", HTP_LOG_CODE_REQUEST_LINE_INVALID },
138  { "REQUEST_BODY_UNEXPECTED", HTP_LOG_CODE_REQUEST_BODY_UNEXPECTED },
139  { "REQUEST_SERVER_PORT_TCP_PORT_MISMATCH", HTP_LOG_CODE_REQUEST_SERVER_PORT_TCP_PORT_MISMATCH },
140  { "REQUEST_URI_HOST_INVALID", HTP_LOG_CODE_URI_HOST_INVALID },
141  { "REQUEST_HEADER_HOST_INVALID", HTP_LOG_CODE_HEADER_HOST_INVALID },
142  { "REQUEST_AUTH_UNRECOGNIZED", HTP_LOG_CODE_AUTH_UNRECOGNIZED },
143  { "REQUEST_HEADER_REPETITION", HTP_LOG_CODE_REQUEST_HEADER_REPETITION },
144  { "RESPONSE_HEADER_REPETITION", HTP_LOG_CODE_RESPONSE_HEADER_REPETITION },
145  { "DOUBLE_ENCODED_URI", HTP_LOG_CODE_DOUBLE_ENCODED_URI },
146  { "URI_DELIM_NON_COMPLIANT", HTP_LOG_CODE_URI_DELIM_NON_COMPLIANT },
147  { "METHOD_DELIM_NON_COMPLIANT", HTP_LOG_CODE_METHOD_DELIM_NON_COMPLIANT },
148  { "REQUEST_LINE_LEADING_WHITESPACE", HTP_LOG_CODE_REQUEST_LINE_LEADING_WHITESPACE },
149  { "TOO_MANY_ENCODING_LAYERS", HTP_LOG_CODE_TOO_MANY_ENCODING_LAYERS },
150  { "ABNORMAL_CE_HEADER", HTP_LOG_CODE_ABNORMAL_CE_HEADER },
151  { "RESPONSE_MULTIPART_BYTERANGES", HTP_LOG_CODE_RESPONSE_MULTIPART_BYTERANGES },
152  { "RESPONSE_ABNORMAL_TRANSFER_ENCODING", HTP_LOG_CODE_RESPONSE_ABNORMAL_TRANSFER_ENCODING },
153  { "RESPONSE_CHUNKED_OLD_PROTO", HTP_LOG_CODE_RESPONSE_CHUNKED_OLD_PROTO },
154  { "RESPONSE_INVALID_PROTOCOL", HTP_LOG_CODE_RESPONSE_INVALID_PROTOCOL },
155  { "RESPONSE_INVALID_STATUS", HTP_LOG_CODE_RESPONSE_INVALID_STATUS },
156  { "REQUEST_LINE_INCOMPLETE", HTP_LOG_CODE_REQUEST_LINE_INCOMPLETE },
157 
158  { "LZMA_MEMLIMIT_REACHED", HTP_LOG_CODE_LZMA_MEMLIMIT_REACHED },
159  { "COMPRESSION_BOMB", HTP_LOG_CODE_COMPRESSION_BOMB },
160 
161  { "RANGE_INVALID", HTTP_DECODER_EVENT_RANGE_INVALID },
162  { "REQUEST_CHUNK_EXTENSION", HTTP_DECODER_EVENT_REQUEST_CHUNK_EXTENSION },
163  { "REQUEST_LINE_MISSING_PROTOCOL", HTTP_DECODER_EVENT_REQUEST_LINE_MISSING_PROTOCOL },
164 
165  { "REQUEST_TOO_MANY_HEADERS", HTTP_DECODER_EVENT_REQUEST_TOO_MANY_HEADERS },
166  { "RESPONSE_TOO_MANY_HEADERS", HTTP_DECODER_EVENT_RESPONSE_TOO_MANY_HEADERS },
167 
168  /* suricata warnings/errors */
169  { "MULTIPART_GENERIC_ERROR", HTTP_DECODER_EVENT_MULTIPART_GENERIC_ERROR },
170  { "MULTIPART_NO_FILEDATA", HTTP_DECODER_EVENT_MULTIPART_NO_FILEDATA },
171  { "MULTIPART_INVALID_HEADER", HTTP_DECODER_EVENT_MULTIPART_INVALID_HEADER },
172 
173  { "TOO_MANY_WARNINGS", HTTP_DECODER_EVENT_TOO_MANY_WARNINGS },
174  { "FAILED_PROTOCOL_CHANGE", HTTP_DECODER_EVENT_FAILED_PROTOCOL_CHANGE },
175 
176  { NULL, -1 },
177 };
178 
179 /* app-layer-frame-documentation tag start: HttpFrameTypes */
183 };
184 
186  {
187  "request",
189  },
190  {
191  "response",
193  },
194  { NULL, -1 },
195 };
196 /* app-layer-frame-documentation tag end: HttpFrameTypes */
197 
198 static int HTTPGetFrameIdByName(const char *frame_name)
199 {
200  int id = SCMapEnumNameToValue(frame_name, http_frame_table);
201  if (id < 0) {
202  return -1;
203  }
204  return id;
205 }
206 
207 static const char *HTTPGetFrameNameById(const uint8_t frame_id)
208 {
209  const char *name = SCMapEnumValueToName(frame_id, http_frame_table);
210  return name;
211 }
212 
213 static void *HTPStateGetTx(void *alstate, uint64_t tx_id);
214 static int HTPStateGetAlstateProgress(void *tx, uint8_t direction);
215 static uint64_t HTPStateGetTxCnt(void *alstate);
216 #ifdef UNITTESTS
217 static void HTPParserRegisterTests(void);
218 #endif
219 
220 static inline uint64_t HtpGetActiveRequestTxID(HtpState *s)
221 {
222  uint64_t id = HTPStateGetTxCnt(s);
223  BUG_ON(id == 0);
224  return id - 1;
225 }
226 
227 static inline uint64_t HtpGetActiveResponseTxID(HtpState *s)
228 {
229  return s->transaction_cnt;
230 }
231 
232 #ifdef DEBUG
233 /**
234  * \internal
235  *
236  * \brief Lookup the HTP personality string from the numeric personality.
237  *
238  * \todo This needs to be a libhtp function.
239  */
240 static const char *HTPLookupPersonalityString(int p)
241 {
242 #define CASE_HTP_PERSONALITY_STRING(p) \
243  case HTP_SERVER_PERSONALITY_##p: \
244  return #p
245 
246  switch (p) {
247  CASE_HTP_PERSONALITY_STRING(MINIMAL);
248  CASE_HTP_PERSONALITY_STRING(GENERIC);
249  CASE_HTP_PERSONALITY_STRING(IDS);
250  CASE_HTP_PERSONALITY_STRING(IIS_4_0);
251  CASE_HTP_PERSONALITY_STRING(IIS_5_0);
252  CASE_HTP_PERSONALITY_STRING(IIS_5_1);
253  CASE_HTP_PERSONALITY_STRING(IIS_6_0);
254  CASE_HTP_PERSONALITY_STRING(IIS_7_0);
255  CASE_HTP_PERSONALITY_STRING(IIS_7_5);
256  CASE_HTP_PERSONALITY_STRING(APACHE_2);
257  }
258 
259  return NULL;
260 }
261 #endif /* DEBUG */
262 
263 /**
264  * \internal
265  *
266  * \brief Lookup the numeric HTP personality from a string.
267  *
268  * \todo This needs to be a libhtp function.
269  */
270 static int HTPLookupPersonality(const char *str)
271 {
272 #define IF_HTP_PERSONALITY_NUM(p) \
273  if (strcasecmp(#p, str) == 0) \
274  return HTP_SERVER_PERSONALITY_##p
275 
276  IF_HTP_PERSONALITY_NUM(MINIMAL);
277  IF_HTP_PERSONALITY_NUM(GENERIC);
279  IF_HTP_PERSONALITY_NUM(IIS_4_0);
280  IF_HTP_PERSONALITY_NUM(IIS_5_0);
281  IF_HTP_PERSONALITY_NUM(IIS_5_1);
282  IF_HTP_PERSONALITY_NUM(IIS_6_0);
283  IF_HTP_PERSONALITY_NUM(IIS_7_0);
284  IF_HTP_PERSONALITY_NUM(IIS_7_5);
285  IF_HTP_PERSONALITY_NUM(APACHE_2);
286  if (strcasecmp("TOMCAT_6_0", str) == 0) {
287  SCLogError("Personality %s no "
288  "longer supported by libhtp.",
289  str);
290  return -1;
291  } else if ((strcasecmp("APACHE", str) == 0) ||
292  (strcasecmp("APACHE_2_2", str) == 0))
293  {
294  SCLogWarning("Personality %s no "
295  "longer supported by libhtp, failing back to "
296  "Apache2 personality.",
297  str);
299  }
300 
301  return -1;
302 }
303 
304 static void HTPSetEvent(HtpState *s, HtpTxUserData *htud,
305  const uint8_t dir, const uint8_t e)
306 {
307  SCLogDebug("setting event %u", e);
308 
309  if (htud) {
310  AppLayerDecoderEventsSetEventRaw(&htud->tx_data.events, e);
311  s->events++;
312  return;
313  }
314 
315  const uint64_t tx_id = (dir == STREAM_TOSERVER) ?
316  HtpGetActiveRequestTxID(s) : HtpGetActiveResponseTxID(s);
317 
318  htp_tx_t *tx = HTPStateGetTx(s, tx_id);
319  if (tx == NULL && tx_id > 0)
320  tx = HTPStateGetTx(s, tx_id - 1);
321  if (tx != NULL) {
322  htud = (HtpTxUserData *) htp_tx_get_user_data(tx);
323  if (htud != NULL) {
324  AppLayerDecoderEventsSetEventRaw(&htud->tx_data.events, e);
325  s->events++;
326  return;
327  }
328  }
329  SCLogDebug("couldn't set event %u", e);
330 }
331 
332 /** \brief Function to allocates the HTTP state memory and also creates the HTTP
333  * connection parser to be used by the HTP library
334  */
335 static void *HTPStateAlloc(void *orig_state, AppProto proto_orig)
336 {
337  SCEnter();
338 
339  HtpState *s = HTPMalloc(sizeof(HtpState));
340  if (unlikely(s == NULL)) {
341  SCReturnPtr(NULL, "void");
342  }
343 
344  memset(s, 0x00, sizeof(HtpState));
345 
346 #ifdef DEBUG
347  SCMutexLock(&htp_state_mem_lock);
348  htp_state_memcnt++;
349  htp_state_memuse += sizeof(HtpState);
350  SCLogDebug("htp memory %"PRIu64" (%"PRIu64")", htp_state_memuse, htp_state_memcnt);
351  SCMutexUnlock(&htp_state_mem_lock);
352 #endif
353 
354  SCReturnPtr((void *)s, "void");
355 }
356 
357 static void HtpTxUserDataFree(HtpState *state, HtpTxUserData *htud)
358 {
359  if (likely(htud)) {
360  HtpBodyFree(&htud->request_body);
361  HtpBodyFree(&htud->response_body);
362  bstr_free(htud->request_uri_normalized);
363  if (htud->request_headers_raw)
365  if (htud->response_headers_raw)
368  if (htud->mime_state)
369  SCMimeStateFree(htud->mime_state);
370  if (htud->tx_data.de_state != NULL) {
371  DetectEngineStateFree(htud->tx_data.de_state);
372  }
373  if (htud->file_range) {
374  HTPFileCloseHandleRange(&htp_sbcfg, &htud->files_tc, 0, htud->file_range, NULL, 0);
376  }
379  HTPFree(htud, sizeof(HtpTxUserData));
380  }
381 }
382 
383 /** \brief Function to frees the HTTP state memory and also frees the HTTP
384  * connection parser memory which was used by the HTP library
385  */
386 void HTPStateFree(void *state)
387 {
388  SCEnter();
389 
390  HtpState *s = (HtpState *)state;
391  if (s == NULL) {
392  SCReturn;
393  }
394 
395  /* free the connection parser memory used by HTP library */
396  if (s->connp != NULL) {
397  SCLogDebug("freeing HTP state");
398 
399  uint64_t tx_id;
400  uint64_t total_txs = HTPStateGetTxCnt(state);
401  /* free the list of body chunks */
402  if (s->conn != NULL) {
403  for (tx_id = s->tx_freed; tx_id < total_txs; tx_id++) {
404  htp_tx_t *tx = HTPStateGetTx(s, tx_id);
405  if (tx != NULL) {
406  HtpTxUserData *htud = (HtpTxUserData *) htp_tx_get_user_data(tx);
407  HtpTxUserDataFree(s, htud);
408  htp_tx_set_user_data(tx, NULL);
409  }
410  }
411  }
412  htp_connp_destroy_all(s->connp);
413  }
414 
415  HTPFree(s, sizeof(HtpState));
416 
417 #ifdef DEBUG
418  SCMutexLock(&htp_state_mem_lock);
419  htp_state_memcnt--;
420  htp_state_memuse -= sizeof(HtpState);
421  SCLogDebug("htp memory %"PRIu64" (%"PRIu64")", htp_state_memuse, htp_state_memcnt);
422  SCMutexUnlock(&htp_state_mem_lock);
423 #endif
424 
425  SCReturn;
426 }
427 
428 /**
429  * \brief HTP transaction cleanup callback
430  *
431  * \warning We cannot actually free the transactions here. It seems that
432  * HTP only accepts freeing of transactions in the response callback.
433  */
434 static void HTPStateTransactionFree(void *state, uint64_t id)
435 {
436  SCEnter();
437 
438  HtpState *s = (HtpState *)state;
439 
440  SCLogDebug("state %p, id %"PRIu64, s, id);
441 
442  htp_tx_t *tx = HTPStateGetTx(s, id);
443  if (tx != NULL) {
444  /* This will remove obsolete body chunks */
445  HtpTxUserData *htud = (HtpTxUserData *) htp_tx_get_user_data(tx);
446  HtpTxUserDataFree(s, htud);
447  htp_tx_set_user_data(tx, NULL);
448 
449  /* hack: even if libhtp considers the tx incomplete, we want to
450  * free it here. htp_tx_destroy however, will refuse to do this.
451  * As htp_tx_destroy_incomplete isn't available in the public API,
452  * we hack around it here. */
457  }
458  // replaces tx in the s->conn->transactions list by NULL
459  htp_tx_destroy(tx);
460  }
461  s->tx_freed += htp_connp_tx_freed(s->connp);
462 }
463 
464 /**
465  * \brief Sets a flag that informs the HTP app layer that some module in the
466  * engine needs the http request body data.
467  * \initonly
468  */
470 {
471  SCEnter();
472 
473  SC_ATOMIC_OR(htp_config_flags, HTP_REQUIRE_REQUEST_BODY);
474  SCReturn;
475 }
476 
477 /**
478  * \brief Sets a flag that informs the HTP app layer that some module in the
479  * engine needs the http request body data.
480  * \initonly
481  */
483 {
484  SCEnter();
485 
486  SC_ATOMIC_OR(htp_config_flags, HTP_REQUIRE_RESPONSE_BODY);
487  SCReturn;
488 }
489 
490 /**
491  * \brief Sets a flag that informs the HTP app layer that some module in the
492  * engine needs the http request file.
493  *
494  * \initonly
495  */
497 {
498  SCEnter();
501 
502  SC_ATOMIC_OR(htp_config_flags, HTP_REQUIRE_REQUEST_FILE);
503  SCReturn;
504 }
505 
506 static void AppLayerHtpSetStreamDepthFlag(void *tx, const uint8_t flags)
507 {
508  HtpTxUserData *tx_ud = (HtpTxUserData *) htp_tx_get_user_data((htp_tx_t *)tx);
509  if (tx_ud) {
510  SCLogDebug("setting HTP_STREAM_DEPTH_SET, flags %02x", flags);
511  if (flags & STREAM_TOCLIENT) {
512  tx_ud->tcflags |= HTP_STREAM_DEPTH_SET;
513  } else {
514  tx_ud->tsflags |= HTP_STREAM_DEPTH_SET;
515  }
516  }
517 }
518 
519 static bool AppLayerHtpCheckDepth(const HTPCfgDir *cfg, HtpBody *body, uint8_t flags)
520 {
521  SCLogDebug("cfg->body_limit %u stream_depth %u body->content_len_so_far %" PRIu64,
523  if (flags & HTP_STREAM_DEPTH_SET) {
524  uint32_t stream_depth = FileReassemblyDepth();
525  if (body->content_len_so_far < (uint64_t)stream_depth || stream_depth == 0) {
526  SCLogDebug("true");
527  return true;
528  }
529  } else {
530  if (cfg->body_limit == 0 || body->content_len_so_far < cfg->body_limit) {
531  return true;
532  }
533  }
534  SCLogDebug("false");
535  return false;
536 }
537 
538 static uint32_t AppLayerHtpComputeChunkLength(uint64_t content_len_so_far, uint32_t body_limit,
539  uint32_t stream_depth, uint8_t flags, uint32_t data_len)
540 {
541  uint32_t chunk_len = 0;
542  if (!(flags & HTP_STREAM_DEPTH_SET) && body_limit > 0 &&
543  (content_len_so_far < (uint64_t)body_limit) &&
544  (content_len_so_far + (uint64_t)data_len) > body_limit)
545  {
546  chunk_len = (uint32_t)(body_limit - content_len_so_far);
547  } else if ((flags & HTP_STREAM_DEPTH_SET) && stream_depth > 0 &&
548  (content_len_so_far < (uint64_t)stream_depth) &&
549  (content_len_so_far + (uint64_t)data_len) > stream_depth)
550  {
551  chunk_len = (uint32_t)(stream_depth - content_len_so_far);
552  }
553  SCLogDebug("len %u", chunk_len);
554  return (chunk_len == 0 ? data_len : chunk_len);
555 }
556 
557 /* below error messages updated up to libhtp 0.5.7 (git 379632278b38b9a792183694a4febb9e0dbd1e7a) */
558 struct {
559  const char *msg;
560  uint8_t de;
561 } htp_errors[] = {
562  { "GZip decompressor: inflateInit2 failed", HTP_LOG_CODE_GZIP_DECOMPRESSION_FAILED },
563  { "Request field invalid: colon missing", HTP_LOG_CODE_REQUEST_FIELD_MISSING_COLON },
564  { "Response field invalid: missing colon", HTP_LOG_CODE_RESPONSE_FIELD_MISSING_COLON },
565  { "Request chunk encoding: Invalid chunk length", HTP_LOG_CODE_INVALID_REQUEST_CHUNK_LEN },
566  { "Response chunk encoding: Invalid chunk length", HTP_LOG_CODE_INVALID_RESPONSE_CHUNK_LEN },
567  /* { "Invalid T-E value in request",
568  HTP_LOG_CODE_INVALID_TRANSFER_ENCODING_VALUE_IN_REQUEST}, <- tx flag
569  HTP_FLAGS_REQUEST_INVALID_T_E { "Invalid T-E value in response",
570  HTP_LOG_CODE_INVALID_TRANSFER_ENCODING_VALUE_IN_RESPONSE}, <- nothing to replace it */
571  /* { "Invalid C-L field in request",
572  HTP_LOG_CODE_INVALID_CONTENT_LENGTH_FIELD_IN_REQUEST}, <- tx flag
573  HTP_FLAGS_REQUEST_INVALID_C_L */
574  { "Invalid C-L field in response", HTP_LOG_CODE_INVALID_CONTENT_LENGTH_FIELD_IN_RESPONSE },
575  { "Already seen 100-Continue", HTP_LOG_CODE_CONTINUE_ALREADY_SEEN },
576  { "Unable to match response to request", HTP_LOG_CODE_UNABLE_TO_MATCH_RESPONSE_TO_REQUEST },
577  { "Invalid server port information in request", HTP_LOG_CODE_INVALID_SERVER_PORT_IN_REQUEST },
578  /* { "Invalid authority port", HTP_LOG_CODE_INVALID_AUTHORITY_PORT}, htp no longer
579  returns this error */
580  { "Request buffer over", HTP_LOG_CODE_REQUEST_FIELD_TOO_LONG },
581  { "Response buffer over", HTP_LOG_CODE_RESPONSE_FIELD_TOO_LONG },
582  { "C-T multipart/byteranges in responses not supported",
584  { "Compression bomb:", HTP_LOG_CODE_COMPRESSION_BOMB },
585 };
586 
587 struct {
588  const char *msg;
589  uint8_t de;
590 } htp_warnings[] = {
591  { "GZip decompressor:", HTP_LOG_CODE_GZIP_DECOMPRESSION_FAILED },
592  { "Request field invalid", HTP_LOG_CODE_REQUEST_HEADER_INVALID },
593  { "Response field invalid", HTP_LOG_CODE_RESPONSE_HEADER_INVALID },
594  { "Request header name is not a token", HTP_LOG_CODE_REQUEST_HEADER_INVALID },
595  { "Response header name is not a token", HTP_LOG_CODE_RESPONSE_HEADER_INVALID },
596  /* { "Host information in request headers required by HTTP/1.1",
597  HTP_LOG_CODE_MISSING_HOST_HEADER}, <- tx flag HTP_FLAGS_HOST_MISSING { "Host
598  information ambiguous", HTP_LOG_CODE_HOST_HEADER_AMBIGUOUS}, <- tx flag
599  HTP_FLAGS_HOST_AMBIGUOUS */
600  { "Invalid request field folding", HTP_LOG_CODE_INVALID_REQUEST_FIELD_FOLDING },
601  { "Invalid response field folding", HTP_LOG_CODE_INVALID_RESPONSE_FIELD_FOLDING },
602  /* line is now: htp_log(connp, HTP_LOG_MARK, HTP_LOG_ERROR, 0, "Request server port=%d number
603  * differs from the actual TCP port=%d", port, connp->conn->server_port); luckily, "Request
604  * server port=" is unique */
605  /* { "Request server port number differs from the actual TCP port",
606  HTP_LOG_CODE_REQUEST_SERVER_PORT_TCP_PORT_MISMATCH}, */
607  { "Request server port=", HTP_LOG_CODE_REQUEST_SERVER_PORT_TCP_PORT_MISMATCH },
608  { "Request line: URI contains non-compliant delimiter", HTP_LOG_CODE_URI_DELIM_NON_COMPLIANT },
609  { "Request line: non-compliant delimiter between Method and URI",
611  { "Request line: leading whitespace", HTP_LOG_CODE_REQUEST_LINE_LEADING_WHITESPACE },
612  { "Too many response content encoding layers", HTP_LOG_CODE_TOO_MANY_ENCODING_LAYERS },
613  { "C-E gzip has abnormal value", HTP_LOG_CODE_ABNORMAL_CE_HEADER },
614  { "C-E deflate has abnormal value", HTP_LOG_CODE_ABNORMAL_CE_HEADER },
615  { "C-E unknown setting", HTP_LOG_CODE_ABNORMAL_CE_HEADER },
616  { "Excessive request header repetitions", HTP_LOG_CODE_REQUEST_HEADER_REPETITION },
617  { "Excessive response header repetitions", HTP_LOG_CODE_RESPONSE_HEADER_REPETITION },
618  { "Transfer-encoding has abnormal chunked value",
620  { "Chunked transfer-encoding on HTTP/0.9 or HTTP/1.0",
622  { "Invalid response line: invalid protocol", HTP_LOG_CODE_RESPONSE_INVALID_PROTOCOL },
623  { "Invalid response line: invalid response status", HTP_LOG_CODE_RESPONSE_INVALID_STATUS },
624  { "Request line incomplete", HTP_LOG_CODE_REQUEST_LINE_INCOMPLETE },
625  { "Unexpected request body", HTP_LOG_CODE_REQUEST_BODY_UNEXPECTED },
626  { "LZMA decompressor: memory limit reached", HTP_LOG_CODE_LZMA_MEMLIMIT_REACHED },
627  { "Ambiguous request C-L value", HTP_LOG_CODE_DUPLICATE_CONTENT_LENGTH_FIELD_IN_REQUEST },
628  { "Ambiguous response C-L value", HTP_LOG_CODE_DUPLICATE_CONTENT_LENGTH_FIELD_IN_RESPONSE },
629  { "Request chunk extension", HTTP_DECODER_EVENT_REQUEST_CHUNK_EXTENSION },
630  { "Request line: missing protocol", HTTP_DECODER_EVENT_REQUEST_LINE_MISSING_PROTOCOL },
631  { "Too many request headers", HTTP_DECODER_EVENT_REQUEST_TOO_MANY_HEADERS },
632  { "Too many response headers", HTTP_DECODER_EVENT_RESPONSE_TOO_MANY_HEADERS },
633 };
634 
635 #define HTP_ERROR_MAX (sizeof(htp_errors) / sizeof(htp_errors[0]))
636 #define HTP_WARNING_MAX (sizeof(htp_warnings) / sizeof(htp_warnings[0]))
637 
638 /**
639  * \internal
640  *
641  * \brief Get the warning id for the warning msg.
642  *
643  * \param msg warning message
644  *
645  * \retval id the id or 0 in case of not found
646  */
647 static uint8_t HTPHandleWarningGetId(const char *msg)
648 {
649  SCLogDebug("received warning \"%s\"", msg);
650  size_t idx;
651  for (idx = 0; idx < HTP_WARNING_MAX; idx++) {
652  if (strncmp(htp_warnings[idx].msg, msg,
653  strlen(htp_warnings[idx].msg)) == 0)
654  {
655  return htp_warnings[idx].de;
656  }
657  }
658 
659  return 0;
660 }
661 
662 /**
663  * \internal
664  *
665  * \brief Get the error id for the error msg.
666  *
667  * \param msg error message
668  *
669  * \retval id the id or 0 in case of not found
670  */
671 static uint8_t HTPHandleErrorGetId(const char *msg)
672 {
673  SCLogDebug("received error \"%s\"", msg);
674 
675  size_t idx;
676  for (idx = 0; idx < HTP_ERROR_MAX; idx++) {
677  if (strncmp(htp_errors[idx].msg, msg,
678  strlen(htp_errors[idx].msg)) == 0)
679  {
680  return htp_errors[idx].de;
681  }
682  }
683 
684  return 0;
685 }
686 
687 /**
688  * \internal
689  *
690  * \brief Check state for errors, warnings and add any as events
691  *
692  * \param s state
693  * \param dir direction: STREAM_TOSERVER or STREAM_TOCLIENT
694  */
695 static void HTPHandleError(HtpState *s, const uint8_t dir)
696 {
697  if (s == NULL || s->conn == NULL ||
698  s->conn->messages == NULL) {
699  return;
700  }
701 
702  size_t size = htp_list_size(s->conn->messages);
703  size_t msg;
704  if(size >= HTP_MAX_MESSAGES) {
706  //only once per HtpState
707  HTPSetEvent(s, NULL, dir, HTTP_DECODER_EVENT_TOO_MANY_WARNINGS);
709  //too noisy in fuzzing
710  //DEBUG_VALIDATE_BUG_ON("Too many libhtp messages");
711  }
712  // ignore further messages
713  return;
714  }
715 
716  for (msg = s->htp_messages_offset; msg < size; msg++) {
717  htp_log_t *log = htp_list_get(s->conn->messages, msg);
718  if (log == NULL)
719  continue;
720 
721  HtpTxUserData *htud = NULL;
722  htp_tx_t *tx = log->tx; // will be NULL in <=0.5.9
723  if (tx != NULL)
724  htud = (HtpTxUserData *) htp_tx_get_user_data(tx);
725 
726  SCLogDebug("message %s", log->msg);
727 
728  uint8_t id = HTPHandleErrorGetId(log->msg);
729  if (id == 0) {
730  id = HTPHandleWarningGetId(log->msg);
731  if (id == 0)
733  }
734 
735  if (id > 0) {
736  HTPSetEvent(s, htud, dir, id);
737  }
738  }
739  s->htp_messages_offset = (uint16_t)msg;
740  SCLogDebug("s->htp_messages_offset %u", s->htp_messages_offset);
741 }
742 
743 static inline void HTPErrorCheckTxRequestFlags(HtpState *s, const htp_tx_t *tx)
744 {
745 #ifdef DEBUG
746  BUG_ON(s == NULL || tx == NULL);
747 #endif
751  HtpTxUserData *htud = (HtpTxUserData *) htp_tx_get_user_data(tx);
752  if (htud == NULL)
753  return;
754 
756  HTPSetEvent(s, htud, STREAM_TOSERVER,
759  HTPSetEvent(
760  s, htud, STREAM_TOSERVER, HTP_LOG_CODE_INVALID_CONTENT_LENGTH_FIELD_IN_REQUEST);
762  HTPSetEvent(s, htud, STREAM_TOSERVER, HTP_LOG_CODE_MISSING_HOST_HEADER);
764  HTPSetEvent(s, htud, STREAM_TOSERVER, HTP_LOG_CODE_HOST_HEADER_AMBIGUOUS);
766  HTPSetEvent(s, htud, STREAM_TOSERVER, HTP_LOG_CODE_URI_HOST_INVALID);
768  HTPSetEvent(s, htud, STREAM_TOSERVER, HTP_LOG_CODE_HEADER_HOST_INVALID);
769  }
771  HtpTxUserData *htud = (HtpTxUserData *) htp_tx_get_user_data(tx);
772  if (htud == NULL)
773  return;
774  HTPSetEvent(s, htud, STREAM_TOSERVER, HTP_LOG_CODE_AUTH_UNRECOGNIZED);
775  }
777  (htp_tx_request_protocol_number(tx) == HTP_PROTOCOL_INVALID ||
778  htp_tx_request_protocol_number(tx) == HTP_PROTOCOL_UNKNOWN)) {
779  HtpTxUserData *htud = (HtpTxUserData *) htp_tx_get_user_data(tx);
780  if (htud == NULL)
781  return;
782  HTPSetEvent(s, htud, STREAM_TOSERVER, HTP_LOG_CODE_REQUEST_BODY_UNEXPECTED);
783  }
784 }
785 
786 static int Setup(Flow *f, HtpState *hstate)
787 {
788  /* store flow ref in state so callbacks can access it */
789  hstate->f = f;
790 
791  HTPCfgRec *htp_cfg_rec = &cfglist;
792  htp_cfg_t *htp = cfglist.cfg; /* Default to the global HTP config */
793  void *user_data = NULL;
794 
795  if (FLOW_IS_IPV4(f)) {
796  SCLogDebug("Looking up HTP config for ipv4 %08x", *GET_IPV4_DST_ADDR_PTR(f));
798  &cfgtree.ipv4, (uint8_t *)GET_IPV4_DST_ADDR_PTR(f), &user_data);
799  }
800  else if (FLOW_IS_IPV6(f)) {
801  SCLogDebug("Looking up HTP config for ipv6");
802  (void)SCRadix6TreeFindBestMatch(&cfgtree.ipv6, (uint8_t *)GET_IPV6_DST_ADDR(f), &user_data);
803  }
804  else {
805  SCLogError("unknown address family, bug!");
806  goto error;
807  }
808 
809  if (user_data != NULL) {
810  htp_cfg_rec = user_data;
811  htp = htp_cfg_rec->cfg;
812  SCLogDebug("LIBHTP using config: %p", htp);
813  } else {
814  SCLogDebug("Using default HTP config: %p", htp);
815  }
816 
817  if (NULL == htp) {
818 #ifdef DEBUG_VALIDATION
819  BUG_ON(htp == NULL);
820 #endif
821  /* should never happen if HTPConfigure is properly invoked */
822  goto error;
823  }
824 
825  hstate->connp = htp_connp_create(htp);
826  if (hstate->connp == NULL) {
827  goto error;
828  }
829 
830  hstate->conn = htp_connp_get_connection(hstate->connp);
831 
832  htp_connp_set_user_data(hstate->connp, (void *)hstate);
833  hstate->cfg = htp_cfg_rec;
834 
835  SCLogDebug("New hstate->connp %p", hstate->connp);
836 
837  struct timeval tv = { SCTIME_SECS(f->startts), SCTIME_USECS(f->startts) };
838  htp_connp_open(hstate->connp, NULL, f->sp, NULL, f->dp, &tv);
839 
841  htp_cfg_rec->request.inspect_min_size);
843  htp_cfg_rec->response.inspect_min_size);
844  return 0;
845 error:
846  return -1;
847 }
848 
849 /**
850  * \brief Function to handle the reassembled data from client and feed it to
851  * the HTP library to process it.
852  *
853  * \param flow Pointer to the flow the data belong to
854  * \param htp_state Pointer the state in which the parsed value to be stored
855  * \param pstate Application layer parser state for this session
856  *
857  * \retval On success returns 1 or on failure returns -1.
858  */
859 static AppLayerResult HTPHandleRequestData(Flow *f, void *htp_state, AppLayerParserState *pstate,
860  StreamSlice stream_slice, void *local_data)
861 {
862  SCEnter();
863  int ret = 0;
864  HtpState *hstate = (HtpState *)htp_state;
865 
866  /* On the first invocation, create the connection parser structure to
867  * be used by HTP library. This is looked up via IP in the radix
868  * tree. Failing that, the default HTP config is used.
869  */
870  if (NULL == hstate->conn) {
871  if (Setup(f, hstate) != 0) {
873  }
874  }
875  DEBUG_VALIDATE_BUG_ON(hstate->connp == NULL);
876  hstate->slice = &stream_slice;
877 
878  const uint8_t *input = StreamSliceGetData(&stream_slice);
879  uint32_t input_len = StreamSliceGetDataLen(&stream_slice);
880 
881  htp_time_t ts = { SCTIME_SECS(f->startts), SCTIME_USECS(f->startts) };
882  /* pass the new data to the htp parser */
883  if (input_len > 0) {
884  const int r = htp_connp_req_data(hstate->connp, &ts, input, input_len);
885  switch (r) {
887  ret = -1;
888  break;
889  default:
890  break;
891  }
892  HTPHandleError(hstate, STREAM_TOSERVER);
893  }
894 
895  /* if the TCP connection is closed, then close the HTTP connection */
897  !(hstate->flags & HTP_FLAG_STATE_CLOSED_TS))
898  {
899  htp_connp_req_close(hstate->connp, &ts);
900  hstate->flags |= HTP_FLAG_STATE_CLOSED_TS;
901  SCLogDebug("stream eof encountered, closing htp handle for ts");
902  }
903 
904  SCLogDebug("hstate->connp %p", hstate->connp);
905  hstate->slice = NULL;
906 
907  if (ret < 0) {
909  }
911 }
912 
913 /**
914  * \brief Function to handle the reassembled data from server and feed it to
915  * the HTP library to process it.
916  *
917  * \param flow Pointer to the flow the data belong to
918  * \param htp_state Pointer the state in which the parsed value to be stored
919  * \param pstate Application layer parser state for this session
920  * \param input Pointer the received HTTP server data
921  * \param input_len Length in bytes of the received data
922  * \param output Pointer to the output (not used in this function)
923  *
924  * \retval On success returns 1 or on failure returns -1
925  */
926 static AppLayerResult HTPHandleResponseData(Flow *f, void *htp_state, AppLayerParserState *pstate,
927  StreamSlice stream_slice, void *local_data)
928 {
929  SCEnter();
930  int ret = 0;
931  HtpState *hstate = (HtpState *)htp_state;
932 
933  const uint8_t *input = StreamSliceGetData(&stream_slice);
934  uint32_t input_len = StreamSliceGetDataLen(&stream_slice);
935 
936  /* On the first invocation, create the connection parser structure to
937  * be used by HTP library. This is looked up via IP in the radix
938  * tree. Failing that, the default HTP config is used.
939  */
940  if (NULL == hstate->conn) {
941  if (Setup(f, hstate) != 0) {
943  }
944  }
945  DEBUG_VALIDATE_BUG_ON(hstate->connp == NULL);
946  hstate->slice = &stream_slice;
947 
948  htp_time_t ts = { SCTIME_SECS(f->startts), SCTIME_USECS(f->startts) };
949  htp_tx_t *tx = NULL;
950  uint32_t consumed = 0;
951  if (input_len > 0) {
952  const int r = htp_connp_res_data(hstate->connp, &ts, input, input_len);
953  switch (r) {
955  ret = -1;
956  break;
958  tx = htp_connp_get_out_tx(hstate->connp);
959  if (tx != NULL && htp_tx_response_status_number(tx) == 101) {
960  const htp_header_t *h = htp_tx_response_header(tx, "Upgrade");
961  if (h == NULL) {
962  break;
963  }
964  uint16_t dp = 0;
965  if (htp_tx_request_port_number(tx) != -1) {
966  dp = (uint16_t)htp_tx_request_port_number(tx);
967  }
968  consumed = (uint32_t)htp_connp_res_data_consumed(hstate->connp);
969  if (bstr_cmp_c(htp_header_value(h), "h2c") == 0) {
971  // if HTTP2 is disabled, keep the HTP_STREAM_STATE_TUNNEL mode
972  break;
973  }
974  hstate->slice = NULL;
975  if (!AppLayerRequestProtocolChange(hstate->f, dp, ALPROTO_HTTP2)) {
976  HTPSetEvent(hstate, NULL, STREAM_TOCLIENT,
978  }
979  // During HTTP2 upgrade, we may consume the HTTP1 part of the data
980  // and we need to parser the remaining part with HTTP2
981  if (consumed > 0 && consumed < input_len) {
982  SCReturnStruct(APP_LAYER_INCOMPLETE(consumed, input_len - consumed));
983  }
985  } else if (bstr_cmp_c_nocase(htp_header_value(h), "WebSocket") == 0) {
987  // if WS is disabled, keep the HTP_STREAM_STATE_TUNNEL mode
988  break;
989  }
990  hstate->slice = NULL;
992  HTPSetEvent(hstate, NULL, STREAM_TOCLIENT,
994  }
995  // During WS upgrade, we may consume the HTTP1 part of the data
996  // and we need to parser the remaining part with WS
997  if (consumed > 0 && consumed < input_len) {
998  SCReturnStruct(APP_LAYER_INCOMPLETE(consumed, input_len - consumed));
999  }
1001  }
1002  }
1003  break;
1004  default:
1005  break;
1006  }
1007  HTPHandleError(hstate, STREAM_TOCLIENT);
1008  }
1009 
1010  /* if we the TCP connection is closed, then close the HTTP connection */
1012  !(hstate->flags & HTP_FLAG_STATE_CLOSED_TC))
1013  {
1014  htp_connp_close(hstate->connp, &ts);
1015  hstate->flags |= HTP_FLAG_STATE_CLOSED_TC;
1016  }
1017 
1018  SCLogDebug("hstate->connp %p", hstate->connp);
1019  hstate->slice = NULL;
1020 
1021  if (ret < 0) {
1023  }
1025 }
1026 
1027 /**
1028  * \param name /Lowercase/ version of the variable name
1029  */
1030 static int HTTPParseContentDispositionHeader(const uint8_t *name, size_t name_len,
1031  const uint8_t *data, size_t len, uint8_t const **retptr, size_t *retlen)
1032 {
1033 #ifdef PRINT
1034  printf("DATA START: \n");
1035  PrintRawDataFp(stdout, data, len);
1036  printf("DATA END: \n");
1037 #endif
1038  size_t x;
1039  int quote = 0;
1040 
1041  for (x = 0; x < len; x++) {
1042  if (!(isspace(data[x])))
1043  break;
1044  }
1045 
1046  if (x >= len)
1047  return 0;
1048 
1049  const uint8_t *line = data + x;
1050  size_t line_len = len-x;
1051  size_t offset = 0;
1052 #ifdef PRINT
1053  printf("LINE START: \n");
1054  PrintRawDataFp(stdout, line, line_len);
1055  printf("LINE END: \n");
1056 #endif
1057  for (x = 0 ; x < line_len; x++) {
1058  if (x > 0) {
1059  if (line[x - 1] != '\\' && line[x] == '\"') {
1060  quote++;
1061  }
1062 
1063  if (((line[x - 1] != '\\' && line[x] == ';') || ((x + 1) == line_len)) && (quote == 0 || quote % 2 == 0)) {
1064  const uint8_t *token = line + offset;
1065  size_t token_len = x - offset;
1066 
1067  if ((x + 1) == line_len) {
1068  token_len++;
1069  }
1070 
1071  offset = x + 1;
1072 
1073  while (offset < line_len && isspace(line[offset])) {
1074  x++;
1075  offset++;
1076  }
1077 #ifdef PRINT
1078  printf("TOKEN START: \n");
1079  PrintRawDataFp(stdout, token, token_len);
1080  printf("TOKEN END: \n");
1081 #endif
1082  if (token_len > name_len) {
1083  if (name == NULL || SCMemcmpLowercase(name, token, name_len) == 0) {
1084  const uint8_t *value = token + name_len;
1085  size_t value_len = token_len - name_len;
1086 
1087  if (value[0] == '\"') {
1088  value++;
1089  value_len--;
1090  }
1091  if (value[value_len-1] == '\"') {
1092  value_len--;
1093  }
1094 #ifdef PRINT
1095  printf("VALUE START: \n");
1096  PrintRawDataFp(stdout, value, value_len);
1097  printf("VALUE END: \n");
1098 #endif
1099  *retptr = value;
1100  *retlen = value_len;
1101  return 1;
1102  }
1103  }
1104  }
1105  }
1106  }
1107 
1108  return 0;
1109 }
1110 
1111 /**
1112  * \brief setup multipart parsing: extract boundary and store it
1113  *
1114  * \param d HTTP transaction
1115  * \param htud transaction userdata
1116  *
1117  * \retval 1 ok, multipart set up
1118  * \retval 0 ok, not multipart though
1119  * \retval -1 error: problem with the boundary
1120  *
1121  * If the request contains a multipart message, this function will
1122  * set the HTP_BOUNDARY_SET in the transaction.
1123  */
1124 static int HtpRequestBodySetupMultipart(const htp_tx_t *tx, HtpTxUserData *htud)
1125 {
1126  const htp_header_t *h = htp_tx_request_header(tx, "Content-Type");
1127  if (h != NULL && htp_header_value_len(h) > 0) {
1128  htud->mime_state =
1129  SCMimeStateInit(htp_header_value_ptr(h), (uint32_t)htp_header_value_len(h));
1130  if (htud->mime_state) {
1131  htud->tsflags |= HTP_BOUNDARY_SET;
1132  SCReturnInt(1);
1133  }
1134  }
1135  SCReturnInt(0);
1136 }
1137 
1138 /**
1139  * \brief Create a single buffer from the HtpBodyChunks in our list
1140  *
1141  * \param htud transaction user data
1142  * \param chunks_buffers pointer to pass back the buffer to the caller
1143  * \param chunks_buffer_len pointer to pass back the buffer length to the caller
1144  */
1145 static void HtpRequestBodyReassemble(HtpTxUserData *htud,
1146  const uint8_t **chunks_buffer, uint32_t *chunks_buffer_len)
1147 {
1149  chunks_buffer, chunks_buffer_len,
1150  htud->request_body.body_parsed);
1151 }
1152 
1153 static void FlagDetectStateNewFile(HtpTxUserData *tx, int dir)
1154 {
1155  SCEnter();
1156  if (tx && tx->tx_data.de_state) {
1157  if (dir == STREAM_TOSERVER) {
1158  SCLogDebug("DETECT_ENGINE_STATE_FLAG_FILE_NEW set");
1159  tx->tx_data.de_state->dir_state[0].flags |= DETECT_ENGINE_STATE_FLAG_FILE_NEW;
1160  } else if (dir == STREAM_TOCLIENT) {
1161  SCLogDebug("DETECT_ENGINE_STATE_FLAG_FILE_NEW set");
1162  tx->tx_data.de_state->dir_state[1].flags |= DETECT_ENGINE_STATE_FLAG_FILE_NEW;
1163  }
1164  }
1165 }
1166 
1167 static int HtpRequestBodyHandleMultipart(HtpState *hstate, HtpTxUserData *htud, const void *tx,
1168  const uint8_t *chunks_buffer, uint32_t chunks_buffer_len, bool eof)
1169 {
1170 #ifdef PRINT
1171  printf("CHUNK START: \n");
1172  PrintRawDataFp(stdout, chunks_buffer, chunks_buffer_len);
1173  printf("CHUNK END: \n");
1174 #endif
1175 
1176  // libhtp will not call us back too late
1177  // should libhtp send a callback eof for 0 chunked ?
1179  STREAM_TOSERVER) >= HTP_REQUEST_PROGRESS_COMPLETE);
1180 
1181  const uint8_t *cur_buf = chunks_buffer;
1182  uint32_t cur_buf_len = chunks_buffer_len;
1183 
1184  if (eof) {
1185  // abrupt end of connection
1186  if (htud->tsflags & HTP_FILENAME_SET && !(htud->tsflags & HTP_DONTSTORE)) {
1187  /* we currently only handle multipart for ts. When we support it for tc,
1188  * we will need to supply right direction */
1189  HTPFileClose(htud, cur_buf, cur_buf_len, FILE_TRUNCATED, STREAM_TOSERVER);
1190  }
1191  htud->tsflags &= ~HTP_FILENAME_SET;
1192  goto end;
1193  }
1194 
1195  uint32_t consumed;
1196  uint32_t warnings;
1197  int result = 0;
1198  const uint8_t *filename = NULL;
1199  uint16_t filename_len = 0;
1200 
1201  // keep parsing mime and use callbacks when needed
1202  while (cur_buf_len > 0) {
1203  MimeParserResult r =
1204  SCMimeParse(htud->mime_state, cur_buf, cur_buf_len, &consumed, &warnings);
1205  DEBUG_VALIDATE_BUG_ON(consumed > cur_buf_len);
1206  htud->request_body.body_parsed += consumed;
1207  if (warnings) {
1208  if (warnings & MIME_EVENT_FLAG_INVALID_HEADER) {
1209  HTPSetEvent(
1210  hstate, htud, STREAM_TOSERVER, HTTP_DECODER_EVENT_MULTIPART_INVALID_HEADER);
1211  }
1212  if (warnings & MIME_EVENT_FLAG_NO_FILEDATA) {
1213  HTPSetEvent(
1214  hstate, htud, STREAM_TOSERVER, HTTP_DECODER_EVENT_MULTIPART_NO_FILEDATA);
1215  }
1216  }
1217  switch (r) {
1218  case MimeNeedsMore:
1219  // there is not enough data, wait for more next time
1220  goto end;
1221  case MimeFileOpen:
1222  // get filename owned by mime state
1223  SCMimeStateGetFilename(htud->mime_state, &filename, &filename_len);
1224  if (filename_len > 0) {
1225  htud->tsflags |= HTP_FILENAME_SET;
1226  htud->tsflags &= ~HTP_DONTSTORE;
1227  result = HTPFileOpen(
1228  hstate, htud, filename, filename_len, NULL, 0, STREAM_TOSERVER);
1229  if (result == -1) {
1230  goto end;
1231  } else if (result == -2) {
1232  htud->tsflags |= HTP_DONTSTORE;
1233  }
1234  FlagDetectStateNewFile(htud, STREAM_TOSERVER);
1235  }
1236  break;
1237  case MimeFileChunk:
1238  if (htud->tsflags & HTP_FILENAME_SET && !(htud->tsflags & HTP_DONTSTORE)) {
1239  result = HTPFileStoreChunk(htud, cur_buf, consumed, STREAM_TOSERVER);
1240  if (result == -1) {
1241  goto end;
1242  } else if (result == -2) {
1243  /* we know for sure we're not storing the file */
1244  htud->tsflags |= HTP_DONTSTORE;
1245  }
1246  }
1247  break;
1248  case MimeFileClose:
1249  if (htud->tsflags & HTP_FILENAME_SET && !(htud->tsflags & HTP_DONTSTORE)) {
1250  uint32_t lastsize = consumed;
1251  if (lastsize > 0 && cur_buf[lastsize - 1] == '\n') {
1252  lastsize--;
1253  if (lastsize > 0 && cur_buf[lastsize - 1] == '\r') {
1254  lastsize--;
1255  }
1256  }
1257  HTPFileClose(htud, cur_buf, lastsize, 0, STREAM_TOSERVER);
1258  }
1259  htud->tsflags &= ~HTP_FILENAME_SET;
1260  break;
1261  }
1262  cur_buf += consumed;
1263  cur_buf_len -= consumed;
1264  }
1265 
1266 end:
1267  SCLogDebug("htud->request_body.body_parsed %"PRIu64, htud->request_body.body_parsed);
1268  return 0;
1269 }
1270 
1271 /** \internal
1272  * \brief Handle POST or PUT, no multipart body data
1273  */
1274 static int HtpRequestBodyHandlePOSTorPUT(HtpState *hstate, HtpTxUserData *htud, const htp_tx_t *tx,
1275  const uint8_t *data, uint32_t data_len)
1276 {
1277  int result = 0;
1278 
1279  /* see if we need to open the file */
1280  if (!(htud->tsflags & HTP_FILENAME_SET))
1281  {
1282  uint8_t *filename = NULL;
1283  size_t filename_len = 0;
1284 
1285  /* get the name */
1286  if (tx->parsed_uri != NULL && tx->parsed_uri->path != NULL) {
1287  filename = (uint8_t *)bstr_ptr(tx->parsed_uri->path);
1288  filename_len = bstr_len(tx->parsed_uri->path);
1289  }
1290 
1291  if (filename != NULL) {
1292  if (filename_len > SC_FILENAME_MAX) {
1293  // explicitly truncate the file name if too long
1294  filename_len = SC_FILENAME_MAX;
1295  HTPSetEvent(hstate, htud, STREAM_TOSERVER, HTP_LOG_CODE_REQUEST_LINE_INVALID);
1296  }
1297  result = HTPFileOpen(hstate, htud, filename, (uint16_t)filename_len, data, data_len,
1298  STREAM_TOSERVER);
1299  if (result == -1) {
1300  goto end;
1301  } else if (result == -2) {
1302  htud->tsflags |= HTP_DONTSTORE;
1303  } else {
1304  FlagDetectStateNewFile(htud, STREAM_TOSERVER);
1305  htud->tsflags |= HTP_FILENAME_SET;
1306  htud->tsflags &= ~HTP_DONTSTORE;
1307  }
1308  }
1309  }
1310  else
1311  {
1312  /* otherwise, just store the data */
1313 
1314  if (!(htud->tsflags & HTP_DONTSTORE)) {
1315  result = HTPFileStoreChunk(htud, data, data_len, STREAM_TOSERVER);
1316  if (result == -1) {
1317  goto end;
1318  } else if (result == -2) {
1319  /* we know for sure we're not storing the file */
1320  htud->tsflags |= HTP_DONTSTORE;
1321  }
1322  }
1323  }
1324 
1325  return 0;
1326 end:
1327  return -1;
1328 }
1329 
1330 static int HtpResponseBodyHandle(HtpState *hstate, HtpTxUserData *htud, const htp_tx_t *tx,
1331  const uint8_t *data, uint32_t data_len)
1332 {
1333  SCEnter();
1334 
1335  int result = 0;
1336 
1337  /* see if we need to open the file
1338  * we check for htp_tx_response_line(tx) in case of junk
1339  * interpreted as body before response line
1340  */
1341  if (!(htud->tcflags & HTP_FILENAME_SET)) {
1342  SCLogDebug("setting up file name");
1343 
1344  const uint8_t *filename = NULL;
1345  size_t filename_len = 0;
1346 
1347  /* try Content-Disposition header first */
1348  const htp_header_t *h = htp_tx_response_header(tx, "Content-Disposition");
1349  if (h != NULL && htp_header_value_len(h) > 0) {
1350  /* parse content-disposition */
1351  (void)HTTPParseContentDispositionHeader((uint8_t *)"filename=", 9,
1352  (uint8_t *)htp_header_value_ptr(h), htp_header_value_len(h), &filename,
1353  &filename_len);
1354  }
1355 
1356  /* fall back to name from the uri */
1357  if (filename == NULL) {
1358  /* get the name */
1359  if (tx->parsed_uri != NULL && tx->parsed_uri->path != NULL) {
1360  filename = (uint8_t *)bstr_ptr(tx->parsed_uri->path);
1361  filename_len = bstr_len(tx->parsed_uri->path);
1362  }
1363  }
1364 
1365  if (filename != NULL) {
1366  // set range if present
1367  const htp_header_t *h_content_range = htp_tx_response_header(tx, "content-range");
1368  if (filename_len > SC_FILENAME_MAX) {
1369  // explicitly truncate the file name if too long
1370  filename_len = SC_FILENAME_MAX;
1371  HTPSetEvent(hstate, htud, STREAM_TOSERVER, HTP_LOG_CODE_REQUEST_LINE_INVALID);
1372  }
1373  if (h_content_range != NULL) {
1374  result = HTPFileOpenWithRange(hstate, htud, filename, (uint16_t)filename_len, data,
1375  data_len, tx, h_content_range->value, htud);
1376  } else {
1377  result = HTPFileOpen(hstate, htud, filename, (uint16_t)filename_len, data, data_len,
1378  STREAM_TOCLIENT);
1379  }
1380  SCLogDebug("result %d", result);
1381  if (result == -1) {
1382  goto end;
1383  } else if (result == -2) {
1384  htud->tcflags |= HTP_DONTSTORE;
1385  } else {
1386  FlagDetectStateNewFile(htud, STREAM_TOCLIENT);
1387  htud->tcflags |= HTP_FILENAME_SET;
1388  htud->tcflags &= ~HTP_DONTSTORE;
1389  }
1390  }
1391  } else {
1392  /* otherwise, just store the data */
1393 
1394  if (!(htud->tcflags & HTP_DONTSTORE)) {
1395  result = HTPFileStoreChunk(htud, data, data_len, STREAM_TOCLIENT);
1396  SCLogDebug("result %d", result);
1397  if (result == -1) {
1398  goto end;
1399  } else if (result == -2) {
1400  /* we know for sure we're not storing the file */
1401  htud->tcflags |= HTP_DONTSTORE;
1402  }
1403  }
1404  }
1405 
1406  htud->response_body.body_parsed += data_len;
1407  return 0;
1408 end:
1409  return -1;
1410 }
1411 
1412 /**
1413  * \brief Function callback to append chunks for Requests
1414  * \param d pointer to the htp_tx_data_t structure (a chunk from htp lib)
1415  * \retval int HTP_STATUS_OK if all goes well
1416  */
1417 static int HTPCallbackRequestBodyData(htp_tx_data_t *d)
1418 {
1419  SCEnter();
1420 
1421  if (!(SC_ATOMIC_GET(htp_config_flags) & HTP_REQUIRE_REQUEST_BODY))
1423 
1424  if (htp_tx_data_len(d) == 0)
1426 
1427 #ifdef PRINT
1428  printf("HTPBODY START: \n");
1429  PrintRawDataFp(stdout, (uint8_t *)htp_tx_data_data(d), htp_tx_data_len(d));
1430  printf("HTPBODY END: \n");
1431 #endif
1432 
1433  HtpState *hstate = htp_connp_get_user_data(d->tx->connp);
1434  if (hstate == NULL) {
1436  }
1437 
1438  SCLogDebug("New request body data available at %p -> %p -> %p, bodylen "
1439  "%" PRIu32 "",
1440  hstate, d, htp_tx_data_data(d), (uint32_t)htp_tx_data_len(d));
1441 
1442  HtpTxUserData *tx_ud = (HtpTxUserData *) htp_tx_get_user_data(d->tx);
1443  if (tx_ud == NULL) {
1445  }
1446  tx_ud->tx_data.updated_ts = true;
1447  SCTxDataUpdateFileFlags(&tx_ud->tx_data, hstate->state_data.file_flags);
1448 
1449  if (!tx_ud->response_body_init) {
1450  tx_ud->response_body_init = 1;
1451 
1452  if (d->htp_tx_request_method_number(tx) == HTP_METHOD_POST) {
1453  SCLogDebug("POST");
1454  int r = HtpRequestBodySetupMultipart(htp_tx_data_tx(d), tx_ud);
1455  if (r == 1) {
1457  } else if (r == 0) {
1459  SCLogDebug("not multipart");
1460  }
1461  } else if (d->htp_tx_request_method_number(tx) == HTP_METHOD_PUT) {
1463  }
1464  }
1465 
1466  /* see if we can get rid of htp body chunks */
1467  HtpBodyPrune(hstate, &tx_ud->request_body, STREAM_TOSERVER);
1468 
1469  SCLogDebug("tx_ud->request_body.content_len_so_far %"PRIu64, tx_ud->request_body.content_len_so_far);
1470  SCLogDebug("hstate->cfg->request.body_limit %u", hstate->cfg->request.body_limit);
1471 
1472  /* within limits, add the body chunk to the state. */
1473  if (AppLayerHtpCheckDepth(&hstate->cfg->request, &tx_ud->request_body, tx_ud->tsflags)) {
1474  uint32_t stream_depth = FileReassemblyDepth();
1475  uint32_t len = AppLayerHtpComputeChunkLength(tx_ud->request_body.content_len_so_far,
1476  hstate->cfg->request.body_limit, stream_depth, tx_ud->tsflags,
1477  (uint32_t)htp_tx_data_len(d));
1478  BUG_ON(len > (uint32_t)htp_tx_data_len(d));
1479 
1481 
1482  const uint8_t *chunks_buffer = NULL;
1483  uint32_t chunks_buffer_len = 0;
1484 
1486  /* multi-part body handling starts here */
1487  if (!(tx_ud->tsflags & HTP_BOUNDARY_SET)) {
1488  goto end;
1489  }
1490 
1491  HtpRequestBodyReassemble(tx_ud, &chunks_buffer, &chunks_buffer_len);
1492  if (chunks_buffer == NULL) {
1493  goto end;
1494  }
1495 #ifdef PRINT
1496  printf("REASSCHUNK START: \n");
1497  PrintRawDataFp(stdout, chunks_buffer, chunks_buffer_len);
1498  printf("REASSCHUNK END: \n");
1499 #endif
1500 
1501  HtpRequestBodyHandleMultipart(hstate, tx_ud, htp_tx_data_tx(d), chunks_buffer,
1502  chunks_buffer_len, (htp_tx_data_data(d) == NULL && htp_tx_data_len(d) == 0));
1503 
1504  } else if (tx_ud->request_body_type == HTP_BODY_REQUEST_POST ||
1506  HtpRequestBodyHandlePOSTorPUT(
1507  hstate, tx_ud, htp_tx_data_tx(d), (uint8_t *)htp_tx_data_data(d), len);
1508  }
1509 
1510  } else {
1511  if (tx_ud->tsflags & HTP_FILENAME_SET) {
1512  SCLogDebug("closing file that was being stored");
1513  (void)HTPFileClose(tx_ud, NULL, 0, FILE_TRUNCATED, STREAM_TOSERVER);
1514  tx_ud->tsflags &= ~HTP_FILENAME_SET;
1515  }
1516  }
1517 
1518 end:
1519  if (hstate->conn != NULL) {
1520  SCLogDebug("checking body size %" PRIu64 " against inspect limit %u (cur %" PRIu64
1521  ", last %" PRIu64 ")",
1523  (uint64_t)htp_conn_request_data_counter(hstate->conn),
1524  hstate->last_request_data_stamp);
1525 
1526  /* if we reach the inspect_min_size we'll trigger inspection,
1527  * so make sure that raw stream is also inspected. Set the
1528  * data to be used to the amount of raw bytes we've seen to
1529  * get here. */
1530  if (tx_ud->request_body.body_inspected == 0 &&
1532  if ((uint64_t)htp_conn_request_data_counter(hstate->conn) >
1533  hstate->last_request_data_stamp &&
1534  (uint64_t)htp_conn_request_data_counter(hstate->conn) -
1535  hstate->last_request_data_stamp <
1536  (uint64_t)UINT_MAX) {
1537  const uint32_t data_size =
1538  (uint32_t)((uint64_t)htp_conn_request_data_counter(hstate->conn) -
1539  hstate->last_request_data_stamp);
1540  const uint32_t depth = MIN(data_size, hstate->cfg->request.inspect_min_size);
1541 
1542  /* body still in progress, but due to min inspect size we need to inspect now */
1543  StreamTcpReassemblySetMinInspectDepth(hstate->f->protoctx, STREAM_TOSERVER, depth);
1544  AppLayerParserTriggerRawStreamReassembly(hstate->f, STREAM_TOSERVER);
1545  }
1546  /* after the start of the body, disable the depth logic */
1547  } else if (tx_ud->request_body.body_inspected > 0) {
1548  StreamTcpReassemblySetMinInspectDepth(hstate->f->protoctx, STREAM_TOSERVER, 0);
1549  }
1550  }
1552 }
1553 
1554 /**
1555  * \brief Function callback to append chunks for Responses
1556  * \param d pointer to the htp_tx_data_t structure (a chunk from htp lib)
1557  * \retval int HTP_STATUS_OK if all goes well
1558  */
1559 static int HTPCallbackResponseBodyData(htp_tx_data_t *d)
1560 {
1561  SCEnter();
1562 
1563  if (!(SC_ATOMIC_GET(htp_config_flags) & HTP_REQUIRE_RESPONSE_BODY))
1565 
1566  if (htp_tx_data_len(d) == 0)
1568 
1569  HtpState *hstate = htp_connp_get_user_data(d->tx->connp);
1570  if (hstate == NULL) {
1572  }
1573 
1574  SCLogDebug("New response body data available at %p -> %p -> %p, bodylen "
1575  "%" PRIu32 "",
1576  hstate, d, htp_tx_data_data(d), (uint32_t)htp_tx_data_len(d));
1577 
1578  HtpTxUserData *tx_ud = (HtpTxUserData *) htp_tx_get_user_data(d->tx);
1579  if (tx_ud == NULL) {
1581  }
1582  tx_ud->tx_data.updated_tc = true;
1583  SCTxDataUpdateFileFlags(&tx_ud->tx_data, hstate->state_data.file_flags);
1584  if (!tx_ud->request_body_init) {
1585  tx_ud->request_body_init = 1;
1586  }
1587 
1588  /* see if we can get rid of htp body chunks */
1589  HtpBodyPrune(hstate, &tx_ud->response_body, STREAM_TOCLIENT);
1590 
1591  SCLogDebug("tx_ud->response_body.content_len_so_far %"PRIu64, tx_ud->response_body.content_len_so_far);
1592  SCLogDebug("hstate->cfg->response.body_limit %u", hstate->cfg->response.body_limit);
1593 
1594  /* within limits, add the body chunk to the state. */
1595  if (AppLayerHtpCheckDepth(&hstate->cfg->response, &tx_ud->response_body, tx_ud->tcflags)) {
1596  uint32_t stream_depth = FileReassemblyDepth();
1597  uint32_t len = AppLayerHtpComputeChunkLength(tx_ud->response_body.content_len_so_far,
1598  hstate->cfg->response.body_limit, stream_depth, tx_ud->tcflags,
1599  (uint32_t)htp_tx_data_len(d));
1600  BUG_ON(len > (uint32_t)htp_tx_data_len(d));
1601 
1603 
1604  HtpResponseBodyHandle(
1605  hstate, tx_ud, htp_tx_data_tx(d), (uint8_t *)htp_tx_data_data(d), len);
1606  } else {
1607  if (tx_ud->tcflags & HTP_FILENAME_SET) {
1608  SCLogDebug("closing file that was being stored");
1609  (void)HTPFileClose(tx_ud, NULL, 0, FILE_TRUNCATED, STREAM_TOCLIENT);
1610  tx_ud->tcflags &= ~HTP_FILENAME_SET;
1611  }
1612  }
1613 
1614  if (hstate->conn != NULL) {
1615  SCLogDebug("checking body size %" PRIu64 " against inspect limit %u (cur %" PRIu64
1616  ", last %" PRIu64 ")",
1618  (uint64_t)htp_conn_request_data_counter(hstate->conn),
1619  hstate->last_response_data_stamp);
1620  /* if we reach the inspect_min_size we'll trigger inspection,
1621  * so make sure that raw stream is also inspected. Set the
1622  * data to be used to the amount of raw bytes we've seen to
1623  * get here. */
1624  if (tx_ud->response_body.body_inspected == 0 &&
1626  if ((uint64_t)htp_conn_response_data_counter(hstate->conn) >
1627  hstate->last_response_data_stamp &&
1628  (uint64_t)htp_conn_response_data_counter(hstate->conn) -
1629  hstate->last_response_data_stamp <
1630  (uint64_t)UINT_MAX) {
1631  const uint32_t data_size =
1632  (uint32_t)((uint64_t)htp_conn_response_data_counter(hstate->conn) -
1633  hstate->last_response_data_stamp);
1634  const uint32_t depth = MIN(data_size, hstate->cfg->response.inspect_min_size);
1635 
1636  /* body still in progress, but due to min inspect size we need to inspect now */
1637  StreamTcpReassemblySetMinInspectDepth(hstate->f->protoctx, STREAM_TOCLIENT, depth);
1638  AppLayerParserTriggerRawStreamReassembly(hstate->f, STREAM_TOCLIENT);
1639  }
1640  /* after the start of the body, disable the depth logic */
1641  } else if (tx_ud->response_body.body_inspected > 0) {
1642  StreamTcpReassemblySetMinInspectDepth(hstate->f->protoctx, STREAM_TOCLIENT, 0);
1643  }
1644  }
1646 }
1647 
1648 /**
1649  * \brief Print the stats of the HTTP requests
1650  */
1652 {
1653 #ifdef DEBUG
1654  SCEnter();
1655  SCMutexLock(&htp_state_mem_lock);
1656  SCLogDebug("http_state_memcnt %"PRIu64", http_state_memuse %"PRIu64"",
1657  htp_state_memcnt, htp_state_memuse);
1658  SCMutexUnlock(&htp_state_mem_lock);
1659  SCReturn;
1660 #endif
1661 }
1662 
1663 /** \brief Clears the HTTP server configuration memory used by HTP library */
1664 void HTPFreeConfig(void)
1665 {
1666  SCEnter();
1667 
1668  if (!AppLayerProtoDetectConfProtoDetectionEnabled("tcp", "http") ||
1669  !AppLayerParserConfParserEnabled("tcp", "http"))
1670  {
1671  SCReturn;
1672  }
1673 
1674  HTPCfgRec *nextrec = cfglist.next;
1675  htp_config_destroy(cfglist.cfg);
1676  while (nextrec != NULL) {
1677  HTPCfgRec *htprec = nextrec;
1678  nextrec = nextrec->next;
1679 
1680  htp_config_destroy(htprec->cfg);
1681  SCFree(htprec);
1682  }
1683  SCRadix4TreeRelease(&cfgtree.ipv4, &htp_radix4_cfg);
1684  SCRadix6TreeRelease(&cfgtree.ipv6, &htp_radix6_cfg);
1685  SCReturn;
1686 }
1687 
1688 static int HTPCallbackRequestHasTrailer(htp_tx_t *tx)
1689 {
1690  HtpTxUserData *htud = (HtpTxUserData *)htp_tx_get_user_data(tx);
1691  if (htud != NULL) {
1692  htud->tx_data.updated_ts = true;
1693  htud->request_has_trailers = 1;
1694  }
1695  return HTP_STATUS_OK;
1696 }
1697 
1698 static int HTPCallbackResponseHasTrailer(htp_tx_t *tx)
1699 {
1700  HtpTxUserData *htud = (HtpTxUserData *)htp_tx_get_user_data(tx);
1701  if (htud != NULL) {
1702  htud->tx_data.updated_tc = true;
1703  htud->response_has_trailers = 1;
1704  }
1705  return HTP_STATUS_OK;
1706 }
1707 
1708 /**\internal
1709  * \brief called at start of request
1710  * Set min inspect size.
1711  */
1712 static int HTPCallbackRequestStart(htp_tx_t *tx)
1713 {
1714  HtpState *hstate = htp_connp_get_user_data(tx->connp);
1715  if (hstate == NULL) {
1717  }
1718 
1719  uint64_t consumed = hstate->slice->offset + htp_connp_req_data_consumed(hstate->connp);
1720  SCLogDebug("HTTP request start: data offset %" PRIu64 ", in_data_counter %" PRIu64, consumed,
1721  (uint64_t)htp_conn_request_data_counter(hstate->conn));
1722 
1723  /* app-layer-frame-documentation tag start: frame registration http request */
1725  hstate->f, hstate->slice, consumed, -1, 0, HTTP_FRAME_REQUEST);
1726  if (frame) {
1727  SCLogDebug("frame %p/%" PRIi64, frame, frame->id);
1728  hstate->request_frame_id = frame->id;
1729  AppLayerFrameSetTxId(frame, HtpGetActiveRequestTxID(hstate));
1730  }
1731  /* app-layer-frame-documentation tag end: frame registration http request */
1732 
1733  if (hstate->cfg)
1734  StreamTcpReassemblySetMinInspectDepth(hstate->f->protoctx, STREAM_TOSERVER,
1735  hstate->cfg->request.inspect_min_size);
1736 
1737  HtpTxUserData *tx_ud = (HtpTxUserData *) htp_tx_get_user_data(tx);
1738  if (tx_ud == NULL) {
1739  tx_ud = HTPCalloc(1, sizeof(HtpTxUserData));
1740  if (unlikely(tx_ud == NULL)) {
1742  }
1743  tx_ud->tx_data.file_tx = STREAM_TOSERVER | STREAM_TOCLIENT; // each http tx may xfer files
1744  htp_tx_set_user_data(tx, tx_ud);
1745  } else {
1746  tx_ud->tx_data.updated_ts = true;
1747  }
1749 }
1750 
1751 /**\internal
1752  * \brief called at start of response
1753  * Set min inspect size.
1754  */
1755 static int HTPCallbackResponseStart(htp_tx_t *tx)
1756 {
1757  HtpState *hstate = htp_connp_get_user_data(tx->connp);
1758  if (hstate == NULL) {
1760  }
1761 
1762  uint64_t consumed = hstate->slice->offset + htp_connp_res_data_consumed(hstate->connp);
1763  SCLogDebug("HTTP response start: data offset %" PRIu64 ", out_data_counter %" PRIu64, consumed,
1764  (uint64_t)htp_conn_response_data_counter(hstate->conn));
1765 
1767  hstate->f, hstate->slice, consumed, -1, 1, HTTP_FRAME_RESPONSE);
1768  if (frame) {
1769  SCLogDebug("frame %p/%" PRIi64, frame, frame->id);
1770  hstate->response_frame_id = frame->id;
1771  AppLayerFrameSetTxId(frame, HtpGetActiveResponseTxID(hstate));
1772  }
1773 
1774  if (hstate->cfg)
1775  StreamTcpReassemblySetMinInspectDepth(hstate->f->protoctx, STREAM_TOCLIENT,
1776  hstate->cfg->response.inspect_min_size);
1777 
1778  HtpTxUserData *tx_ud = (HtpTxUserData *) htp_tx_get_user_data(tx);
1779  if (tx_ud == NULL) {
1780  tx_ud = HTPCalloc(1, sizeof(HtpTxUserData));
1781  if (unlikely(tx_ud == NULL)) {
1783  }
1784  tx_ud->tx_data.file_tx =
1785  STREAM_TOCLIENT; // each http tx may xfer files. Toserver already missed.
1786  htp_tx_set_user_data(tx, tx_ud);
1787  } else {
1788  tx_ud->tx_data.updated_tc = true;
1789  }
1791 }
1792 
1793 /**
1794  * \brief callback for request to store the recent incoming request
1795  into the recent_in_tx for the given htp state
1796  * \param connp pointer to the current connection parser which has the htp
1797  * state in it as user data
1798  */
1799 static int HTPCallbackRequestComplete(htp_tx_t *tx)
1800 {
1801  SCEnter();
1802 
1803  if (tx == NULL) {
1805  }
1806 
1807  HtpState *hstate = htp_connp_get_user_data(tx->connp);
1808  if (hstate == NULL) {
1810  }
1811 
1812  const uint64_t abs_right_edge =
1813  hstate->slice->offset + htp_connp_req_data_consumed(hstate->connp);
1814 
1815  /* app-layer-frame-documentation tag start: updating frame->len */
1816  if (hstate->request_frame_id > 0) {
1817  Frame *frame = AppLayerFrameGetById(hstate->f, 0, hstate->request_frame_id);
1818  if (frame) {
1819  const uint64_t request_size = abs_right_edge - hstate->last_request_data_stamp;
1820 
1821  SCLogDebug("HTTP request complete: data offset %" PRIu64 ", request_size %" PRIu64,
1822  hstate->last_request_data_stamp, request_size);
1823  SCLogDebug("frame %p/%" PRIi64 " setting len to %" PRIu64, frame, frame->id,
1824  request_size);
1825  frame->len = (int64_t)request_size;
1826  /* app-layer-frame-documentation tag end: updating frame->len */
1827  }
1828  hstate->request_frame_id = 0;
1829  }
1830 
1831  SCLogDebug("transaction_cnt %"PRIu64", list_size %"PRIu64,
1832  hstate->transaction_cnt, HTPStateGetTxCnt(hstate));
1833 
1834  SCLogDebug("HTTP request completed");
1835 
1836  HTPErrorCheckTxRequestFlags(hstate, tx);
1837 
1838  HtpTxUserData *htud = (HtpTxUserData *)htp_tx_get_user_data(tx);
1839  if (htud != NULL) {
1840  htud->tx_data.updated_ts = true;
1841  if (htud->tsflags & HTP_FILENAME_SET) {
1842  SCLogDebug("closing file that was being stored");
1843  (void)HTPFileClose(htud, NULL, 0, 0, STREAM_TOSERVER);
1844  htud->tsflags &= ~HTP_FILENAME_SET;
1845  if (abs_right_edge < (uint64_t)UINT32_MAX) {
1847  hstate->f->protoctx, STREAM_TOSERVER, (uint32_t)abs_right_edge);
1848  }
1849  }
1850  }
1851 
1852  hstate->last_request_data_stamp = abs_right_edge;
1853  /* request done, do raw reassembly now to inspect state and stream
1854  * at the same time. */
1855  AppLayerParserTriggerRawStreamReassembly(hstate->f, STREAM_TOSERVER);
1857 }
1858 
1859 /**
1860  * \brief callback for response to remove the recent received requests
1861  from the recent_in_tx for the given htp state
1862  * \param connp pointer to the current connection parser which has the htp
1863  * state in it as user data
1864  */
1865 static int HTPCallbackResponseComplete(htp_tx_t *tx)
1866 {
1867  SCEnter();
1868 
1869  HtpState *hstate = htp_connp_get_user_data(tx->connp);
1870  if (hstate == NULL) {
1872  }
1873 
1874  /* we have one whole transaction now */
1875  hstate->transaction_cnt++;
1876 
1877  const uint64_t abs_right_edge =
1878  hstate->slice->offset + htp_connp_res_data_consumed(hstate->connp);
1879 
1880  if (hstate->response_frame_id > 0) {
1881  Frame *frame = AppLayerFrameGetById(hstate->f, 1, hstate->response_frame_id);
1882  if (frame) {
1883  const uint64_t response_size = abs_right_edge - hstate->last_response_data_stamp;
1884 
1885  SCLogDebug("HTTP response complete: data offset %" PRIu64 ", response_size %" PRIu64,
1886  hstate->last_response_data_stamp, response_size);
1887  SCLogDebug("frame %p/%" PRIi64 " setting len to %" PRIu64, frame, frame->id,
1888  response_size);
1889  frame->len = (int64_t)response_size;
1890  }
1891  hstate->response_frame_id = 0;
1892  }
1893 
1894  HtpTxUserData *htud = (HtpTxUserData *) htp_tx_get_user_data(tx);
1895  if (htud != NULL) {
1896  htud->tx_data.updated_tc = true;
1897  if (htud->tcflags & HTP_FILENAME_SET) {
1898  SCLogDebug("closing file that was being stored");
1899  (void)HTPFileClose(htud, NULL, 0, 0, STREAM_TOCLIENT);
1900  htud->tcflags &= ~HTP_FILENAME_SET;
1901  }
1902  }
1903 
1904  /* response done, do raw reassembly now to inspect state and stream
1905  * at the same time. */
1906  AppLayerParserTriggerRawStreamReassembly(hstate->f, STREAM_TOCLIENT);
1907 
1908  /* handle HTTP CONNECT */
1910  /* any 2XX status response implies that the connection will become
1911  a tunnel immediately after this packet (RFC 7230, 3.3.3). */
1912  if ((htp_tx_response_status_number(tx) >= 200) &&
1913  (htp_tx_response_status_number(tx) < 300) && (hstate->transaction_cnt == 1)) {
1914  uint16_t dp = 0;
1915  if (htp_tx_request_port_number(tx) != -1) {
1916  dp = (uint16_t)htp_tx_request_port_number(tx);
1917  }
1918  // both ALPROTO_HTTP1 and ALPROTO_TLS are normal options
1919  if (!AppLayerRequestProtocolChange(hstate->f, dp, ALPROTO_UNKNOWN)) {
1920  HTPSetEvent(
1921  hstate, htud, STREAM_TOCLIENT, HTTP_DECODER_EVENT_FAILED_PROTOCOL_CHANGE);
1922  }
1925  }
1926  }
1927 
1928  hstate->last_response_data_stamp = abs_right_edge;
1930 }
1931 
1932 static int HTPCallbackRequestLine(htp_tx_t *tx)
1933 {
1934  HtpTxUserData *tx_ud;
1935  bstr *request_uri_normalized;
1936  HtpState *hstate = htp_connp_get_user_data(tx->connp);
1937  const HTPCfgRec *cfg = hstate->cfg;
1938 
1939  request_uri_normalized = SCHTPGenerateNormalizedUri(tx, tx->parsed_uri, cfg->uri_include_all);
1940  if (request_uri_normalized == NULL)
1941  return HTP_STATUS_OK;
1942 
1943  tx_ud = htp_tx_get_user_data(tx);
1944  if (unlikely(tx_ud == NULL)) {
1945  bstr_free(request_uri_normalized);
1946  return HTP_STATUS_OK;
1947  }
1948  if (unlikely(tx_ud->request_uri_normalized != NULL))
1949  bstr_free(tx_ud->request_uri_normalized);
1950  tx_ud->request_uri_normalized = request_uri_normalized;
1951 
1952  if (htp_tx_flags(tx)) {
1953  HTPErrorCheckTxRequestFlags(hstate, tx);
1954  }
1955  return HTP_STATUS_OK;
1956 }
1957 
1958 static int HTPCallbackDoubleDecodeUriPart(htp_tx_t *tx, bstr *part)
1959 {
1960  if (part == NULL)
1961  return HTP_STATUS_OK;
1962 
1963  uint64_t flags = 0;
1964  size_t prevlen = bstr_len(part);
1965  htp_status_t res = htp_urldecode_inplace(tx->cfg, HTP_DECODER_URLENCODED, part, &flags);
1966  // shorter string means that uri was encoded
1967  if (res == HTP_STATUS_OK && prevlen > bstr_len(part)) {
1968  HtpTxUserData *htud = (HtpTxUserData *) htp_tx_get_user_data(tx);
1969  if (htud == NULL)
1970  return HTP_STATUS_OK;
1971  HtpState *s = htp_connp_get_user_data(tx->connp);
1972  if (s == NULL)
1973  return HTP_STATUS_OK;
1974  HTPSetEvent(s, htud, STREAM_TOSERVER, HTP_LOG_CODE_DOUBLE_ENCODED_URI);
1975  }
1976 
1977  return HTP_STATUS_OK;
1978 }
1979 
1980 static int HTPCallbackDoubleDecodeQuery(htp_tx_t *tx)
1981 {
1982  if (tx->parsed_uri == NULL)
1983  return HTP_STATUS_OK;
1984 
1985  return HTPCallbackDoubleDecodeUriPart(tx, tx->parsed_uri->query);
1986 }
1987 
1988 static int HTPCallbackDoubleDecodePath(htp_tx_t *tx)
1989 {
1990  if (tx->parsed_uri == NULL)
1991  return HTP_STATUS_OK;
1992 
1993  return HTPCallbackDoubleDecodeUriPart(tx, tx->parsed_uri->path);
1994 }
1995 
1996 static int HTPCallbackRequestHeaderData(htp_tx_data_t *tx_data)
1997 {
1998  void *ptmp;
1999  if (htp_tx_data_len(tx_data) == 0 || htp_tx_data_tx(tx_data) == NULL)
2000  return HTP_STATUS_OK;
2001 
2002  HtpTxUserData *tx_ud = htp_tx_get_user_data(htp_tx_data_tx(tx_data));
2003  if (tx_ud == NULL) {
2004  return HTP_STATUS_OK;
2005  }
2007  tx_ud->request_headers_raw_len + htp_tx_data_len(tx_data));
2008  if (ptmp == NULL) {
2009  return HTP_STATUS_OK;
2010  }
2011  tx_ud->request_headers_raw = ptmp;
2012  tx_ud->tx_data.updated_ts = true;
2013 
2014  memcpy(tx_ud->request_headers_raw + tx_ud->request_headers_raw_len, htp_tx_data_data(tx_data),
2015  htp_tx_data_len(tx_data));
2016  tx_ud->request_headers_raw_len += htp_tx_data_len(tx_data);
2017 
2018  if (htp_tx_data_tx(tx_data) && htp_tx_data_tx(tx_data)->flags) {
2019  HtpState *hstate = htp_connp_get_user_data(htp_tx_data_tx(tx_data)->connp);
2020  HTPErrorCheckTxRequestFlags(hstate, htp_tx_data_tx(tx_data));
2021  }
2022  return HTP_STATUS_OK;
2023 }
2024 
2025 static int HTPCallbackResponseHeaderData(htp_tx_data_t *tx_data)
2026 {
2027  void *ptmp;
2028  if (htp_tx_data_len(tx_data) == 0 || htp_tx_data_tx(tx_data) == NULL)
2029  return HTP_STATUS_OK;
2030 
2031  HtpTxUserData *tx_ud = htp_tx_get_user_data(htp_tx_data_tx(tx_data));
2032  if (tx_ud == NULL) {
2033  return HTP_STATUS_OK;
2034  }
2035  tx_ud->tx_data.updated_tc = true;
2037  tx_ud->response_headers_raw_len + htp_tx_data_len(tx_data));
2038  if (ptmp == NULL) {
2039  return HTP_STATUS_OK;
2040  }
2041  tx_ud->response_headers_raw = ptmp;
2042 
2043  memcpy(tx_ud->response_headers_raw + tx_ud->response_headers_raw_len, htp_tx_data_data(tx_data),
2044  htp_tx_data_len(tx_data));
2045  tx_ud->response_headers_raw_len += htp_tx_data_len(tx_data);
2046 
2047  return HTP_STATUS_OK;
2048 }
2049 
2050 /*
2051  * We have a similar set function called HTPConfigSetDefaultsPhase1.
2052  */
2053 static void HTPConfigSetDefaultsPhase1(HTPCfgRec *cfg_prec)
2054 {
2055  cfg_prec->uri_include_all = false;
2062 
2063  if (!g_disable_randomness) {
2065  } else {
2066  cfg_prec->randomize = 0;
2067  }
2069 
2070  htp_config_register_request_header_data(cfg_prec->cfg, HTPCallbackRequestHeaderData);
2071  htp_config_register_request_trailer_data(cfg_prec->cfg, HTPCallbackRequestHeaderData);
2072  htp_config_register_response_header_data(cfg_prec->cfg, HTPCallbackResponseHeaderData);
2073  htp_config_register_response_trailer_data(cfg_prec->cfg, HTPCallbackResponseHeaderData);
2074 
2075  htp_config_register_request_trailer(cfg_prec->cfg, HTPCallbackRequestHasTrailer);
2076  htp_config_register_response_trailer(cfg_prec->cfg, HTPCallbackResponseHasTrailer);
2077 
2078  htp_config_register_request_body_data(cfg_prec->cfg, HTPCallbackRequestBodyData);
2079  htp_config_register_response_body_data(cfg_prec->cfg, HTPCallbackResponseBodyData);
2080 
2081  htp_config_register_request_start(cfg_prec->cfg, HTPCallbackRequestStart);
2082  htp_config_register_request_complete(cfg_prec->cfg, HTPCallbackRequestComplete);
2083 
2084  htp_config_register_response_start(cfg_prec->cfg, HTPCallbackResponseStart);
2085  htp_config_register_response_complete(cfg_prec->cfg, HTPCallbackResponseComplete);
2086 
2087  htp_config_set_parse_request_cookies(cfg_prec->cfg, 0);
2088 #ifdef HAVE_HTP_CONFIG_SET_ALLOW_SPACE_URI
2089  htp_config_set_allow_space_uri(cfg_prec->cfg, 1);
2090 #endif
2091 
2092  /* don't convert + to space by default */
2093  htp_config_set_plusspace_decode(cfg_prec->cfg, HTP_DECODER_URLENCODED, 0);
2094  // enables request decompression
2095  htp_config_set_request_decompression(cfg_prec->cfg, 1);
2096 #ifdef HAVE_HTP_CONFIG_SET_LZMA_LAYERS
2097  // disable by default
2098  htp_config_set_lzma_layers(cfg_prec->cfg, HTP_CONFIG_DEFAULT_LZMA_LAYERS);
2099 #endif
2100 #ifdef HAVE_HTP_CONFIG_SET_LZMA_MEMLIMIT
2101  htp_config_set_lzma_memlimit(cfg_prec->cfg,
2103 #endif
2104 #ifdef HAVE_HTP_CONFIG_SET_COMPRESSION_BOMB_LIMIT
2105  htp_config_set_compression_bomb_limit(cfg_prec->cfg,
2107 #endif
2108 #ifdef HAVE_HTP_CONFIG_SET_COMPRESSION_TIME_LIMIT
2109  htp_config_set_compression_time_limit(cfg_prec->cfg, HTP_CONFIG_DEFAULT_COMPRESSION_TIME_LIMIT);
2110 #endif
2111 #ifdef HAVE_HTP_CONFIG_SET_MAX_TX
2112 #define HTP_CONFIG_DEFAULT_MAX_TX_LIMIT 512
2113  htp_config_set_max_tx(cfg_prec->cfg, HTP_CONFIG_DEFAULT_MAX_TX_LIMIT);
2114 #endif
2115 #ifdef HAVE_HTP_CONFIG_SET_HEADERS_LIMIT
2116 #define HTP_CONFIG_DEFAULT_HEADERS_LIMIT 1024
2117  htp_config_set_number_headers_limit(cfg_prec->cfg, HTP_CONFIG_DEFAULT_HEADERS_LIMIT);
2118 #endif
2119  /* libhtp <= 0.5.9 doesn't use soft limit, but it's impossible to set
2120  * only the hard limit. So we set both here to the (current) htp defaults.
2121  * The reason we do this is that if the user sets the hard limit in the
2122  * config, we have to set the soft limit as well. If libhtp starts using
2123  * the soft limit in the future, we at least make sure we control what
2124  * it's value is. */
2125  htp_config_set_field_limits(cfg_prec->cfg, (size_t)HTP_CONFIG_DEFAULT_FIELD_LIMIT_SOFT,
2127 }
2128 
2129 /* hack: htp random range code expects random values in range of 0-RAND_MAX,
2130  * but we can get both <0 and >RAND_MAX values from RandomGet
2131  */
2132 static int RandomGetWrap(void)
2133 {
2134  unsigned long r;
2135 
2136  do {
2137  r = RandomGet();
2138  } while(r >= ULONG_MAX - (ULONG_MAX % RAND_MAX));
2139 
2140  return r % RAND_MAX;
2141 }
2142 
2143 /*
2144  * We have this splitup so that in case double decoding has been enabled
2145  * for query and path, they would be called first on the callback queue,
2146  * before the callback set by Phase2() is called. We need this, since
2147  * the callback in Phase2() generates the normalized uri which utilizes
2148  * the query and path. */
2149 static void HTPConfigSetDefaultsPhase2(const char *name, HTPCfgRec *cfg_prec)
2150 {
2151  /* randomize inspection size if needed */
2152  if (cfg_prec->randomize) {
2153  int rdrange = cfg_prec->randomize_range;
2154 
2155  long int r = RandomGetWrap();
2156  cfg_prec->request.inspect_min_size += (int)(cfg_prec->request.inspect_min_size *
2157  ((double)r / RAND_MAX - 0.5) * rdrange / 100);
2158 
2159  r = RandomGetWrap();
2160  cfg_prec->request.inspect_window += (int)(cfg_prec->request.inspect_window *
2161  ((double)r / RAND_MAX - 0.5) * rdrange / 100);
2162  SCLogConfig("'%s' server has 'request-body-minimal-inspect-size' set to"
2163  " %u and 'request-body-inspect-window' set to %u after"
2164  " randomization.",
2165  name, cfg_prec->request.inspect_min_size, cfg_prec->request.inspect_window);
2166 
2167  r = RandomGetWrap();
2168  cfg_prec->response.inspect_min_size += (int)(cfg_prec->response.inspect_min_size *
2169  ((double)r / RAND_MAX - 0.5) * rdrange / 100);
2170 
2171  r = RandomGetWrap();
2172  cfg_prec->response.inspect_window += (int)(cfg_prec->response.inspect_window *
2173  ((double)r / RAND_MAX - 0.5) * rdrange / 100);
2174 
2175  SCLogConfig("'%s' server has 'response-body-minimal-inspect-size' set to"
2176  " %u and 'response-body-inspect-window' set to %u after"
2177  " randomization.",
2178  name, cfg_prec->response.inspect_min_size, cfg_prec->response.inspect_window);
2179  }
2180 
2181  htp_config_register_request_line(cfg_prec->cfg, HTPCallbackRequestLine);
2182 }
2183 
2184 static void HTPConfigParseParameters(HTPCfgRec *cfg_prec, ConfNode *s, struct HTPConfigTree *tree)
2185 {
2186  if (cfg_prec == NULL || s == NULL || tree == NULL)
2187  return;
2188 
2189  ConfNode *p = NULL;
2190 
2191  /* Default Parameters */
2192  TAILQ_FOREACH (p, &s->head, next) {
2193  if (strcasecmp("address", p->name) == 0) {
2194  ConfNode *pval;
2195  /* Addresses */
2196  TAILQ_FOREACH(pval, &p->head, next) {
2197  SCLogDebug("LIBHTP server %s: %s=%s", s->name, p->name, pval->val);
2198  /* IPV6 or IPV4? */
2199  if (strchr(pval->val, ':') != NULL) {
2200  SCLogDebug("LIBHTP adding ipv6 server %s at %s: %p",
2201  s->name, pval->val, cfg_prec->cfg);
2203  &tree->ipv6, &htp_radix6_cfg, pval->val, cfg_prec)) {
2204  SCLogWarning("LIBHTP failed to add ipv6 server %s, ignoring", pval->val);
2205  }
2206  } else {
2207  SCLogDebug("LIBHTP adding ipv4 server %s at %s: %p",
2208  s->name, pval->val, cfg_prec->cfg);
2210  &tree->ipv4, &htp_radix4_cfg, pval->val, cfg_prec)) {
2211  SCLogWarning("LIBHTP failed to add ipv4 server %s, ignoring", pval->val);
2212  }
2213  } /* else - if (strchr(pval->val, ':') != NULL) */
2214  } /* TAILQ_FOREACH(pval, &p->head, next) */
2215 
2216  } else if (strcasecmp("personality", p->name) == 0) {
2217  /* Personalities */
2218  int personality = HTPLookupPersonality(p->val);
2219  SCLogDebug("LIBHTP default: %s = %s", p->name, p->val);
2220  SCLogDebug("LIBHTP default: %s = %s", p->name, p->val);
2221 
2222  if (personality >= 0) {
2223  SCLogDebug("LIBHTP default: %s=%s (%d)", p->name, p->val,
2224  personality);
2225  if (htp_config_set_server_personality(cfg_prec->cfg, personality) ==
2226  HTP_STATUS_ERROR) {
2227  SCLogWarning("LIBHTP Failed adding "
2228  "personality \"%s\", ignoring",
2229  p->val);
2230  } else {
2231  SCLogDebug("LIBHTP personality set to %s",
2232  HTPLookupPersonalityString(personality));
2233  }
2234 
2235  /* The IDS personality by default converts the path (and due to
2236  * our query string callback also the query string) to lowercase.
2237  * Signatures do not expect this, so override it. */
2238  htp_config_set_convert_lowercase(cfg_prec->cfg, HTP_DECODER_URL_PATH, 0);
2239  } else {
2240  SCLogWarning("LIBHTP Unknown personality "
2241  "\"%s\", ignoring",
2242  p->val);
2243  continue;
2244  }
2245 
2246  } else if (strcasecmp("request-body-limit", p->name) == 0 ||
2247  strcasecmp("request_body_limit", p->name) == 0) {
2248  if (ParseSizeStringU32(p->val, &cfg_prec->request.body_limit) < 0) {
2249  SCLogError("Error parsing request-body-limit "
2250  "from conf file - %s. Killing engine",
2251  p->val);
2252  exit(EXIT_FAILURE);
2253  }
2254 
2255  } else if (strcasecmp("response-body-limit", p->name) == 0) {
2256  if (ParseSizeStringU32(p->val, &cfg_prec->response.body_limit) < 0) {
2257  SCLogError("Error parsing response-body-limit "
2258  "from conf file - %s. Killing engine",
2259  p->val);
2260  exit(EXIT_FAILURE);
2261  }
2262 
2263  } else if (strcasecmp("request-body-minimal-inspect-size", p->name) == 0) {
2264  if (ParseSizeStringU32(p->val, &cfg_prec->request.inspect_min_size) < 0) {
2265  SCLogError("Error parsing request-body-minimal-inspect-size "
2266  "from conf file - %s. Killing engine",
2267  p->val);
2268  exit(EXIT_FAILURE);
2269  }
2270 
2271  } else if (strcasecmp("request-body-inspect-window", p->name) == 0) {
2272  if (ParseSizeStringU32(p->val, &cfg_prec->request.inspect_window) < 0) {
2273  SCLogError("Error parsing request-body-inspect-window "
2274  "from conf file - %s. Killing engine",
2275  p->val);
2276  exit(EXIT_FAILURE);
2277  }
2278 
2279  } else if (strcasecmp("double-decode-query", p->name) == 0) {
2280  if (ConfValIsTrue(p->val)) {
2281  htp_config_register_request_line(cfg_prec->cfg,
2282  HTPCallbackDoubleDecodeQuery);
2283  }
2284 
2285  } else if (strcasecmp("double-decode-path", p->name) == 0) {
2286  if (ConfValIsTrue(p->val)) {
2287  htp_config_register_request_line(cfg_prec->cfg,
2288  HTPCallbackDoubleDecodePath);
2289  }
2290 
2291  } else if (strcasecmp("response-body-minimal-inspect-size", p->name) == 0) {
2292  if (ParseSizeStringU32(p->val, &cfg_prec->response.inspect_min_size) < 0) {
2293  SCLogError("Error parsing response-body-minimal-inspect-size "
2294  "from conf file - %s. Killing engine",
2295  p->val);
2296  exit(EXIT_FAILURE);
2297  }
2298 
2299  } else if (strcasecmp("response-body-inspect-window", p->name) == 0) {
2300  if (ParseSizeStringU32(p->val, &cfg_prec->response.inspect_window) < 0) {
2301  SCLogError("Error parsing response-body-inspect-window "
2302  "from conf file - %s. Killing engine",
2303  p->val);
2304  exit(EXIT_FAILURE);
2305  }
2306 
2307  } else if (strcasecmp("response-body-decompress-layer-limit", p->name) == 0) {
2308  uint32_t value = 2;
2309  if (ParseSizeStringU32(p->val, &value) < 0) {
2310  SCLogError("Error parsing response-body-inspect-window "
2311  "from conf file - %s. Killing engine",
2312  p->val);
2313  exit(EXIT_FAILURE);
2314  }
2315 #ifdef HAVE_HTP_CONFIG_SET_RESPONSE_DECOMPRESSION_LAYER_LIMIT
2316  htp_config_set_response_decompression_layer_limit(cfg_prec->cfg, value);
2317 #else
2318  SCLogWarning("can't set response-body-decompress-layer-limit "
2319  "to %u, libhtp version too old",
2320  value);
2321 #endif
2322  } else if (strcasecmp("path-convert-backslash-separators", p->name) == 0) {
2323  htp_config_set_backslash_convert_slashes(cfg_prec->cfg,
2324  HTP_DECODER_URL_PATH,
2325  ConfValIsTrue(p->val));
2326  } else if (strcasecmp("path-bestfit-replacement-char", p->name) == 0) {
2327  if (strlen(p->val) == 1) {
2328  htp_config_set_bestfit_replacement_byte(cfg_prec->cfg,
2329  HTP_DECODER_URL_PATH,
2330  p->val[0]);
2331  } else {
2332  SCLogError("Invalid entry "
2333  "for libhtp param path-bestfit-replacement-char");
2334  }
2335  } else if (strcasecmp("path-convert-lowercase", p->name) == 0) {
2336  htp_config_set_convert_lowercase(cfg_prec->cfg,
2337  HTP_DECODER_URL_PATH,
2338  ConfValIsTrue(p->val));
2339  } else if (strcasecmp("path-nul-encoded-terminates", p->name) == 0) {
2340  htp_config_set_nul_encoded_terminates(cfg_prec->cfg,
2341  HTP_DECODER_URL_PATH,
2342  ConfValIsTrue(p->val));
2343  } else if (strcasecmp("path-nul-raw-terminates", p->name) == 0) {
2344  htp_config_set_nul_raw_terminates(cfg_prec->cfg,
2345  HTP_DECODER_URL_PATH,
2346  ConfValIsTrue(p->val));
2347  } else if (strcasecmp("path-separators-compress", p->name) == 0) {
2348  htp_config_set_path_separators_compress(cfg_prec->cfg,
2349  HTP_DECODER_URL_PATH,
2350  ConfValIsTrue(p->val));
2351  } else if (strcasecmp("path-separators-decode", p->name) == 0) {
2352  htp_config_set_path_separators_decode(cfg_prec->cfg,
2353  HTP_DECODER_URL_PATH,
2354  ConfValIsTrue(p->val));
2355  } else if (strcasecmp("path-u-encoding-decode", p->name) == 0) {
2356  htp_config_set_u_encoding_decode(cfg_prec->cfg,
2357  HTP_DECODER_URL_PATH,
2358  ConfValIsTrue(p->val));
2359  } else if (strcasecmp("path-url-encoding-invalid-handling", p->name) == 0) {
2360  enum htp_url_encoding_handling_t handling;
2361  if (strcasecmp(p->val, "preserve_percent") == 0) {
2362  handling = HTP_URL_DECODE_PRESERVE_PERCENT;
2363  } else if (strcasecmp(p->val, "remove_percent") == 0) {
2364  handling = HTP_URL_DECODE_REMOVE_PERCENT;
2365  } else if (strcasecmp(p->val, "decode_invalid") == 0) {
2366  handling = HTP_URL_DECODE_PROCESS_INVALID;
2367  } else {
2368  SCLogError("Invalid entry "
2369  "for libhtp param path-url-encoding-invalid-handling");
2370  return;
2371  }
2372  htp_config_set_url_encoding_invalid_handling(cfg_prec->cfg,
2373  HTP_DECODER_URL_PATH,
2374  handling);
2375  } else if (strcasecmp("path-utf8-convert-bestfit", p->name) == 0) {
2376  htp_config_set_utf8_convert_bestfit(cfg_prec->cfg,
2377  HTP_DECODER_URL_PATH,
2378  ConfValIsTrue(p->val));
2379  } else if (strcasecmp("uri-include-all", p->name) == 0) {
2380  cfg_prec->uri_include_all = (1 == ConfValIsTrue(p->val));
2381  SCLogDebug("uri-include-all %s",
2382  cfg_prec->uri_include_all ? "enabled" : "disabled");
2383  } else if (strcasecmp("query-plusspace-decode", p->name) == 0) {
2384  htp_config_set_plusspace_decode(cfg_prec->cfg,
2385  HTP_DECODER_URLENCODED,
2386  ConfValIsTrue(p->val));
2387  } else if (strcasecmp("meta-field-limit", p->name) == 0) {
2388  uint32_t limit = 0;
2389  if (ParseSizeStringU32(p->val, &limit) < 0) {
2390  SCLogError("Error meta-field-limit "
2391  "from conf file - %s. Killing engine",
2392  p->val);
2393  exit(EXIT_FAILURE);
2394  }
2395  if (limit == 0) {
2396  FatalError("Error meta-field-limit "
2397  "from conf file cannot be 0. Killing engine");
2398  }
2399  /* set default soft-limit with our new hard limit */
2400  htp_config_set_field_limits(cfg_prec->cfg,
2402  (size_t)limit);
2403 #ifdef HAVE_HTP_CONFIG_SET_LZMA_MEMLIMIT
2404  } else if (strcasecmp("lzma-memlimit", p->name) == 0) {
2405  uint32_t limit = 0;
2406  if (ParseSizeStringU32(p->val, &limit) < 0) {
2407  FatalError("failed to parse 'lzma-memlimit' "
2408  "from conf file - %s.",
2409  p->val);
2410  }
2411  if (limit == 0) {
2412  FatalError("'lzma-memlimit' "
2413  "from conf file cannot be 0.");
2414  }
2415  /* set default soft-limit with our new hard limit */
2416  SCLogConfig("Setting HTTP LZMA memory limit to %"PRIu32" bytes", limit);
2417  htp_config_set_lzma_memlimit(cfg_prec->cfg, (size_t)limit);
2418 #endif
2419 #ifdef HAVE_HTP_CONFIG_SET_LZMA_LAYERS
2420  } else if (strcasecmp("lzma-enabled", p->name) == 0) {
2421  if (ConfValIsTrue(p->val)) {
2422  htp_config_set_lzma_layers(cfg_prec->cfg, 1);
2423  } else if (!ConfValIsFalse(p->val)) {
2424  int8_t limit;
2425  if (StringParseInt8(&limit, 10, 0, (const char *)p->val) < 0) {
2426  FatalError("failed to parse 'lzma-enabled' "
2427  "from conf file - %s.",
2428  p->val);
2429  }
2430  SCLogConfig("Setting HTTP LZMA decompression layers to %" PRIu32 "", (int)limit);
2431  htp_config_set_lzma_layers(cfg_prec->cfg, limit);
2432  }
2433 #endif
2434 #ifdef HAVE_HTP_CONFIG_SET_COMPRESSION_BOMB_LIMIT
2435  } else if (strcasecmp("compression-bomb-limit", p->name) == 0) {
2436  uint32_t limit = 0;
2437  if (ParseSizeStringU32(p->val, &limit) < 0) {
2438  FatalError("failed to parse 'compression-bomb-limit' "
2439  "from conf file - %s.",
2440  p->val);
2441  }
2442  if (limit == 0) {
2443  FatalError("'compression-bomb-limit' "
2444  "from conf file cannot be 0.");
2445  }
2446  /* set default soft-limit with our new hard limit */
2447  SCLogConfig("Setting HTTP compression bomb limit to %"PRIu32" bytes", limit);
2448  htp_config_set_compression_bomb_limit(cfg_prec->cfg, (size_t)limit);
2449 #endif
2450 #ifdef HAVE_HTP_CONFIG_SET_COMPRESSION_TIME_LIMIT
2451  } else if (strcasecmp("decompression-time-limit", p->name) == 0) {
2452  uint32_t limit = 0;
2453  // between 1 usec and 1 second
2454  if (StringParseU32RangeCheck(&limit, 10, 0, p->val, 1, 1000000) < 0) {
2455  FatalError("failed to parse 'decompression-time-limit' "
2456  "from conf file - %s.",
2457  p->val);
2458  }
2459  SCLogConfig("Setting HTTP decompression time limit to %" PRIu32 " usec", limit);
2460  htp_config_set_compression_time_limit(cfg_prec->cfg, (size_t)limit);
2461 #endif
2462 #ifdef HAVE_HTP_CONFIG_SET_MAX_TX
2463  } else if (strcasecmp("max-tx", p->name) == 0) {
2464  uint32_t limit = 0;
2465  if (ParseSizeStringU32(p->val, &limit) < 0) {
2466  FatalError("failed to parse 'max-tx' "
2467  "from conf file - %s.",
2468  p->val);
2469  }
2470  /* set default soft-limit with our new hard limit */
2471  SCLogConfig("Setting HTTP max-tx limit to %" PRIu32 " bytes", limit);
2472  htp_config_set_max_tx(cfg_prec->cfg, limit);
2473 #endif
2474 #ifdef HAVE_HTP_CONFIG_SET_HEADERS_LIMIT
2475  } else if (strcasecmp("headers-limit", p->name) == 0) {
2476  uint32_t limit = 0;
2477  if (ParseSizeStringU32(p->val, &limit) < 0) {
2478  FatalError("failed to parse 'headers-limit' "
2479  "from conf file - %s.",
2480  p->val);
2481  }
2482  SCLogConfig("Setting HTTP headers limit to %" PRIu32, limit);
2483  htp_config_set_number_headers_limit(cfg_prec->cfg, limit);
2484 #endif
2485  } else if (strcasecmp("randomize-inspection-sizes", p->name) == 0) {
2486  if (!g_disable_randomness) {
2487  cfg_prec->randomize = ConfValIsTrue(p->val);
2488  }
2489  } else if (strcasecmp("randomize-inspection-range", p->name) == 0) {
2490  uint32_t range;
2491  if (StringParseU32RangeCheck(&range, 10, 0,
2492  (const char *)p->val, 0, 100) < 0) {
2493  SCLogError("Invalid value for randomize"
2494  "-inspection-range setting from conf file - \"%s\"."
2495  " It should be a valid integer less than or equal to 100."
2496  " Killing engine",
2497  p->val);
2498  exit(EXIT_FAILURE);
2499  }
2500  cfg_prec->randomize_range = range;
2501  } else if (strcasecmp("http-body-inline", p->name) == 0) {
2502  if (ConfValIsTrue(p->val)) {
2503  cfg_prec->http_body_inline = 1;
2504  } else if (ConfValIsFalse(p->val)) {
2505  cfg_prec->http_body_inline = 0;
2506  } else {
2507  if (strcmp("auto", p->val) != 0) {
2508  WarnInvalidConfEntry("http_body_inline", "%s", "auto");
2509  }
2510  if (EngineModeIsIPS()) {
2511  cfg_prec->http_body_inline = 1;
2512  } else {
2513  cfg_prec->http_body_inline = 0;
2514  }
2515  }
2516  } else if (strcasecmp("swf-decompression", p->name) == 0) {
2517  ConfNode *pval;
2518 
2519  TAILQ_FOREACH(pval, &p->head, next) {
2520  if (strcasecmp("enabled", pval->name) == 0) {
2521  if (ConfValIsTrue(pval->val)) {
2522  cfg_prec->swf_decompression_enabled = 1;
2523  } else if (ConfValIsFalse(pval->val)) {
2524  cfg_prec->swf_decompression_enabled = 0;
2525  } else {
2526  WarnInvalidConfEntry("swf-decompression.enabled", "%s", "no");
2527  }
2528  } else if (strcasecmp("type", pval->name) == 0) {
2529  if (strcasecmp("no", pval->val) == 0) {
2531  } else if (strcasecmp("deflate", pval->val) == 0) {
2533  } else if (strcasecmp("lzma", pval->val) == 0) {
2535  } else if (strcasecmp("both", pval->val) == 0) {
2537  } else {
2538  SCLogError("Invalid entry for "
2539  "swf-decompression.type: %s - "
2540  "Killing engine",
2541  pval->val);
2542  exit(EXIT_FAILURE);
2543  }
2544  } else if (strcasecmp("compress-depth", pval->name) == 0) {
2545  if (ParseSizeStringU32(pval->val, &cfg_prec->swf_compress_depth) < 0) {
2546  SCLogError("Error parsing swf-decompression.compression-depth "
2547  "from conf file - %s. Killing engine",
2548  p->val);
2549  exit(EXIT_FAILURE);
2550  }
2551  } else if (strcasecmp("decompress-depth", pval->name) == 0) {
2552  if (ParseSizeStringU32(pval->val, &cfg_prec->swf_decompress_depth) < 0) {
2553  SCLogError("Error parsing swf-decompression.decompression-depth "
2554  "from conf file - %s. Killing engine",
2555  p->val);
2556  exit(EXIT_FAILURE);
2557  }
2558  } else {
2559  SCLogWarning("Ignoring unknown param %s", pval->name);
2560  }
2561  }
2562  } else {
2563  SCLogWarning("LIBHTP Ignoring unknown "
2564  "default config: %s",
2565  p->name);
2566  }
2567  } /* TAILQ_FOREACH(p, &default_config->head, next) */
2568 }
2569 
2570 void HTPConfigure(void)
2571 {
2572  SCEnter();
2573 
2574  cfglist.next = NULL;
2575 
2579 
2580  /* Default Config */
2581  cfglist.cfg = htp_config_create();
2582  if (NULL == cfglist.cfg) {
2583  FatalError("Failed to create HTP default config");
2584  }
2585  SCLogDebug("LIBHTP default config: %p", cfglist.cfg);
2586  HTPConfigSetDefaultsPhase1(&cfglist);
2587  if (ConfGetNode("app-layer.protocols.http.libhtp") == NULL) {
2588  HTPConfigParseParameters(&cfglist, ConfGetNode("libhtp.default-config"), &cfgtree);
2589  } else {
2590  HTPConfigParseParameters(
2591  &cfglist, ConfGetNode("app-layer.protocols.http.libhtp.default-config"), &cfgtree);
2592  }
2593  HTPConfigSetDefaultsPhase2("default", &cfglist);
2594 
2595  HTPParseMemcap();
2596 
2597  /* Read server config and create a parser for each IP in radix tree */
2598  ConfNode *server_config = ConfGetNode("app-layer.protocols.http.libhtp.server-config");
2599  if (server_config == NULL) {
2600  server_config = ConfGetNode("libhtp.server-config");
2601  if (server_config == NULL) {
2602  SCLogDebug("LIBHTP Configuring %p", server_config);
2603  SCReturn;
2604  }
2605  }
2606  SCLogDebug("LIBHTP Configuring %p", server_config);
2607 
2608  ConfNode *si;
2609  /* Server Nodes */
2610  TAILQ_FOREACH(si, &server_config->head, next) {
2611  /* Need the named node, not the index */
2612  ConfNode *s = TAILQ_FIRST(&si->head);
2613  if (NULL == s) {
2614  SCLogDebug("LIBHTP s NULL");
2615  continue;
2616  }
2617 
2618  SCLogDebug("LIBHTP server %s", s->name);
2619 
2620  HTPCfgRec *nextrec = cfglist.next;
2621  HTPCfgRec *htprec = SCCalloc(1, sizeof(HTPCfgRec));
2622  if (NULL == htprec)
2623  exit(EXIT_FAILURE);
2624 
2625  cfglist.next = htprec;
2626 
2627  cfglist.next->next = nextrec;
2628  cfglist.next->cfg = htp_config_create();
2629  if (NULL == cfglist.next->cfg) {
2630  FatalError("Failed to create HTP server config");
2631  }
2632 
2633  HTPConfigSetDefaultsPhase1(htprec);
2634  HTPConfigParseParameters(htprec, s, &cfgtree);
2635  HTPConfigSetDefaultsPhase2(s->name, htprec);
2636  }
2637 
2638  SCReturn;
2639 }
2640 
2642 {
2643 #ifdef DEBUG
2644  SCMutexLock(&htp_state_mem_lock);
2645  SCLogPerf("htp memory %"PRIu64" (%"PRIu64")", htp_state_memuse, htp_state_memcnt);
2646  SCMutexUnlock(&htp_state_mem_lock);
2647 #endif
2648 }
2649 
2650 /** \internal
2651  * \brief get files callback
2652  * \param state state ptr
2653  * \param direction flow direction
2654  * \retval files files ptr
2655  */
2656 static AppLayerGetFileState HTPGetTxFiles(void *txv, uint8_t direction)
2657 {
2658  AppLayerGetFileState files = { .fc = NULL, .cfg = &htp_sbcfg };
2659  htp_tx_t *tx = (htp_tx_t *)txv;
2660  HtpTxUserData *tx_ud = htp_tx_get_user_data(tx);
2661  if (tx_ud) {
2662  if (direction & STREAM_TOCLIENT) {
2663  files.fc = &tx_ud->files_tc;
2664  } else {
2665  files.fc = &tx_ud->files_ts;
2666  }
2667  }
2668  return files;
2669 }
2670 
2671 static int HTPStateGetAlstateProgress(void *tx, uint8_t direction)
2672 {
2673  if (direction & STREAM_TOSERVER)
2674  return ((htp_tx_t *)tx)->request_progress;
2675  else
2676  return ((htp_tx_t *)tx)->response_progress;
2677 }
2678 
2679 static uint64_t HTPStateGetTxCnt(void *alstate)
2680 {
2681  HtpState *http_state = (HtpState *)alstate;
2682 
2683  if (http_state != NULL && http_state->conn != NULL) {
2684  const int64_t size = (int64_t)htp_list_size(http_state->conn->transactions);
2685  if (size < 0)
2686  return 0ULL;
2687  SCLogDebug("size %"PRIu64, size);
2688  return (uint64_t)size + http_state->tx_freed;
2689  } else {
2690  return 0ULL;
2691  }
2692 }
2693 
2694 static void *HTPStateGetTx(void *alstate, uint64_t tx_id)
2695 {
2696  HtpState *http_state = (HtpState *)alstate;
2697 
2698  if (http_state != NULL && http_state->conn != NULL && tx_id >= http_state->tx_freed)
2699  return htp_list_get(http_state->conn->transactions, tx_id - http_state->tx_freed);
2700  else
2701  return NULL;
2702 }
2703 
2704 void *HtpGetTxForH2(void *alstate)
2705 {
2706  // gets last transaction
2707  HtpState *http_state = (HtpState *)alstate;
2708  if (http_state != NULL && http_state->conn != NULL) {
2709  size_t txid = HTPStateGetTxCnt(http_state);
2710  if (txid > http_state->tx_freed) {
2711  return htp_list_get(http_state->conn->transactions, txid - http_state->tx_freed - 1);
2712  }
2713  }
2714  return NULL;
2715 }
2716 
2717 static int HTPStateGetEventInfo(
2718  const char *event_name, uint8_t *event_id, AppLayerEventType *event_type)
2719 {
2720  if (SCAppLayerGetEventIdByName(event_name, http_decoder_event_table, event_id) == 0) {
2721  *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
2722  return 0;
2723  }
2724  return -1;
2725 }
2726 
2727 static int HTPStateGetEventInfoById(
2728  uint8_t event_id, const char **event_name, AppLayerEventType *event_type)
2729 {
2730  *event_name = SCMapEnumValueToName(event_id, http_decoder_event_table);
2731  if (*event_name == NULL) {
2732  SCLogError("event \"%d\" not present in "
2733  "http's enum map table.",
2734  event_id);
2735  /* this should be treated as fatal */
2736  return -1;
2737  }
2738 
2739  *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
2740 
2741  return 0;
2742 }
2743 
2744 static AppLayerTxData *HTPGetTxData(void *vtx)
2745 {
2746  htp_tx_t *tx = (htp_tx_t *)vtx;
2747  HtpTxUserData *tx_ud = htp_tx_get_user_data(tx);
2748  if (tx_ud) {
2749  return &tx_ud->tx_data;
2750  }
2751  return NULL;
2752 }
2753 
2754 static AppLayerStateData *HTPGetStateData(void *vstate)
2755 {
2756  HtpState *s = vstate;
2757  return &s->state_data;
2758 }
2759 
2760 static int HTPRegisterPatternsForProtocolDetection(void)
2761 {
2762  const char *methods[] = { "GET", "PUT", "POST", "HEAD", "TRACE", "OPTIONS",
2763  "CONNECT", "DELETE", "PATCH", "PROPFIND", "PROPPATCH", "MKCOL",
2764  "COPY", "MOVE", "LOCK", "UNLOCK", "CHECKOUT", "UNCHECKOUT", "CHECKIN",
2765  "UPDATE", "LABEL", "REPORT", "MKWORKSPACE", "MKACTIVITY", "MERGE",
2766  "INVALID", "VERSION-CONTROL", "BASELINE-CONTROL", NULL};
2767  const char *spacings[] = { "|20|", "|09|", NULL };
2768  const char *versions[] = { "HTTP/0.9", "HTTP/1.0", "HTTP/1.1", NULL };
2769 
2770  int methods_pos;
2771  int spacings_pos;
2772  int versions_pos;
2773  int register_result;
2774  char method_buffer[32] = "";
2775 
2776  /* Loop through all the methods ands spacings and register the patterns */
2777  for (methods_pos = 0; methods[methods_pos]; methods_pos++) {
2778  for (spacings_pos = 0; spacings[spacings_pos]; spacings_pos++) {
2779 
2780  /* Combine the method name and the spacing */
2781  snprintf(method_buffer, sizeof(method_buffer), "%s%s", methods[methods_pos], spacings[spacings_pos]);
2782 
2783  /* Register the new method+spacing pattern
2784  * 3 is subtracted from the length since the spacing is hex typed as |xx|
2785  * but the pattern matching should only be one char
2786  */
2787  register_result = AppLayerProtoDetectPMRegisterPatternCI(IPPROTO_TCP, ALPROTO_HTTP1,
2788  method_buffer, (uint16_t)strlen(method_buffer) - 3, 0, STREAM_TOSERVER);
2789  if (register_result < 0) {
2790  return -1;
2791  }
2792  }
2793  }
2794 
2795  /* Loop through all the http version patterns that are TO_CLIENT */
2796  for (versions_pos = 0; versions[versions_pos]; versions_pos++) {
2797  register_result = AppLayerProtoDetectPMRegisterPatternCI(IPPROTO_TCP, ALPROTO_HTTP1,
2798  versions[versions_pos], (uint16_t)strlen(versions[versions_pos]), 0,
2799  STREAM_TOCLIENT);
2800  if (register_result < 0) {
2801  return -1;
2802  }
2803  }
2804 
2805  return 0;
2806 }
2807 
2808 /**
2809  * \brief Register the HTTP protocol and state handling functions to APP layer
2810  * of the engine.
2811  */
2813 {
2814  SCEnter();
2815 
2816  const char *proto_name = "http";
2817 
2818  /** HTTP */
2819  if (AppLayerProtoDetectConfProtoDetectionEnabled("tcp", proto_name)) {
2821  if (HTPRegisterPatternsForProtocolDetection() < 0)
2822  return;
2823  } else {
2824  SCLogInfo("Protocol detection and parser disabled for %s protocol",
2825  proto_name);
2826  return;
2827  }
2828 
2829  if (AppLayerParserConfParserEnabled("tcp", proto_name)) {
2830  AppLayerParserRegisterStateFuncs(IPPROTO_TCP, ALPROTO_HTTP1, HTPStateAlloc, HTPStateFree);
2831  AppLayerParserRegisterTxFreeFunc(IPPROTO_TCP, ALPROTO_HTTP1, HTPStateTransactionFree);
2832  AppLayerParserRegisterGetTxFilesFunc(IPPROTO_TCP, ALPROTO_HTTP1, HTPGetTxFiles);
2834  IPPROTO_TCP, ALPROTO_HTTP1, HTPStateGetAlstateProgress);
2835  AppLayerParserRegisterGetTxCnt(IPPROTO_TCP, ALPROTO_HTTP1, HTPStateGetTxCnt);
2836  AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_HTTP1, HTPStateGetTx);
2837 
2840  AppLayerParserRegisterGetEventInfo(IPPROTO_TCP, ALPROTO_HTTP1, HTPStateGetEventInfo);
2842  IPPROTO_TCP, ALPROTO_HTTP1, HTPStateGetEventInfoById);
2843 
2844  AppLayerParserRegisterTxDataFunc(IPPROTO_TCP, ALPROTO_HTTP1, HTPGetTxData);
2845  AppLayerParserRegisterStateDataFunc(IPPROTO_TCP, ALPROTO_HTTP1, HTPGetStateData);
2846 
2848  IPPROTO_TCP, ALPROTO_HTTP1, AppLayerHtpSetStreamDepthFlag);
2849 
2851  IPPROTO_TCP, ALPROTO_HTTP1, STREAM_TOSERVER, HTPHandleRequestData);
2853  IPPROTO_TCP, ALPROTO_HTTP1, STREAM_TOCLIENT, HTPHandleResponseData);
2854  SC_ATOMIC_INIT(htp_config_flags);
2855  /* This parser accepts gaps. */
2859  IPPROTO_TCP, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_TOCLIENT);
2860  /* app-layer-frame-documentation tag start: registering relevant callbacks */
2862  IPPROTO_TCP, ALPROTO_HTTP1, HTTPGetFrameIdByName, HTTPGetFrameNameById);
2863  /* app-layer-frame-documentation tag end: registering relevant callbacks */
2864  HTPConfigure();
2865  } else {
2866  SCLogInfo("Parser disabled for %s protocol. Protocol detection still on.", proto_name);
2867  }
2868 #ifdef UNITTESTS
2869  AppLayerParserRegisterProtocolUnittests(IPPROTO_TCP, ALPROTO_HTTP1, HTPParserRegisterTests);
2870 #endif
2871 
2872  SCReturn;
2873 }
2874 
2875 #ifdef UNITTESTS
2876 #include "detect-engine-alert.h"
2877 
2878 static HTPCfgRec cfglist_backup;
2879 
2881 {
2882  cfglist_backup = cfglist;
2883 }
2884 
2886 {
2887  cfglist = cfglist_backup;
2888 }
2889 
2890 /** \test Test case where chunks are sent in smaller chunks and check the
2891  * response of the parser from HTP library. */
2892 static int HTPParserTest01(void)
2893 {
2894  uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Victor/1.0\r\n\r\nPost"
2895  " Data is c0oL!";
2896  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2897 
2898  TcpSession ssn;
2899  memset(&ssn, 0, sizeof(ssn));
2900 
2903 
2904  Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
2905  FAIL_IF_NULL(f);
2906  f->protoctx = &ssn;
2907  f->proto = IPPROTO_TCP;
2908  f->alproto = ALPROTO_HTTP1;
2909 
2910  StreamTcpInitConfig(true);
2911 
2912  uint32_t u;
2913  for (u = 0; u < httplen1; u++) {
2914  uint8_t flags = 0;
2915 
2916  if (u == 0)
2917  flags = STREAM_TOSERVER|STREAM_START;
2918  else if (u == (httplen1 - 1))
2919  flags = STREAM_TOSERVER|STREAM_EOF;
2920  else
2921  flags = STREAM_TOSERVER;
2922 
2923  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, flags, &httpbuf1[u], 1);
2924  FAIL_IF(r != 0);
2925  }
2926 
2927  HtpState *htp_state = f->alstate;
2928  FAIL_IF_NULL(htp_state);
2929 
2930  htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
2931  FAIL_IF_NULL(tx);
2932 
2933  const htp_header_t *h = htp_tx_request_header_index(tx, 0);
2934  FAIL_IF_NULL(h);
2935 
2936  FAIL_IF(strcmp(bstr_util_strdup_to_c(htp_header_value(h)), "Victor/1.0"));
2939 
2941  StreamTcpFreeConfig(true);
2942  UTHFreeFlow(f);
2943  PASS;
2944 }
2945 
2946 /** \test Test folding in 1 read case */
2947 static int HTPParserTest01b(void)
2948 {
2949  uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent:\r\n Victor/1.0\r\n\r\nPost"
2950  " Data is c0oL!";
2951  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2952 
2953  TcpSession ssn;
2954  memset(&ssn, 0, sizeof(ssn));
2955 
2958 
2959  Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
2960  FAIL_IF_NULL(f);
2961  f->protoctx = &ssn;
2962  f->proto = IPPROTO_TCP;
2963  f->alproto = ALPROTO_HTTP1;
2964 
2965  StreamTcpInitConfig(true);
2966 
2967  uint8_t flags =STREAM_TOSERVER|STREAM_START|STREAM_EOF;
2968  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, flags, httpbuf1, httplen1);
2969  FAIL_IF(r != 0);
2970 
2971  HtpState *htp_state = f->alstate;
2972  FAIL_IF_NULL(htp_state);
2973 
2974  htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
2975  FAIL_IF_NULL(tx);
2976 
2977  const htp_header_t *h = htp_tx_request_header_index(tx, 0);
2978  FAIL_IF_NULL(h);
2979 
2980  FAIL_IF(strcmp(bstr_util_strdup_to_c(htp_header_value(h)), "Victor/1.0"));
2983 
2985  StreamTcpFreeConfig(true);
2986  UTHFreeFlow(f);
2987  PASS;
2988 }
2989 
2990 /** \test Test folding in 1byte per read case */
2991 static int HTPParserTest01c(void)
2992 {
2993  uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent:\r\n Victor/1.0\r\n\r\nPost"
2994  " Data is c0oL!";
2995  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2996 
2997  TcpSession ssn;
2998  memset(&ssn, 0, sizeof(ssn));
2999 
3002 
3003  Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
3004  FAIL_IF_NULL(f);
3005  f->protoctx = &ssn;
3006  f->proto = IPPROTO_TCP;
3007  f->alproto = ALPROTO_HTTP1;
3008 
3009  StreamTcpInitConfig(true);
3010 
3011  uint32_t u;
3012  for (u = 0; u < httplen1; u++) {
3013  uint8_t flags = 0;
3014 
3015  if (u == 0)
3016  flags = STREAM_TOSERVER|STREAM_START;
3017  else if (u == (httplen1 - 1))
3018  flags = STREAM_TOSERVER|STREAM_EOF;
3019  else
3020  flags = STREAM_TOSERVER;
3021 
3022  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, flags, &httpbuf1[u], 1);
3023  FAIL_IF(r != 0);
3024  }
3025 
3026  HtpState *htp_state = f->alstate;
3027  FAIL_IF_NULL(htp_state);
3028 
3029  htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3030  FAIL_IF_NULL(tx);
3031 
3032  const htp_header_t *h = htp_tx_request_header_index(tx, 0);
3033  FAIL_IF_NULL(h);
3034 
3035  FAIL_IF(strcmp(bstr_util_strdup_to_c(htp_header_value(h)), "Victor/1.0"));
3038 
3040  StreamTcpFreeConfig(true);
3041  UTHFreeFlow(f);
3042  PASS;
3043 }
3044 
3045 /** \test Test case where chunks are sent in smaller chunks and check the
3046  * response of the parser from HTP library. */
3047 static int HTPParserTest01a(void)
3048 {
3049  Flow *f = NULL;
3050  uint8_t httpbuf1[] = " POST / HTTP/1.0\r\nUser-Agent: Victor/1.0\r\n\r\nPost"
3051  " Data is c0oL!";
3052  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
3053  TcpSession ssn;
3054  HtpState *htp_state = NULL;
3056 
3057  memset(&ssn, 0, sizeof(ssn));
3058 
3059  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
3060  FAIL_IF_NULL(f);
3061  f->protoctx = &ssn;
3062  f->proto = IPPROTO_TCP;
3063  f->alproto = ALPROTO_HTTP1;
3064 
3065  StreamTcpInitConfig(true);
3066 
3067  uint32_t u;
3068  for (u = 0; u < httplen1; u++) {
3069  uint8_t flags = 0;
3070 
3071  if (u == 0)
3072  flags = STREAM_TOSERVER|STREAM_START;
3073  else if (u == (httplen1 - 1))
3074  flags = STREAM_TOSERVER|STREAM_EOF;
3075  else
3076  flags = STREAM_TOSERVER;
3077 
3078  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, flags, &httpbuf1[u], 1);
3079  FAIL_IF(r != 0);
3080  }
3081 
3082  htp_state = f->alstate;
3083  FAIL_IF_NULL(htp_state);
3084 
3085  htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3086  FAIL_IF_NULL(tx);
3087 
3088  const htp_header_t *h = htp_tx_request_header_index(tx, 0);
3089  FAIL_IF_NULL(h);
3090 
3091  FAIL_IF(strcmp(bstr_util_strdup_to_c(htp_header_value(h)), "Victor/1.0"));
3094 
3096  StreamTcpFreeConfig(true);
3097  UTHFreeFlow(f);
3098  PASS;
3099 }
3100 
3101 /** \test See how it deals with an incomplete request. */
3102 static int HTPParserTest02(void)
3103 {
3104  Flow *f = NULL;
3105  uint8_t httpbuf1[] = "POST";
3106  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
3107  TcpSession ssn;
3108  HtpState *http_state = NULL;
3110 
3111  memset(&ssn, 0, sizeof(ssn));
3112 
3113  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
3114  FAIL_IF_NULL(f);
3115  f->protoctx = &ssn;
3116  f->proto = IPPROTO_TCP;
3117  f->alproto = ALPROTO_HTTP1;
3118 
3119  StreamTcpInitConfig(true);
3120 
3121  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1,
3122  STREAM_TOSERVER | STREAM_START | STREAM_EOF, httpbuf1, httplen1);
3123  FAIL_IF(r != 0);
3124 
3125  http_state = f->alstate;
3126  FAIL_IF_NULL(http_state);
3127 
3128  htp_tx_t *tx = HTPStateGetTx(http_state, 0);
3129  FAIL_IF_NULL(tx);
3130  const htp_header_t *h = htp_tx_request_header_index(tx, 0);
3131  FAIL_IF_NOT_NULL(h);
3132 
3134  char *method = bstr_util_strdup_to_c(htp_tx_request_method(tx));
3135  FAIL_IF_NULL(method);
3136 
3137  FAIL_IF(strcmp(method, "POST") != 0);
3138  SCFree(method);
3139 
3141  StreamTcpFreeConfig(true);
3142  UTHFreeFlow(f);
3143  PASS;
3144 }
3145 
3146 /** \test Test case where method is invalid and data is sent in smaller chunks
3147  * and check the response of the parser from HTP library. */
3148 static int HTPParserTest03(void)
3149 {
3150  Flow *f = NULL;
3151  uint8_t httpbuf1[] = "HELLO / HTTP/1.0\r\n";
3152  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
3153  TcpSession ssn;
3154  HtpState *htp_state = NULL;
3156 
3157  memset(&ssn, 0, sizeof(ssn));
3158 
3159  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
3160  FAIL_IF_NULL(f);
3161  f->protoctx = &ssn;
3162  f->proto = IPPROTO_TCP;
3163  f->alproto = ALPROTO_HTTP1;
3164 
3165  StreamTcpInitConfig(true);
3166 
3167  uint32_t u;
3168  for (u = 0; u < httplen1; u++) {
3169  uint8_t flags = 0;
3170 
3171  if (u == 0) flags = STREAM_TOSERVER|STREAM_START;
3172  else if (u == (httplen1 - 1)) flags = STREAM_TOSERVER|STREAM_EOF;
3173  else flags = STREAM_TOSERVER;
3174 
3175  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, flags, &httpbuf1[u], 1);
3176  FAIL_IF(r != 0);
3177  }
3178  htp_state = f->alstate;
3179  FAIL_IF_NULL(htp_state);
3180 
3181  htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3182  FAIL_IF_NULL(tx);
3183 
3184  const htp_header_t *h = htp_tx_request_header_index(tx, 0);
3185  FAIL_IF_NOT_NULL(h);
3188 
3190  StreamTcpFreeConfig(true);
3191  UTHFreeFlow(f);
3192  PASS;
3193 }
3194 
3195 /** \test Test case where invalid data is sent and check the response of the
3196  * parser from HTP library. */
3197 static int HTPParserTest04(void)
3198 {
3199  Flow *f = NULL;
3200  HtpState *htp_state = NULL;
3201  uint8_t httpbuf1[] = "World!\r\n";
3202  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
3203  TcpSession ssn;
3205 
3206  memset(&ssn, 0, sizeof(ssn));
3207 
3208  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
3209  FAIL_IF_NULL(f);
3210  f->protoctx = &ssn;
3211  f->proto = IPPROTO_TCP;
3212  f->alproto = ALPROTO_HTTP1;
3213 
3214  StreamTcpInitConfig(true);
3215 
3216  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1,
3217  STREAM_TOSERVER | STREAM_START | STREAM_EOF, httpbuf1, httplen1);
3218  FAIL_IF(r != 0);
3219 
3220  htp_state = f->alstate;
3221  FAIL_IF_NULL(htp_state);
3222 
3223  htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3224  FAIL_IF_NULL(tx);
3225  const htp_header_t *h = htp_tx_request_header_index(tx, 0);
3226 
3227  FAIL_IF_NOT_NULL(h);
3230 
3232  StreamTcpFreeConfig(true);
3233  UTHFreeFlow(f);
3234  PASS;
3235 }
3236 
3237 /** \test Test both sides of a http stream mixed up to see if the HTP parser
3238  * properly parsed them and also keeps them separated. */
3239 static int HTPParserTest05(void)
3240 {
3241  uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Victor/1.0\r\nContent-Length: 17\r\n\r\n";
3242  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
3243  uint8_t httpbuf2[] = "Post D";
3244  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
3245  uint8_t httpbuf3[] = "ata is c0oL!";
3246  uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
3247 
3248  uint8_t httpbuf4[] = "HTTP/1.0 200 OK\r\nServer: VictorServer/1.0\r\n\r\n";
3249  uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
3250  uint8_t httpbuf5[] = "post R";
3251  uint32_t httplen5 = sizeof(httpbuf5) - 1; /* minus the \0 */
3252  uint8_t httpbuf6[] = "esults are tha bomb!";
3253  uint32_t httplen6 = sizeof(httpbuf6) - 1; /* minus the \0 */
3254 
3255  TcpSession ssn;
3256  memset(&ssn, 0, sizeof(ssn));
3257 
3260 
3261  Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
3262  FAIL_IF_NULL(f);
3263  f->protoctx = &ssn;
3264  f->proto = IPPROTO_TCP;
3265  f->alproto = ALPROTO_HTTP1;
3266 
3267  StreamTcpInitConfig(true);
3268 
3269  int r = AppLayerParserParse(
3270  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_START, httpbuf1, httplen1);
3271  FAIL_IF(r != 0);
3272 
3273  r = AppLayerParserParse(
3274  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_START, httpbuf4, httplen4);
3275  FAIL_IF(r != 0);
3276 
3277  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOCLIENT, httpbuf5, httplen5);
3278  FAIL_IF(r != 0);
3279 
3280  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
3281  FAIL_IF(r != 0);
3282 
3283  r = AppLayerParserParse(
3284  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_EOF, httpbuf3, httplen3);
3285  FAIL_IF(r != 0);
3286 
3287  r = AppLayerParserParse(
3288  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_EOF, httpbuf6, httplen6);
3289  FAIL_IF(r != 0);
3290 
3291  HtpState *http_state = f->alstate;
3292  FAIL_IF_NULL(http_state);
3293 
3294  htp_tx_t *tx = HTPStateGetTx(http_state, 0);
3295  FAIL_IF_NULL(tx);
3298 
3299  const htp_header_t *h = htp_tx_request_header_index(tx, 0);
3300  FAIL_IF_NULL(h);
3301 
3303 
3305  StreamTcpFreeConfig(true);
3306  UTHFreeFlow(f);
3307  PASS;
3308 }
3309 
3310 /** \test Test proper chunked encoded response body
3311  */
3312 static int HTPParserTest06(void)
3313 {
3314  uint8_t httpbuf1[] = "GET /ld/index.php?id=412784631&cid=0064&version=4&"
3315  "name=try HTTP/1.1\r\nAccept: */*\r\nUser-Agent: "
3316  "LD-agent\r\nHost: 209.205.196.16\r\n\r\n";
3317  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
3318  uint8_t httpbuf2[] = "HTTP/1.1 200 OK\r\nDate: Sat, 03 Oct 2009 10:16:02 "
3319  "GMT\r\n"
3320  "Server: Apache/1.3.37 (Unix) mod_ssl/2.8.28 "
3321  "OpenSSL/0.9.7a PHP/4.4.7 mod_perl/1.29 "
3322  "FrontPage/5.0.2.2510\r\n"
3323  "X-Powered-By: PHP/4.4.7\r\nTransfer-Encoding: "
3324  "chunked\r\n"
3325  "Content-Type: text/html\r\n\r\n"
3326  "580\r\n"
3327  "W2dyb3VwMV0NCnBob25lMT1wMDB3ODgyMTMxMzAyMTINCmxvZ2lu"
3328  "MT0NCnBhc3N3b3JkMT0NCnBob25lMj1wMDB3ODgyMTMxMzAyMTIN"
3329  "CmxvZ2luMj0NCnBhc3N3b3JkMj0NCnBob25lMz0NCmxvZ2luMz0N"
3330  "CnBhc3N3b3JkMz0NCnBob25lND0NCmxvZ2luND0NCnBhc3N3b3Jk"
3331  "ND0NCnBob25lNT0NCmxvZ2luNT0NCnBhc3N3b3JkNT0NCnBob25l"
3332  "Nj0NCmxvZ2luNj0NCnBhc3N3b3JkNj0NCmNhbGxfdGltZTE9MzIN"
3333  "CmNhbGxfdGltZTI9MjMyDQpkYXlfbGltaXQ9NQ0KbW9udGhfbGlt"
3334  "aXQ9MTUNCltncm91cDJdDQpwaG9uZTE9DQpsb2dpbjE9DQpwYXNz"
3335  "d29yZDE9DQpwaG9uZTI9DQpsb2dpbjI9DQpwYXNzd29yZDI9DQpw"
3336  "aG9uZTM9DQpsb2dpbjM9DQpwYXNzd29yZDM9DQpwaG9uZTQ9DQps"
3337  "b2dpbjQ9DQpwYXNzd29yZDQ9DQpwaG9uZTU9DQpsb2dpbjU9DQpw"
3338  "YXNzd29yZDU9DQpwaG9uZTY9DQpsb2dpbjY9DQpwYXNzd29yZDY9"
3339  "DQpjYWxsX3RpbWUxPQ0KY2FsbF90aW1lMj0NCmRheV9saW1pdD0N"
3340  "Cm1vbnRoX2xpbWl0PQ0KW2dyb3VwM10NCnBob25lMT0NCmxvZ2lu"
3341  "MT0NCnBhc3N3b3JkMT0NCnBob25lMj0NCmxvZ2luMj0NCnBhc3N3"
3342  "b3JkMj0NCnBob25lMz0NCmxvZ2luMz0NCnBhc3N3b3JkMz0NCnBo"
3343  "b25lND0NCmxvZ2luND0NCnBhc3N3b3JkND0NCnBob25lNT0NCmxv"
3344  "Z2luNT0NCnBhc3N3b3JkNT0NCnBob25lNj0NCmxvZ2luNj0NCnBh"
3345  "c3N3b3JkNj0NCmNhbGxfdGltZTE9DQpjYWxsX3RpbWUyPQ0KZGF5"
3346  "X2xpbWl0PQ0KbW9udGhfbGltaXQ9DQpbZ3JvdXA0XQ0KcGhvbmUx"
3347  "PQ0KbG9naW4xPQ0KcGFzc3dvcmQxPQ0KcGhvbmUyPQ0KbG9naW4y"
3348  "PQ0KcGFzc3dvcmQyPQ0KcGhvbmUzPQ0KbG9naW4zPQ0KcGFzc3dv"
3349  "cmQzPQ0KcGhvbmU0PQ0KbG9naW40PQ0KcGFzc3dvcmQ0PQ0KcGhv"
3350  "bmU1PQ0KbG9naW41PQ0KcGFzc3dvcmQ1PQ0KcGhvbmU2PQ0KbG9n"
3351  "aW42PQ0KcGFzc3dvcmQ2PQ0KY2FsbF90aW1lMT0NCmNhbGxfdGlt"
3352  "ZTI9DQpkYXlfbGltaXQ9DQptb250aF9saW1pdD0NCltmaWxlc10N"
3353  "Cmxpbms9aHR0cDovLzIwOS4yMDUuMTk2LjE2L2xkL2dldGJvdC5w"
3354  "aHA=\r\n0\r\n\r\n";
3355  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
3356  TcpSession ssn;
3357 
3360 
3361  memset(&ssn, 0, sizeof(ssn));
3362 
3363  Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
3364  FAIL_IF_NULL(f);
3365  f->protoctx = &ssn;
3366  f->proto = IPPROTO_TCP;
3367  f->alproto = ALPROTO_HTTP1;
3368 
3369  StreamTcpInitConfig(true);
3370 
3371  int r = AppLayerParserParse(
3372  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_START, httpbuf1, httplen1);
3373  FAIL_IF(r != 0);
3374  r = AppLayerParserParse(
3375  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_START, httpbuf2, httplen2);
3376  FAIL_IF(r != 0);
3377 
3378  HtpState *http_state = f->alstate;
3379  FAIL_IF_NULL(http_state);
3380 
3381  htp_tx_t *tx = HTPStateGetTx(http_state, 0);
3382  FAIL_IF_NULL(tx);
3383 
3386 
3389 
3390  const htp_header_t *h = htp_tx_request_header_index(tx, 0);
3391  FAIL_IF_NULL(h);
3392 
3394  StreamTcpFreeConfig(true);
3395  UTHFreeFlow(f);
3396  PASS;
3397 }
3398 
3399 /** \test
3400  */
3401 static int HTPParserTest07(void)
3402 {
3403  Flow *f = NULL;
3404  uint8_t httpbuf1[] = "GET /awstats.pl?/migratemigrate%20=%20| HTTP/1.0\r\n\r\n";
3405  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
3406  TcpSession ssn;
3407  HtpState *htp_state = NULL;
3409 
3410  memset(&ssn, 0, sizeof(ssn));
3411 
3412  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
3413  FAIL_IF_NULL(f);
3414  f->protoctx = &ssn;
3415  f->proto = IPPROTO_TCP;
3416  f->alproto = ALPROTO_HTTP1;
3417 
3418  StreamTcpInitConfig(true);
3419 
3420  uint32_t u;
3421  for (u = 0; u < httplen1; u++) {
3422  uint8_t flags = 0;
3423 
3424  if (u == 0)
3425  flags = STREAM_TOSERVER|STREAM_START;
3426  else if (u == (httplen1 - 1))
3427  flags = STREAM_TOSERVER|STREAM_EOF;
3428  else
3429  flags = STREAM_TOSERVER;
3430 
3431  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, flags, &httpbuf1[u], 1);
3432  FAIL_IF(r != 0);
3433  }
3434 
3435  htp_state = f->alstate;
3436  FAIL_IF_NULL(htp_state);
3437 
3438  uint8_t ref[] = "/awstats.pl?/migratemigrate = |";
3439  size_t reflen = sizeof(ref) - 1;
3440 
3441  htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3442  FAIL_IF_NULL(tx);
3443  HtpTxUserData *tx_ud = (HtpTxUserData *)htp_tx_get_user_data(tx);
3444 
3445  FAIL_IF_NULL(tx_ud);
3447  FAIL_IF(reflen != bstr_len(tx_ud->request_uri_normalized));
3448 
3449  FAIL_IF(memcmp(bstr_ptr(tx_ud->request_uri_normalized), ref,
3450  bstr_len(tx_ud->request_uri_normalized)) != 0);
3451 
3453  StreamTcpFreeConfig(true);
3454  UTHFreeFlow(f);
3455  PASS;
3456 }
3457 
3458 #include "conf-yaml-loader.h"
3459 
3460 /** \test Abort
3461  */
3462 static int HTPParserTest08(void)
3463 {
3464  Flow *f = NULL;
3465  uint8_t httpbuf1[] = "GET /secondhouse/image/js/\%ce\%de\%ce\%fd_RentCity.js?v=2011.05.02 HTTP/1.0\r\n\r\n";
3466  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
3467  TcpSession ssn;
3469 
3470  char input[] = "\
3471 %YAML 1.1\n\
3472 ---\n\
3473 libhtp:\n\
3474 \n\
3475  default-config:\n\
3476  personality: IDS\n\
3477 ";
3478 
3480  ConfInit();
3482 
3483  ConfYamlLoadString(input, strlen(input));
3484  HTPConfigure();
3485 
3486  HtpState *htp_state = NULL;
3487  memset(&ssn, 0, sizeof(ssn));
3488 
3489  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
3490  FAIL_IF_NULL(f);
3491  f->protoctx = &ssn;
3492  f->proto = IPPROTO_TCP;
3493  f->alproto = ALPROTO_HTTP1;
3494 
3495  StreamTcpInitConfig(true);
3496 
3497  uint8_t flags = STREAM_TOSERVER | STREAM_START | STREAM_EOF;
3498 
3499  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, flags, httpbuf1, httplen1);
3500  FAIL_IF(r != 0);
3501 
3502  htp_state = f->alstate;
3503  FAIL_IF_NULL(htp_state);
3504 
3505  htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3506  FAIL_IF_NULL(tx);
3507  HtpTxUserData *tx_ud = (HtpTxUserData *) htp_tx_get_user_data(tx);
3508  FAIL_IF_NULL(tx_ud);
3510  PrintRawDataFp(stdout, bstr_ptr(tx_ud->request_uri_normalized),
3511  bstr_len(tx_ud->request_uri_normalized));
3512 
3514  StreamTcpFreeConfig(true);
3515  HTPFreeConfig();
3516  ConfDeInit();
3519  UTHFreeFlow(f);
3520  PASS;
3521 }
3522 
3523 /** \test Abort
3524  */
3525 static int HTPParserTest09(void)
3526 {
3527  Flow *f = NULL;
3528  uint8_t httpbuf1[] = "GET /secondhouse/image/js/\%ce\%de\%ce\%fd_RentCity.js?v=2011.05.02 HTTP/1.0\r\n\r\n";
3529  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
3530  TcpSession ssn;
3532 
3533  char input[] = "\
3534 %YAML 1.1\n\
3535 ---\n\
3536 libhtp:\n\
3537 \n\
3538  default-config:\n\
3539  personality: Apache_2_2\n\
3540 ";
3541 
3543  ConfInit();
3545 
3546  ConfYamlLoadString(input, strlen(input));
3547  HTPConfigure();
3548 
3549  HtpState *htp_state = NULL;
3550 
3551  memset(&ssn, 0, sizeof(ssn));
3552 
3553  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
3554  FAIL_IF_NULL(f);
3555  f->protoctx = &ssn;
3556  f->proto = IPPROTO_TCP;
3557  f->alproto = ALPROTO_HTTP1;
3558 
3559  StreamTcpInitConfig(true);
3560 
3561  uint8_t flags = STREAM_TOSERVER | STREAM_START | STREAM_EOF;
3562 
3563  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, flags, httpbuf1, httplen1);
3564  FAIL_IF(r != 0);
3565 
3566  htp_state = f->alstate;
3567  FAIL_IF_NULL(htp_state);
3568 
3569  htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3570  FAIL_IF_NULL(tx);
3571 
3572  HtpTxUserData *tx_ud = (HtpTxUserData *) htp_tx_get_user_data(tx);
3573  FAIL_IF_NULL(tx_ud);
3575  PrintRawDataFp(stdout, bstr_ptr(tx_ud->request_uri_normalized),
3576  bstr_len(tx_ud->request_uri_normalized));
3577 
3579  StreamTcpFreeConfig(true);
3580  HTPFreeConfig();
3581  ConfDeInit();
3584  UTHFreeFlow(f);
3585  PASS;
3586 }
3587 
3588 /** \test Host:www.google.com <- missing space between name:value (rfc violation)
3589  */
3590 static int HTPParserTest10(void)
3591 {
3592 
3593  Flow *f = NULL;
3594  uint8_t httpbuf1[] = "GET / HTTP/1.0\r\nHost:www.google.com\r\n\r\n";
3595  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
3596  TcpSession ssn;
3597  HtpState *htp_state = NULL;
3599 
3600  memset(&ssn, 0, sizeof(ssn));
3601 
3602  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
3603  FAIL_IF_NULL(f);
3604  f->protoctx = &ssn;
3605  f->proto = IPPROTO_TCP;
3606  f->alproto = ALPROTO_HTTP1;
3607 
3608  StreamTcpInitConfig(true);
3609 
3610  uint32_t u;
3611  for (u = 0; u < httplen1; u++) {
3612  uint8_t flags = 0;
3613 
3614  if (u == 0)
3615  flags = STREAM_TOSERVER|STREAM_START;
3616  else if (u == (httplen1 - 1))
3617  flags = STREAM_TOSERVER|STREAM_EOF;
3618  else
3619  flags = STREAM_TOSERVER;
3620 
3621  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, flags, &httpbuf1[u], 1);
3622  FAIL_IF(r != 0);
3623  }
3624 
3625  htp_state = f->alstate;
3626  FAIL_IF_NULL(htp_state);
3627 
3628  htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3629  const htp_header_t *h = htp_tx_request_header_index(tx, 0);
3630  FAIL_IF_NULL(h);
3631 
3632  char *name = bstr_util_strdup_to_c(htp_header_name(h));
3633  FAIL_IF_NULL(name);
3634  FAIL_IF(strcmp(name, "Host") != 0);
3635 
3636  char *value = bstr_util_strdup_to_c(htp_header_value(h));
3637  FAIL_IF_NULL(value);
3638  FAIL_IF(strcmp(value, "www.google.com") != 0);
3639 
3641  StreamTcpFreeConfig(true);
3642  UTHFreeFlow(f);
3643  SCFree(name);
3644  SCFree(value);
3645  PASS;
3646 }
3647 
3648 /** \test double encoding in path
3649  */
3650 static int HTPParserTest11(void)
3651 {
3652  Flow *f = NULL;
3653  uint8_t httpbuf1[] = "GET /%2500 HTTP/1.0\r\n\r\n";
3654  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
3655  TcpSession ssn;
3656  HtpState *htp_state = NULL;
3658 
3659  memset(&ssn, 0, sizeof(ssn));
3660 
3661  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
3662  FAIL_IF_NULL(f);
3663  f->protoctx = &ssn;
3664  f->proto = IPPROTO_TCP;
3665  f->alproto = ALPROTO_HTTP1;
3666 
3667  StreamTcpInitConfig(true);
3668 
3669  uint32_t u;
3670  for (u = 0; u < httplen1; u++) {
3671  uint8_t flags = 0;
3672 
3673  if (u == 0)
3674  flags = STREAM_TOSERVER|STREAM_START;
3675  else if (u == (httplen1 - 1))
3676  flags = STREAM_TOSERVER|STREAM_EOF;
3677  else
3678  flags = STREAM_TOSERVER;
3679 
3680  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, flags, &httpbuf1[u], 1);
3681  FAIL_IF(r != 0);
3682  }
3683 
3684  htp_state = f->alstate;
3685  FAIL_IF_NULL(htp_state);
3686 
3687  htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3688  FAIL_IF_NULL(tx);
3689 
3690  HtpTxUserData *tx_ud = (HtpTxUserData *)htp_tx_get_user_data(tx);
3691  FAIL_IF_NULL(tx_ud);
3693 
3694  FAIL_IF(bstr_len(tx_ud->request_uri_normalized) != 4);
3695 
3696  FAIL_IF(bstr_ptr(tx_ud->request_uri_normalized)[0] != '/');
3697  FAIL_IF(bstr_ptr(tx_ud->request_uri_normalized)[1] != '%');
3698  FAIL_IF(bstr_ptr(tx_ud->request_uri_normalized)[2] != '0');
3699  FAIL_IF(bstr_ptr(tx_ud->request_uri_normalized)[3] != '0');
3700 
3702  StreamTcpFreeConfig(true);
3703  UTHFreeFlow(f);
3704  PASS;
3705 }
3706 
3707 /** \test double encoding in query
3708  */
3709 static int HTPParserTest12(void)
3710 {
3711  Flow *f = NULL;
3712  uint8_t httpbuf1[] = "GET /?a=%2500 HTTP/1.0\r\n\r\n";
3713  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
3714  TcpSession ssn;
3715  HtpState *htp_state = NULL;
3717 
3718  memset(&ssn, 0, sizeof(ssn));
3719 
3720  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
3721  FAIL_IF_NULL(f);
3722  f->protoctx = &ssn;
3723  f->proto = IPPROTO_TCP;
3724  f->alproto = ALPROTO_HTTP1;
3725 
3726  StreamTcpInitConfig(true);
3727 
3728  uint32_t u;
3729  for (u = 0; u < httplen1; u++) {
3730  uint8_t flags = 0;
3731 
3732  if (u == 0)
3733  flags = STREAM_TOSERVER|STREAM_START;
3734  else if (u == (httplen1 - 1))
3735  flags = STREAM_TOSERVER|STREAM_EOF;
3736  else
3737  flags = STREAM_TOSERVER;
3738 
3739  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, flags, &httpbuf1[u], 1);
3740  FAIL_IF(r != 0);
3741  }
3742 
3743  htp_state = f->alstate;
3744  FAIL_IF_NULL(htp_state);
3745 
3746  htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3747  FAIL_IF_NULL(tx);
3748  HtpTxUserData *tx_ud = (HtpTxUserData *) htp_tx_get_user_data(tx);
3749  FAIL_IF_NULL(tx_ud);
3751 
3752  FAIL_IF(bstr_len(tx_ud->request_uri_normalized) != 7);
3753 
3754  FAIL_IF(bstr_ptr(tx_ud->request_uri_normalized)[0] != '/');
3755  FAIL_IF(bstr_ptr(tx_ud->request_uri_normalized)[1] != '?');
3756  FAIL_IF(bstr_ptr(tx_ud->request_uri_normalized)[2] != 'a');
3757  FAIL_IF(bstr_ptr(tx_ud->request_uri_normalized)[3] != '=');
3758  FAIL_IF(bstr_ptr(tx_ud->request_uri_normalized)[4] != '%');
3759  FAIL_IF(bstr_ptr(tx_ud->request_uri_normalized)[5] != '0');
3760  FAIL_IF(bstr_ptr(tx_ud->request_uri_normalized)[6] != '0');
3761 
3763  StreamTcpFreeConfig(true);
3764  UTHFreeFlow(f);
3765  PASS;
3766 }
3767 
3768 /** \test Host:www.google.com0dName: Value0d0a <- missing space between name:value (rfc violation)
3769  */
3770 static int HTPParserTest13(void)
3771 {
3772  Flow *f = NULL;
3773  uint8_t httpbuf1[] = "GET / HTTP/1.0\r\nHost:www.google.com\rName: Value\r\n\r\n";
3774  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
3775  TcpSession ssn;
3776  HtpState *htp_state = NULL;
3778 
3779  memset(&ssn, 0, sizeof(ssn));
3780 
3781  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
3782  FAIL_IF_NULL(f);
3783  f->protoctx = &ssn;
3784  f->proto = IPPROTO_TCP;
3785  f->alproto = ALPROTO_HTTP1;
3786 
3787  StreamTcpInitConfig(true);
3788 
3789  uint32_t u;
3790  for (u = 0; u < httplen1; u++) {
3791  uint8_t flags = 0;
3792 
3793  if (u == 0)
3794  flags = STREAM_TOSERVER|STREAM_START;
3795  else if (u == (httplen1 - 1))
3796  flags = STREAM_TOSERVER|STREAM_EOF;
3797  else
3798  flags = STREAM_TOSERVER;
3799 
3800  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, flags, &httpbuf1[u], 1);
3801  FAIL_IF(r != 0);
3802  }
3803 
3804  htp_state = f->alstate;
3805  FAIL_IF_NULL(htp_state);
3806  htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3807  const htp_header_t *h = htp_tx_request_header_index(tx, 0);
3808  FAIL_IF_NULL(h);
3809 
3810  char *name = bstr_util_strdup_to_c(htp_header_name(h));
3811  FAIL_IF_NULL(name);
3812  FAIL_IF(strcmp(name, "Host") != 0);
3813 
3814  char *value = bstr_util_strdup_to_c(htp_header_value(h));
3815  FAIL_IF_NULL(value);
3816  FAIL_IF(strcmp(value, "www.google.com\rName: Value") != 0);
3817 
3819  StreamTcpFreeConfig(true);
3820  UTHFreeFlow(f);
3821  SCFree(name);
3822  SCFree(value);
3823 
3824  PASS;
3825 }
3826 
3827 /** \test Test basic config */
3828 static int HTPParserConfigTest01(void)
3829 {
3830  char input[] = "\
3831 %YAML 1.1\n\
3832 ---\n\
3833 libhtp:\n\
3834 \n\
3835  default-config:\n\
3836  personality: IDS\n\
3837 \n\
3838  server-config:\n\
3839 \n\
3840  - apache-tomcat:\n\
3841  address: [192.168.1.0/24, 127.0.0.0/8, \"::1\"]\n\
3842  personality: Tomcat_6_0\n\
3843 \n\
3844  - iis7:\n\
3845  address: \n\
3846  - 192.168.0.0/24\n\
3847  - 192.168.10.0/24\n\
3848  personality: IIS_7_0\n\
3849 ";
3850 
3852  ConfInit();
3853 
3854  ConfYamlLoadString(input, strlen(input));
3855 
3856  ConfNode *outputs;
3857  outputs = ConfGetNode("libhtp.default-config.personality");
3858  FAIL_IF_NULL(outputs);
3859 
3860  outputs = ConfGetNode("libhtp.server-config");
3861  FAIL_IF_NULL(outputs);
3862 
3863  ConfNode *node = TAILQ_FIRST(&outputs->head);
3864  FAIL_IF_NULL(node);
3865  FAIL_IF(strcmp(node->name, "0") != 0);
3866  node = TAILQ_FIRST(&node->head);
3867  FAIL_IF_NULL(node);
3868  FAIL_IF(strcmp(node->name, "apache-tomcat") != 0);
3869 
3870  int i = 0;
3871  ConfNode *n;
3872 
3873  ConfNode *node2 = ConfNodeLookupChild(node, "personality");
3874  FAIL_IF_NULL(node2);
3875  FAIL_IF(strcmp(node2->val, "Tomcat_6_0") != 0);
3876 
3877  node = ConfNodeLookupChild(node, "address");
3878  FAIL_IF_NULL(node);
3879 
3880  TAILQ_FOREACH (n, &node->head, next) {
3881  FAIL_IF_NULL(n);
3882  switch(i) {
3883  case 0:
3884  FAIL_IF(strcmp(n->name, "0") != 0);
3885  FAIL_IF(strcmp(n->val, "192.168.1.0/24") != 0);
3886  break;
3887  case 1:
3888  FAIL_IF(strcmp(n->name, "1") != 0);
3889  FAIL_IF(strcmp(n->val, "127.0.0.0/8") != 0);
3890  break;
3891  case 2:
3892  FAIL_IF(strcmp(n->name, "2") != 0);
3893  FAIL_IF(strcmp(n->val, "::1") != 0);
3894  break;
3895  default:
3896  FAIL;
3897  }
3898  i++;
3899  }
3900 
3901  outputs = ConfGetNode("libhtp.server-config");
3902  FAIL_IF_NULL(outputs);
3903  node = TAILQ_FIRST(&outputs->head);
3904  node = TAILQ_NEXT(node, next);
3905  FAIL_IF_NULL(node);
3906  FAIL_IF(strcmp(node->name, "1") != 0);
3907  node = TAILQ_FIRST(&node->head);
3908  FAIL_IF_NULL(node);
3909  FAIL_IF(strcmp(node->name, "iis7") != 0);
3910 
3911  node2 = ConfNodeLookupChild(node, "personality");
3912  FAIL_IF_NULL(node2);
3913  FAIL_IF(strcmp(node2->val, "IIS_7_0") != 0);
3914 
3915  node = ConfNodeLookupChild(node, "address");
3916  FAIL_IF_NULL(node);
3917 
3918  i = 0;
3919  TAILQ_FOREACH(n, &node->head, next) {
3920  FAIL_IF_NULL(n);
3921 
3922  switch(i) {
3923  case 0:
3924  FAIL_IF(strcmp(n->name, "0") != 0);
3925  FAIL_IF(strcmp(n->val, "192.168.0.0/24") != 0);
3926  break;
3927  case 1:
3928  FAIL_IF(strcmp(n->name, "1") != 0);
3929  FAIL_IF(strcmp(n->val, "192.168.10.0/24") != 0);
3930  break;
3931  default:
3932  FAIL;
3933  }
3934  i++;
3935  }
3936 
3937  ConfDeInit();
3939 
3940  PASS;
3941 }
3942 
3943 /** \test Test config builds radix correctly */
3944 static int HTPParserConfigTest02(void)
3945 {
3946  char input[] = "\
3947 %YAML 1.1\n\
3948 ---\n\
3949 libhtp:\n\
3950 \n\
3951  default-config:\n\
3952  personality: IDS\n\
3953 \n\
3954  server-config:\n\
3955 \n\
3956  - apache-tomcat:\n\
3957  address: [192.168.1.0/24, 127.0.0.0/8, \"::1\"]\n\
3958  personality: Tomcat_6_0\n\
3959 \n\
3960  - iis7:\n\
3961  address: \n\
3962  - 192.168.0.0/24\n\
3963  - 192.168.10.0/24\n\
3964  personality: IIS_7_0\n\
3965 ";
3966 
3968  ConfInit();
3970  ConfYamlLoadString(input, strlen(input));
3971  HTPConfigure();
3972  FAIL_IF_NULL(cfglist.cfg);
3973  FAIL_IF_NULL(cfgtree.ipv4.head);
3974  FAIL_IF_NULL(cfgtree.ipv6.head);
3975 
3976  htp_cfg_t *htp = cfglist.cfg;
3977  uint8_t buf[128];
3978  const char *addr;
3979  void *user_data = NULL;
3980 
3981  addr = "192.168.10.42";
3982  FAIL_IF(inet_pton(AF_INET, addr, buf) != 1);
3983  (void)SCRadix4TreeFindBestMatch(&cfgtree.ipv4, buf, &user_data);
3984  FAIL_IF_NULL(user_data);
3985  HTPCfgRec *htp_cfg_rec = user_data;
3986  htp = htp_cfg_rec->cfg;
3987  FAIL_IF_NULL(htp);
3988  SCLogDebug("LIBHTP using config: %p", htp);
3989 
3990  user_data = NULL;
3991  addr = "::1";
3992  FAIL_IF(inet_pton(AF_INET6, addr, buf) != 1);
3993  (void)SCRadix6TreeFindBestMatch(&cfgtree.ipv6, buf, &user_data);
3994  FAIL_IF_NULL(user_data);
3995  htp_cfg_rec = user_data;
3996  htp = htp_cfg_rec->cfg;
3997  FAIL_IF_NULL(htp);
3998  SCLogDebug("LIBHTP using config: %p", htp);
3999 
4000  HTPFreeConfig();
4001  ConfDeInit();
4004 
4005  PASS;
4006 }
4007 
4008 /** \test Test traffic is handled by the correct htp config */
4009 static int HTPParserConfigTest03(void)
4010 {
4011  Flow *f = NULL;
4012  uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Victor/1.0\r\n\r\nPost"
4013  " Data is c0oL!";
4014  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
4015  TcpSession ssn;
4017 
4018  HtpState *htp_state = NULL;
4019  char input[] = "\
4020 %YAML 1.1\n\
4021 ---\n\
4022 libhtp:\n\
4023 \n\
4024  default-config:\n\
4025  personality: IDS\n\
4026 \n\
4027  server-config:\n\
4028 \n\
4029  - apache-tomcat:\n\
4030  address: [192.168.1.0/24, 127.0.0.0/8, \"::1\"]\n\
4031  personality: Tomcat_6_0\n\
4032 \n\
4033  - iis7:\n\
4034  address: \n\
4035  - 192.168.0.0/24\n\
4036  - 192.168.10.0/24\n\
4037  personality: IIS_7_0\n\
4038 ";
4039 
4041  ConfInit();
4043 
4044  ConfYamlLoadString(input, strlen(input));
4045 
4046  HTPConfigure();
4047 
4048  const char *addr = "192.168.10.42";
4049 
4050  memset(&ssn, 0, sizeof(ssn));
4051 
4052  f = UTHBuildFlow(AF_INET, "1.2.3.4", addr, 1024, 80);
4053  FAIL_IF_NULL(f);
4054  f->protoctx = &ssn;
4055  f->proto = IPPROTO_TCP;
4056  f->alproto = ALPROTO_HTTP1;
4057 
4058  htp_cfg_t *htp = cfglist.cfg;
4059  FAIL_IF_NULL(htp);
4060 
4061  void *user_data = NULL;
4062  (void)SCRadix4TreeFindBestMatch(&cfgtree.ipv4, (uint8_t *)f->dst.addr_data32, &user_data);
4063  FAIL_IF_NULL(user_data);
4064 
4065  HTPCfgRec *htp_cfg_rec = user_data;
4066  htp = htp_cfg_rec->cfg;
4067  FAIL_IF_NULL(user_data);
4068  SCLogDebug("LIBHTP using config: %p", htp);
4069 
4070  StreamTcpInitConfig(true);
4071 
4072  uint32_t u;
4073  for (u = 0; u < httplen1; u++) {
4074  uint8_t flags = 0;
4075 
4076  if (u == 0) flags = STREAM_TOSERVER|STREAM_START;
4077  else if (u == (httplen1 - 1)) flags = STREAM_TOSERVER|STREAM_EOF;
4078  else flags = STREAM_TOSERVER;
4079 
4080  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, flags, &httpbuf1[u], 1);
4081  FAIL_IF(r != 0);
4082  }
4083 
4084  htp_state = f->alstate;
4085  FAIL_IF_NULL(htp_state);
4086 
4087  FAIL_IF(HTPStateGetTxCnt(htp_state) != 2);
4088 
4089  htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4090  FAIL_IF_NULL(tx);
4091  FAIL_IF(tx->cfg != htp);
4092 
4093  tx = HTPStateGetTx(htp_state, 1);
4094  FAIL_IF_NULL(tx);
4095  FAIL_IF(tx->cfg != htp);
4096 
4098  HTPFreeConfig();
4099  ConfDeInit();
4102 
4103  StreamTcpFreeConfig(true);
4104  UTHFreeFlow(f);
4105  PASS;
4106 }
4107 
4108 /** \test Test %2f decoding in profile Apache_2_2
4109  *
4110  * %2f in path is left untouched
4111  * %2f in query string is normalized to %2F
4112  * %252f in query string is decoded/normalized to %2F
4113  */
4114 static int HTPParserDecodingTest01(void)
4115 {
4116  uint8_t httpbuf1[] =
4117  "GET /abc%2fdef HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
4118  "GET /abc/def?ghi%2fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
4119  "GET /abc/def?ghi%252fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
4120  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
4121  TcpSession ssn;
4124 
4125  char input[] = "\
4126 %YAML 1.1\n\
4127 ---\n\
4128 libhtp:\n\
4129 \n\
4130  default-config:\n\
4131  personality: Apache_2\n\
4132 ";
4133 
4135  ConfInit();
4137  ConfYamlLoadString(input, strlen(input));
4138  HTPConfigure();
4139  const char *addr = "4.3.2.1";
4140  memset(&ssn, 0, sizeof(ssn));
4141 
4142  Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", addr, 1024, 80);
4143  FAIL_IF_NULL(f);
4144  f->protoctx = &ssn;
4145  f->proto = IPPROTO_TCP;
4146  f->alproto = ALPROTO_HTTP1;
4147 
4148  StreamTcpInitConfig(true);
4149 
4150  for (uint32_t u = 0; u < httplen1; u++) {
4151  uint8_t flags = 0;
4152  if (u == 0) flags = STREAM_TOSERVER|STREAM_START;
4153  else if (u == (httplen1 - 1)) flags = STREAM_TOSERVER|STREAM_EOF;
4154  else flags = STREAM_TOSERVER;
4155 
4156  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, flags, &httpbuf1[u], 1);
4157  FAIL_IF(r != 0);
4158  }
4159 
4160  HtpState *htp_state = f->alstate;
4161  FAIL_IF_NULL(htp_state);
4162 
4163  uint8_t ref1[] = "/abc%2fdef";
4164  size_t reflen = sizeof(ref1) - 1;
4165 
4166  htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4167  FAIL_IF_NULL(tx);
4168 
4169  HtpTxUserData *tx_ud = (HtpTxUserData *)htp_tx_get_user_data(tx);
4170  FAIL_IF_NULL(tx_ud);
4172  FAIL_IF(reflen != bstr_len(tx_ud->request_uri_normalized));
4173  FAIL_IF(memcmp(bstr_ptr(tx_ud->request_uri_normalized), ref1,
4174  bstr_len(tx_ud->request_uri_normalized)) != 0);
4175 
4176  uint8_t ref2[] = "/abc/def?ghi/jkl";
4177  reflen = sizeof(ref2) - 1;
4178 
4179  tx = HTPStateGetTx(htp_state, 1);
4180  FAIL_IF_NULL(tx);
4181  tx_ud = (HtpTxUserData *)htp_tx_get_user_data(tx);
4182  FAIL_IF_NULL(tx_ud);
4184  FAIL_IF(reflen != bstr_len(tx_ud->request_uri_normalized));
4185 
4186  FAIL_IF(memcmp(bstr_ptr(tx_ud->request_uri_normalized), ref2,
4187  bstr_len(tx_ud->request_uri_normalized)) != 0);
4188 
4189  uint8_t ref3[] = "/abc/def?ghi%2fjkl";
4190  reflen = sizeof(ref3) - 1;
4191  tx = HTPStateGetTx(htp_state, 2);
4192  FAIL_IF_NULL(tx);
4193  tx_ud = (HtpTxUserData *) htp_tx_get_user_data(tx);
4194  FAIL_IF_NULL(tx_ud);
4196  FAIL_IF(reflen != bstr_len(tx_ud->request_uri_normalized));
4197 
4198  FAIL_IF(memcmp(bstr_ptr(tx_ud->request_uri_normalized), ref3,
4199  bstr_len(tx_ud->request_uri_normalized)) != 0);
4200 
4202  HTPFreeConfig();
4203  ConfDeInit();
4206 
4207  StreamTcpFreeConfig(true);
4208  UTHFreeFlow(f);
4209  PASS;
4210 }
4211 
4212 static int HTPParserDecodingTest01a(void)
4213 {
4214  uint8_t httpbuf1[] = "GET /abc%2fdef HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
4215  "GET /abc/def?ghi%2fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
4216  "GET /abc/def?ghi%252fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
4217  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
4218  TcpSession ssn;
4221 
4222  char input[] = "\
4223 %YAML 1.1\n\
4224 ---\n\
4225 libhtp:\n\
4226 \n\
4227  default-config:\n\
4228  personality: Apache_2\n\
4229 ";
4230 
4232  ConfInit();
4234  ConfYamlLoadString(input, strlen(input));
4235  HTPConfigure();
4236  const char *addr = "4.3.2.1";
4237  memset(&ssn, 0, sizeof(ssn));
4238 
4239  Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", addr, 1024, 80);
4240  FAIL_IF_NULL(f);
4241  f->protoctx = &ssn;
4242  f->proto = IPPROTO_TCP;
4243  f->alproto = ALPROTO_HTTP1;
4244 
4245  StreamTcpInitConfig(true);
4246 
4247  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1,
4248  (STREAM_TOSERVER | STREAM_START | STREAM_EOF), httpbuf1, httplen1);
4249  FAIL_IF(r != 0);
4250 
4251  HtpState *htp_state = f->alstate;
4252  FAIL_IF_NULL(htp_state);
4253 
4254  uint8_t ref1[] = "/abc%2fdef";
4255  size_t reflen = sizeof(ref1) - 1;
4256 
4257  htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4258  FAIL_IF_NULL(tx);
4259 
4260  HtpTxUserData *tx_ud = (HtpTxUserData *)htp_tx_get_user_data(tx);
4261  FAIL_IF_NULL(tx_ud);
4263  FAIL_IF(reflen != bstr_len(tx_ud->request_uri_normalized));
4264  FAIL_IF(memcmp(bstr_ptr(tx_ud->request_uri_normalized), ref1,
4265  bstr_len(tx_ud->request_uri_normalized)) != 0);
4266 
4267  uint8_t ref2[] = "/abc/def?ghi/jkl";
4268  reflen = sizeof(ref2) - 1;
4269 
4270  tx = HTPStateGetTx(htp_state, 1);
4271  FAIL_IF_NULL(tx);
4272  tx_ud = (HtpTxUserData *)htp_tx_get_user_data(tx);
4273  FAIL_IF_NULL(tx_ud);
4275  FAIL_IF(reflen != bstr_len(tx_ud->request_uri_normalized));
4276 
4277  FAIL_IF(memcmp(bstr_ptr(tx_ud->request_uri_normalized), ref2,
4278  bstr_len(tx_ud->request_uri_normalized)) != 0);
4279 
4280  uint8_t ref3[] = "/abc/def?ghi%2fjkl";
4281  reflen = sizeof(ref3) - 1;
4282  tx = HTPStateGetTx(htp_state, 2);
4283  FAIL_IF_NULL(tx);
4284  tx_ud = (HtpTxUserData *)htp_tx_get_user_data(tx);
4285  FAIL_IF_NULL(tx_ud);
4287  FAIL_IF(reflen != bstr_len(tx_ud->request_uri_normalized));
4288 
4289  FAIL_IF(memcmp(bstr_ptr(tx_ud->request_uri_normalized), ref3,
4290  bstr_len(tx_ud->request_uri_normalized)) != 0);
4291 
4293  HTPFreeConfig();
4294  ConfDeInit();
4297 
4298  StreamTcpFreeConfig(true);
4299  UTHFreeFlow(f);
4300  PASS;
4301 }
4302 
4303 /** \test Test %2f decoding in profile IDS
4304  *
4305  * %2f in path decoded to /
4306  * %2f in query string is decoded to /
4307  * %252f in query string is decoded to %2F
4308  */
4309 static int HTPParserDecodingTest02(void)
4310 {
4311  Flow *f = NULL;
4312  uint8_t httpbuf1[] =
4313  "GET /abc%2fdef HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
4314  "GET /abc/def?ghi%2fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
4315  "GET /abc/def?ghi%252fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
4316  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
4317  TcpSession ssn;
4319 
4320  HtpState *htp_state = NULL;
4321  char input[] = "\
4322 %YAML 1.1\n\
4323 ---\n\
4324 libhtp:\n\
4325 \n\
4326  default-config:\n\
4327  personality: IDS\n\
4328  double-decode-path: no\n\
4329  double-decode-query: no\n\
4330 ";
4331 
4333  ConfInit();
4335  ConfYamlLoadString(input, strlen(input));
4336  HTPConfigure();
4337  const char *addr = "4.3.2.1";
4338  memset(&ssn, 0, sizeof(ssn));
4339 
4340  f = UTHBuildFlow(AF_INET, "1.2.3.4", addr, 1024, 80);
4341  FAIL_IF_NULL(f);
4342  f->protoctx = &ssn;
4343  f->proto = IPPROTO_TCP;
4344  f->alproto = ALPROTO_HTTP1;
4345 
4346  StreamTcpInitConfig(true);
4347 
4348  uint32_t u;
4349  for (u = 0; u < httplen1; u++) {
4350  uint8_t flags = 0;
4351 
4352  if (u == 0) flags = STREAM_TOSERVER|STREAM_START;
4353  else if (u == (httplen1 - 1)) flags = STREAM_TOSERVER|STREAM_EOF;
4354  else flags = STREAM_TOSERVER;
4355 
4356  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, flags, &httpbuf1[u], 1);
4357  FAIL_IF(r != 0);
4358  }
4359 
4360  htp_state = f->alstate;
4361  FAIL_IF_NULL(htp_state);
4362 
4363  uint8_t ref1[] = "/abc/def";
4364  size_t reflen = sizeof(ref1) - 1;
4365 
4366  htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4367  FAIL_IF_NULL(tx);
4368  HtpTxUserData *tx_ud = (HtpTxUserData *)htp_tx_get_user_data(tx);
4369  FAIL_IF_NULL(tx_ud);
4371  FAIL_IF(reflen != bstr_len(tx_ud->request_uri_normalized));
4372  FAIL_IF(memcmp(bstr_ptr(tx_ud->request_uri_normalized), ref1,
4373  bstr_len(tx_ud->request_uri_normalized)) != 0);
4374 
4375  uint8_t ref2[] = "/abc/def?ghi/jkl";
4376  reflen = sizeof(ref2) - 1;
4377 
4378  tx = HTPStateGetTx(htp_state, 1);
4379  FAIL_IF_NULL(tx);
4380  tx_ud = (HtpTxUserData *)htp_tx_get_user_data(tx);
4381  FAIL_IF_NULL(tx_ud);
4383  FAIL_IF(reflen != bstr_len(tx_ud->request_uri_normalized));
4384 
4385  FAIL_IF(memcmp(bstr_ptr(tx_ud->request_uri_normalized), ref2,
4386  bstr_len(tx_ud->request_uri_normalized)) != 0);
4387 
4388  uint8_t ref3[] = "/abc/def?ghi%2fjkl";
4389  reflen = sizeof(ref3) - 1;
4390  tx = HTPStateGetTx(htp_state, 2);
4391  FAIL_IF_NULL(tx);
4392  tx_ud = (HtpTxUserData *)htp_tx_get_user_data(tx);
4393  FAIL_IF_NULL(tx_ud);
4395  FAIL_IF(reflen != bstr_len(tx_ud->request_uri_normalized));
4396 
4397  FAIL_IF(memcmp(bstr_ptr(tx_ud->request_uri_normalized), ref3,
4398  bstr_len(tx_ud->request_uri_normalized)) != 0);
4399 
4401  HTPFreeConfig();
4402  ConfDeInit();
4405 
4406  StreamTcpFreeConfig(true);
4407  UTHFreeFlow(f);
4408  PASS;
4409 }
4410 
4411 /** \test Test %2f decoding in profile IDS with double-decode-* options
4412  *
4413  * %252f in path decoded to /
4414  * %252f in query string is decoded to /
4415  */
4416 static int HTPParserDecodingTest03(void)
4417 {
4418  Flow *f = NULL;
4419  uint8_t httpbuf1[] =
4420  "GET /abc%252fdef HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
4421  "GET /abc/def?ghi%252fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
4422  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
4423  TcpSession ssn;
4425 
4426  HtpState *htp_state = NULL;
4427  char input[] = "\
4428 %YAML 1.1\n\
4429 ---\n\
4430 libhtp:\n\
4431 \n\
4432  default-config:\n\
4433  personality: IDS\n\
4434  double-decode-path: yes\n\
4435  double-decode-query: yes\n\
4436 ";
4437 
4439  ConfInit();
4441  ConfYamlLoadString(input, strlen(input));
4442  HTPConfigure();
4443  const char *addr = "4.3.2.1";
4444  memset(&ssn, 0, sizeof(ssn));
4445 
4446  f = UTHBuildFlow(AF_INET, "1.2.3.4", addr, 1024, 80);
4447  FAIL_IF_NULL(f);
4448  f->protoctx = &ssn;
4449  f->proto = IPPROTO_TCP;
4450  f->alproto = ALPROTO_HTTP1;
4451 
4452  StreamTcpInitConfig(true);
4453 
4454  uint32_t u;
4455  for (u = 0; u < httplen1; u++) {
4456  uint8_t flags = 0;
4457 
4458  if (u == 0) flags = STREAM_TOSERVER|STREAM_START;
4459  else if (u == (httplen1 - 1)) flags = STREAM_TOSERVER|STREAM_EOF;
4460  else flags = STREAM_TOSERVER;
4461 
4462  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, flags, &httpbuf1[u], 1);
4463  FAIL_IF(r != 0);
4464  }
4465 
4466  htp_state = f->alstate;
4467  FAIL_IF_NULL(htp_state);
4468 
4469  uint8_t ref1[] = "/abc/def";
4470  size_t reflen = sizeof(ref1) - 1;
4471 
4472  htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4473  FAIL_IF_NULL(tx);
4474  HtpTxUserData *tx_ud = (HtpTxUserData *) htp_tx_get_user_data(tx);
4475  FAIL_IF_NULL(tx_ud);
4477  FAIL_IF(reflen != bstr_len(tx_ud->request_uri_normalized));
4478 
4479  FAIL_IF(memcmp(bstr_ptr(tx_ud->request_uri_normalized), ref1,
4480  bstr_len(tx_ud->request_uri_normalized)) != 0);
4481 
4482  uint8_t ref2[] = "/abc/def?ghi/jkl";
4483  reflen = sizeof(ref2) - 1;
4484 
4485  tx = HTPStateGetTx(htp_state, 1);
4486  FAIL_IF_NULL(tx);
4487  tx_ud = (HtpTxUserData *)htp_tx_get_user_data(tx);
4488  FAIL_IF_NULL(tx_ud);
4490  FAIL_IF(reflen != bstr_len(tx_ud->request_uri_normalized));
4491 
4492  FAIL_IF(memcmp(bstr_ptr(tx_ud->request_uri_normalized), ref2,
4493  bstr_len(tx_ud->request_uri_normalized)) != 0);
4494 
4496  HTPFreeConfig();
4497  ConfDeInit();
4500 
4501  StreamTcpFreeConfig(true);
4502  UTHFreeFlow(f);
4503  PASS;
4504 }
4505 
4506 /** \test Test http:// in query profile IDS
4507  */
4508 static int HTPParserDecodingTest04(void)
4509 {
4510  Flow *f = NULL;
4511  uint8_t httpbuf1[] =
4512  "GET /abc/def?a=http://www.abc.com/ HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
4513  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
4514  TcpSession ssn;
4516 
4517  HtpState *htp_state = NULL;
4518  char input[] = "\
4519 %YAML 1.1\n\
4520 ---\n\
4521 libhtp:\n\
4522 \n\
4523  default-config:\n\
4524  personality: IDS\n\
4525  double-decode-path: yes\n\
4526  double-decode-query: yes\n\
4527 ";
4528 
4530  ConfInit();
4532  ConfYamlLoadString(input, strlen(input));
4533  HTPConfigure();
4534  const char *addr = "4.3.2.1";
4535  memset(&ssn, 0, sizeof(ssn));
4536 
4537  f = UTHBuildFlow(AF_INET, "1.2.3.4", addr, 1024, 80);
4538  FAIL_IF_NULL(f);
4539  f->protoctx = &ssn;
4540  f->proto = IPPROTO_TCP;
4541  f->alproto = ALPROTO_HTTP1;
4542 
4543  StreamTcpInitConfig(true);
4544 
4545  uint32_t u;
4546  for (u = 0; u < httplen1; u++) {
4547  uint8_t flags = 0;
4548 
4549  if (u == 0) flags = STREAM_TOSERVER|STREAM_START;
4550  else if (u == (httplen1 - 1)) flags = STREAM_TOSERVER|STREAM_EOF;
4551  else flags = STREAM_TOSERVER;
4552 
4553  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, flags, &httpbuf1[u], 1);
4554  FAIL_IF(r != 0);
4555  }
4556 
4557  htp_state = f->alstate;
4558  FAIL_IF_NULL(htp_state);
4559 
4560  uint8_t ref1[] = "/abc/def?a=http://www.abc.com/";
4561  size_t reflen = sizeof(ref1) - 1;
4562 
4563  htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4564  FAIL_IF_NULL(tx);
4565  HtpTxUserData *tx_ud = (HtpTxUserData *) htp_tx_get_user_data(tx);
4566  FAIL_IF_NULL(tx_ud);
4568  FAIL_IF(reflen != bstr_len(tx_ud->request_uri_normalized));
4569 
4570  FAIL_IF(memcmp(bstr_ptr(tx_ud->request_uri_normalized), ref1,
4571  bstr_len(tx_ud->request_uri_normalized)) != 0);
4572 
4574  HTPFreeConfig();
4575  ConfDeInit();
4578 
4579  StreamTcpFreeConfig(true);
4580  UTHFreeFlow(f);
4581  PASS;
4582 }
4583 
4584 /** \test Test \ char in query profile IDS. Bug 739
4585  */
4586 static int HTPParserDecodingTest05(void)
4587 {
4588  Flow *f = NULL;
4589  uint8_t httpbuf1[] =
4590  "GET /index?id=\\\"<script>alert(document.cookie)</script> HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
4591  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
4592  TcpSession ssn;
4594 
4595  HtpState *htp_state = NULL;
4596  char input[] = "\
4597 %YAML 1.1\n\
4598 ---\n\
4599 libhtp:\n\
4600 \n\
4601  default-config:\n\
4602  personality: IDS\n\
4603  double-decode-path: yes\n\
4604  double-decode-query: yes\n\
4605 ";
4606 
4608  ConfInit();
4610  ConfYamlLoadString(input, strlen(input));
4611  HTPConfigure();
4612  const char *addr = "4.3.2.1";
4613  memset(&ssn, 0, sizeof(ssn));
4614 
4615  f = UTHBuildFlow(AF_INET, "1.2.3.4", addr, 1024, 80);
4616  FAIL_IF_NULL(f);
4617  f->protoctx = &ssn;
4618  f->proto = IPPROTO_TCP;
4619  f->alproto = ALPROTO_HTTP1;
4620 
4621  StreamTcpInitConfig(true);
4622 
4623  uint32_t u;
4624  for (u = 0; u < httplen1; u++) {
4625  uint8_t flags = 0;
4626 
4627  if (u == 0) flags = STREAM_TOSERVER|STREAM_START;
4628  else if (u == (httplen1 - 1)) flags = STREAM_TOSERVER|STREAM_EOF;
4629  else flags = STREAM_TOSERVER;
4630 
4631  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, flags, &httpbuf1[u], 1);
4632  FAIL_IF(r != 0);
4633  }
4634 
4635  htp_state = f->alstate;
4636  FAIL_IF_NULL(htp_state);
4637 
4638  uint8_t ref1[] = "/index?id=\\\"<script>alert(document.cookie)</script>";
4639  size_t reflen = sizeof(ref1) - 1;
4640 
4641  htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4642  FAIL_IF_NULL(tx);
4643  HtpTxUserData *tx_ud = (HtpTxUserData *) htp_tx_get_user_data(tx);
4644  FAIL_IF_NULL(tx_ud);
4646  FAIL_IF(reflen != bstr_len(tx_ud->request_uri_normalized));
4647 
4648  FAIL_IF(memcmp(bstr_ptr(tx_ud->request_uri_normalized), ref1,
4649  bstr_len(tx_ud->request_uri_normalized)) != 0);
4650 
4652  HTPFreeConfig();
4653  ConfDeInit();
4656 
4657  StreamTcpFreeConfig(true);
4658  UTHFreeFlow(f);
4659  PASS;
4660 }
4661 
4662 /** \test Test + char in query. Bug 1035
4663  */
4664 static int HTPParserDecodingTest06(void)
4665 {
4666  Flow *f = NULL;
4667  uint8_t httpbuf1[] =
4668  "GET /put.php?ip=1.2.3.4&port=+6000 HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
4669  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
4670  TcpSession ssn;
4672 
4673  HtpState *htp_state = NULL;
4674  char input[] = "\
4675 %YAML 1.1\n\
4676 ---\n\
4677 libhtp:\n\
4678 \n\
4679  default-config:\n\
4680  personality: IDS\n\
4681  double-decode-path: yes\n\
4682  double-decode-query: yes\n\
4683 ";
4684 
4686  ConfInit();
4688  ConfYamlLoadString(input, strlen(input));
4689  HTPConfigure();
4690  const char *addr = "4.3.2.1";
4691  memset(&ssn, 0, sizeof(ssn));
4692 
4693  f = UTHBuildFlow(AF_INET, "1.2.3.4", addr, 1024, 80);
4694  FAIL_IF_NULL(f);
4695  f->protoctx = &ssn;
4696  f->proto = IPPROTO_TCP;
4697  f->alproto = ALPROTO_HTTP1;
4698 
4699  StreamTcpInitConfig(true);
4700 
4701  uint32_t u;
4702  for (u = 0; u < httplen1; u++) {
4703  uint8_t flags = 0;
4704 
4705  if (u == 0) flags = STREAM_TOSERVER|STREAM_START;
4706  else if (u == (httplen1 - 1)) flags = STREAM_TOSERVER|STREAM_EOF;
4707  else flags = STREAM_TOSERVER;
4708 
4709  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, flags, &httpbuf1[u], 1);
4710  FAIL_IF(r != 0);
4711  }
4712 
4713  htp_state = f->alstate;
4714  FAIL_IF_NULL(htp_state);
4715 
4716  uint8_t ref1[] = "/put.php?ip=1.2.3.4&port=+6000";
4717  size_t reflen = sizeof(ref1) - 1;
4718 
4719  htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4720  FAIL_IF_NULL(tx);
4721  HtpTxUserData *tx_ud = (HtpTxUserData *) htp_tx_get_user_data(tx);
4722  FAIL_IF_NULL(tx_ud);
4724  FAIL_IF(reflen != bstr_len(tx_ud->request_uri_normalized));
4725 
4726  FAIL_IF(memcmp(bstr_ptr(tx_ud->request_uri_normalized), ref1,
4727  bstr_len(tx_ud->request_uri_normalized)) != 0);
4728 
4730  HTPFreeConfig();
4731  ConfDeInit();
4734 
4735  StreamTcpFreeConfig(true);
4736  UTHFreeFlow(f);
4737  PASS;
4738 }
4739 
4740 /** \test Test + char in query. Bug 1035
4741  */
4742 static int HTPParserDecodingTest07(void)
4743 {
4744  Flow *f = NULL;
4745  uint8_t httpbuf1[] =
4746  "GET /put.php?ip=1.2.3.4&port=+6000 HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
4747  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
4748  TcpSession ssn;
4750 
4751  HtpState *htp_state = NULL;
4752  char input[] = "\
4753 %YAML 1.1\n\
4754 ---\n\
4755 libhtp:\n\
4756 \n\
4757  default-config:\n\
4758  personality: IDS\n\
4759  double-decode-path: yes\n\
4760  double-decode-query: yes\n\
4761  query-plusspace-decode: yes\n\
4762 ";
4763 
4765  ConfInit();
4767  ConfYamlLoadString(input, strlen(input));
4768  HTPConfigure();
4769  const char *addr = "4.3.2.1";
4770  memset(&ssn, 0, sizeof(ssn));
4771 
4772  f = UTHBuildFlow(AF_INET, "1.2.3.4", addr, 1024, 80);
4773  FAIL_IF_NULL(f);
4774  f->protoctx = &ssn;
4775  f->proto = IPPROTO_TCP;
4776  f->alproto = ALPROTO_HTTP1;
4777 
4778  StreamTcpInitConfig(true);
4779 
4780  uint32_t u;
4781  for (u = 0; u < httplen1; u++) {
4782  uint8_t flags = 0;
4783 
4784  if (u == 0) flags = STREAM_TOSERVER|STREAM_START;
4785  else if (u == (httplen1 - 1)) flags = STREAM_TOSERVER|STREAM_EOF;
4786  else flags = STREAM_TOSERVER;
4787 
4788  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, flags, &httpbuf1[u], 1);
4789  FAIL_IF(r != 0);
4790  }
4791 
4792  htp_state = f->alstate;
4793  FAIL_IF_NULL(htp_state);
4794 
4795  uint8_t ref1[] = "/put.php?ip=1.2.3.4&port= 6000";
4796  size_t reflen = sizeof(ref1) - 1;
4797 
4798  htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4799  FAIL_IF_NULL(tx);
4800  HtpTxUserData *tx_ud = (HtpTxUserData *) htp_tx_get_user_data(tx);
4801  FAIL_IF_NULL(tx_ud);
4803  FAIL_IF(reflen != bstr_len(tx_ud->request_uri_normalized));
4804 
4805  FAIL_IF(memcmp(bstr_ptr(tx_ud->request_uri_normalized), ref1,
4806  bstr_len(tx_ud->request_uri_normalized)) != 0);
4807 
4809  HTPFreeConfig();
4810  ConfDeInit();
4813 
4814  StreamTcpFreeConfig(true);
4815  UTHFreeFlow(f);
4816  PASS;
4817 }
4818 
4819 /** \test Test 'proxy' URI normalization. Ticket 1008
4820  */
4821 static int HTPParserDecodingTest08(void)
4822 {
4823  Flow *f = NULL;
4824  uint8_t httpbuf1[] =
4825  "GET http://suricata-ids.org/blah/ HTTP/1.1\r\nHost: suricata-ids.org\r\n\r\n";
4826  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
4827  TcpSession ssn;
4829 
4830  HtpState *htp_state = NULL;
4831  char input[] = "\
4832 %YAML 1.1\n\
4833 ---\n\
4834 libhtp:\n\
4835 \n\
4836  default-config:\n\
4837  personality: IDS\n\
4838 ";
4839 
4841  ConfInit();
4843  ConfYamlLoadString(input, strlen(input));
4844  HTPConfigure();
4845  const char *addr = "4.3.2.1";
4846  memset(&ssn, 0, sizeof(ssn));
4847 
4848  f = UTHBuildFlow(AF_INET, "1.2.3.4", addr, 1024, 80);
4849  FAIL_IF_NULL(f);
4850  f->protoctx = &ssn;
4851  f->proto = IPPROTO_TCP;
4852  f->alproto = ALPROTO_HTTP1;
4853 
4854  StreamTcpInitConfig(true);
4855 
4856  uint32_t u;
4857  for (u = 0; u < httplen1; u++) {
4858  uint8_t flags = 0;
4859 
4860  if (u == 0) flags = STREAM_TOSERVER|STREAM_START;
4861  else if (u == (httplen1 - 1)) flags = STREAM_TOSERVER|STREAM_EOF;
4862  else flags = STREAM_TOSERVER;
4863 
4864  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, flags, &httpbuf1[u], 1);
4865  FAIL_IF(r != 0);
4866  }
4867 
4868  htp_state = f->alstate;
4869  FAIL_IF_NULL(htp_state);
4870 
4871  uint8_t ref1[] = "/blah/";
4872  size_t reflen = sizeof(ref1) - 1;
4873 
4874  htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4875  FAIL_IF_NULL(tx);
4876  HtpTxUserData *tx_ud = (HtpTxUserData *) htp_tx_get_user_data(tx);
4877  FAIL_IF_NULL(tx_ud);
4879  FAIL_IF(reflen != bstr_len(tx_ud->request_uri_normalized));
4880 
4881  FAIL_IF(memcmp(bstr_ptr(tx_ud->request_uri_normalized), ref1,
4882  bstr_len(tx_ud->request_uri_normalized)) != 0);
4883 
4885  HTPFreeConfig();
4886  ConfDeInit();
4889 
4890  StreamTcpFreeConfig(true);
4891  UTHFreeFlow(f);
4892  PASS;
4893 }
4894 
4895 /** \test Test 'proxy' URI normalization. Ticket 1008
4896  */
4897 static int HTPParserDecodingTest09(void)
4898 {
4899  Flow *f = NULL;
4900  uint8_t httpbuf1[] =
4901  "GET http://suricata-ids.org/blah/ HTTP/1.1\r\nHost: suricata-ids.org\r\n\r\n";
4902  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
4903  TcpSession ssn;
4905 
4906  HtpState *htp_state = NULL;
4907  char input[] = "\
4908 %YAML 1.1\n\
4909 ---\n\
4910 libhtp:\n\
4911 \n\
4912  default-config:\n\
4913  personality: IDS\n\
4914  uri-include-all: true\n\
4915 ";
4916 
4918  ConfInit();
4920  ConfYamlLoadString(input, strlen(input));
4921  HTPConfigure();
4922  const char *addr = "4.3.2.1";
4923  memset(&ssn, 0, sizeof(ssn));
4924 
4925  f = UTHBuildFlow(AF_INET, "1.2.3.4", addr, 1024, 80);
4926  FAIL_IF_NULL(f);
4927  f->protoctx = &ssn;
4928  f->proto = IPPROTO_TCP;
4929  f->alproto = ALPROTO_HTTP1;
4930 
4931  StreamTcpInitConfig(true);
4932 
4933  uint32_t u;
4934  for (u = 0; u < httplen1; u++) {
4935  uint8_t flags = 0;
4936 
4937  if (u == 0) flags = STREAM_TOSERVER|STREAM_START;
4938  else if (u == (httplen1 - 1)) flags = STREAM_TOSERVER|STREAM_EOF;
4939  else flags = STREAM_TOSERVER;
4940 
4941  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, flags, &httpbuf1[u], 1);
4942  FAIL_IF(r != 0);
4943  }
4944 
4945  htp_state = f->alstate;
4946  FAIL_IF_NULL(htp_state);
4947 
4948  uint8_t ref1[] = "http://suricata-ids.org/blah/";
4949  size_t reflen = sizeof(ref1) - 1;
4950 
4951  htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4952  FAIL_IF_NULL(tx);
4953  HtpTxUserData *tx_ud = (HtpTxUserData *) htp_tx_get_user_data(tx);
4954  FAIL_IF_NULL(tx_ud);
4956  FAIL_IF(reflen != bstr_len(tx_ud->request_uri_normalized));
4957 
4958  FAIL_IF(memcmp(bstr_ptr(tx_ud->request_uri_normalized), ref1,
4959  bstr_len(tx_ud->request_uri_normalized)) != 0);
4960 
4962  HTPFreeConfig();
4963  ConfDeInit();
4966 
4967  StreamTcpFreeConfig(true);
4968  UTHFreeFlow(f);
4969  PASS;
4970 }
4971 
4972 /** \test BG box crash -- chunks are messed up. Observed for real. */
4973 static int HTPBodyReassemblyTest01(void)
4974 {
4975  HtpTxUserData htud;
4976  memset(&htud, 0x00, sizeof(htud));
4977  HtpState hstate;
4978  memset(&hstate, 0x00, sizeof(hstate));
4979  Flow flow;
4980  memset(&flow, 0x00, sizeof(flow));
4982  htp_tx_t tx;
4983  memset(&tx, 0, sizeof(tx));
4984 
4985  hstate.f = &flow;
4986  flow.alparser = parser;
4987 
4988  uint8_t chunk1[] = "--e5a320f21416a02493a0a6f561b1c494\r\nContent-Disposition: form-data; name=\"uploadfile\"; filename=\"D2GUef.jpg\"\r";
4989  uint8_t chunk2[] = "POST /uri HTTP/1.1\r\nHost: hostname.com\r\nKeep-Alive: 115\r\nAccept-Charset: utf-8\r\nUser-Agent: Mozilla/5.0 (X11; Linux i686; rv:9.0.1) Gecko/20100101 Firefox/9.0.1\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nConnection: keep-alive\r\nContent-length: 68102\r\nReferer: http://otherhost.com\r\nAccept-Encoding: gzip\r\nContent-Type: multipart/form-data; boundary=e5a320f21416a02493a0a6f561b1c494\r\nCookie: blah\r\nAccept-Language: us\r\n\r\n--e5a320f21416a02493a0a6f561b1c494\r\nContent-Disposition: form-data; name=\"uploadfile\"; filename=\"D2GUef.jpg\"\r";
4990 
4991  int r = HtpBodyAppendChunk(&htud.request_body, chunk1, sizeof(chunk1) - 1);
4992  BUG_ON(r != 0);
4993  r = HtpBodyAppendChunk(&htud.request_body, chunk2, sizeof(chunk2) - 1);
4994  BUG_ON(r != 0);
4995 
4996  const uint8_t *chunks_buffer = NULL;
4997  uint32_t chunks_buffer_len = 0;
4998 
4999  HtpRequestBodyReassemble(&htud, &chunks_buffer, &chunks_buffer_len);
5000  FAIL_IF_NULL(chunks_buffer);
5001 #ifdef PRINT
5002  printf("REASSCHUNK START: \n");
5003  PrintRawDataFp(stdout, chunks_buffer, chunks_buffer_len);
5004  printf("REASSCHUNK END: \n");
5005 #endif
5006 
5007  htud.mime_state = SCMimeStateInit((const uint8_t *)"multipart/form-data; boundary=toto",
5008  strlen("multipart/form-data; boundary=toto"));
5009  FAIL_IF_NULL(htud.mime_state);
5010  htud.tsflags |= HTP_BOUNDARY_SET;
5011  HtpRequestBodyHandleMultipart(&hstate, &htud, &tx, chunks_buffer, chunks_buffer_len, false);
5012 
5014 
5016 
5017  PASS;
5018 }
5019 
5020 /** \test BG crash */
5021 static int HTPSegvTest01(void)
5022 {
5023  Flow *f = NULL;
5024  uint8_t httpbuf1[] = "POST /uri HTTP/1.1\r\nHost: hostname.com\r\nKeep-Alive: 115\r\nAccept-Charset: utf-8\r\nUser-Agent: Mozilla/5.0 (X11; Linux i686; rv:9.0.1) Gecko/20100101 Firefox/9.0.1\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nConnection: keep-alive\r\nContent-length: 68102\r\nReferer: http://otherhost.com\r\nAccept-Encoding: gzip\r\nContent-Type: multipart/form-data; boundary=e5a320f21416a02493a0a6f561b1c494\r\nCookie: blah\r\nAccept-Language: us\r\n\r\n--e5a320f21416a02493a0a6f561b1c494\r\nContent-Disposition: form-data; name=\"uploadfile\"; filename=\"D2GUef.jpg\"\r";
5025  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
5026  char input[] = "\
5027 %YAML 1.1\n\
5028 ---\n\
5029 libhtp:\n\
5030 \n\
5031  default-config:\n\
5032  personality: IDS\n\
5033  double-decode-path: no\n\
5034  double-decode-query: no\n\
5035  request-body-limit: 0\n\
5036  response-body-limit: 0\n\
5037 ";
5038 
5040  ConfInit();
5042  ConfYamlLoadString(input, strlen(input));
5043  HTPConfigure();
5044 
5045  TcpSession ssn;
5046  HtpState *http_state = NULL;
5048 
5049  memset(&ssn, 0, sizeof(ssn));
5050 
5051  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
5052  FAIL_IF_NULL(f);
5053  f->protoctx = &ssn;
5054  f->proto = IPPROTO_TCP;
5055  f->alproto = ALPROTO_HTTP1;
5056 
5057  StreamTcpInitConfig(true);
5058 
5059  SCLogDebug("\n>>>> processing chunk 1 <<<<\n");
5060  int r = AppLayerParserParse(
5061  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_START, httpbuf1, httplen1);
5062  FAIL_IF(r != 0);
5063  SCLogDebug("\n>>>> processing chunk 1 again <<<<\n");
5064  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
5065  FAIL_IF(r != 0);
5066 
5067  http_state = f->alstate;
5068  FAIL_IF_NULL(http_state);
5069 
5071  FAIL_IF_NOT_NULL(decoder_events);
5072 
5074  HTPFreeConfig();
5075  ConfDeInit();
5078  StreamTcpFreeConfig(true);
5079  UTHFreeFlow(f);
5080  PASS;
5081 }
5082 
5083 /** \test Test really long request, this should result in HTP_LOG_CODE_REQUEST_FIELD_TOO_LONG */
5084 static int HTPParserTest14(void)
5085 {
5086  size_t len = 18887;
5087  TcpSession ssn;
5088  char input[] = "\
5089 %YAML 1.1\n\
5090 ---\n\
5091 libhtp:\n\
5092 \n\
5093  default-config:\n\
5094  personality: IDS\n\
5095  double-decode-path: no\n\
5096  double-decode-query: no\n\
5097  request-body-limit: 0\n\
5098  response-body-limit: 0\n\
5099 ";
5102 
5103  memset(&ssn, 0, sizeof(ssn));
5104 
5106  ConfInit();
5108  ConfYamlLoadString(input, strlen(input));
5109  HTPConfigure();
5110 
5111  char *httpbuf = SCMalloc(len);
5112  FAIL_IF_NULL(httpbuf);
5113  memset(httpbuf, 0x00, len);
5114 
5115  /* create the request with a longer than 18k cookie */
5116  strlcpy(httpbuf, "GET /blah/ HTTP/1.1\r\n"
5117  "Host: myhost.lan\r\n"
5118  "Connection: keep-alive\r\n"
5119  "Accept: */*\r\n"
5120  "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.76 Safari/537.36\r\n"
5121  "Referer: http://blah.lan/\r\n"
5122  "Accept-Encoding: gzip,deflate,sdch\r\nAccept-Language: en-US,en;q=0.8\r\n"
5123  "Cookie: ", len);
5124  size_t o = strlen(httpbuf);
5125  for ( ; o < len - 4; o++) {
5126  httpbuf[o] = 'A';
5127  }
5128  httpbuf[len - 4] = '\r';
5129  httpbuf[len - 3] = '\n';
5130  httpbuf[len - 2] = '\r';
5131  httpbuf[len - 1] = '\n';
5132 
5133  Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
5134  FAIL_IF_NULL(f);
5135  f->protoctx = &ssn;
5136  f->alproto = ALPROTO_HTTP1;
5137  f->proto = IPPROTO_TCP;
5138 
5139  StreamTcpInitConfig(true);
5140 
5141  uint32_t u;
5142  for (u = 0; u < len; u++) {
5143  uint8_t flags = 0;
5144 
5145  if (u == 0) flags = STREAM_TOSERVER|STREAM_START;
5146  else if (u == (len - 1)) flags = STREAM_TOSERVER|STREAM_EOF;
5147  else flags = STREAM_TOSERVER;
5148 
5149  (void)AppLayerParserParse(
5150  NULL, alp_tctx, f, ALPROTO_HTTP1, flags, (uint8_t *)&httpbuf[u], 1);
5151  }
5152  HtpState *htp_state = f->alstate;
5153  FAIL_IF_NULL(htp_state);
5154 
5155  htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5156  FAIL_IF_NULL(tx);
5159 
5160  void *txtmp = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, f->alstate, 0);
5161  AppLayerDecoderEvents *decoder_events =
5162  AppLayerParserGetEventsByTx(IPPROTO_TCP, ALPROTO_HTTP1, txtmp);
5163  FAIL_IF_NULL(decoder_events);
5164 
5165  FAIL_IF(decoder_events->events[0] != HTP_LOG_CODE_REQUEST_FIELD_TOO_LONG);
5166 
5168  StreamTcpFreeConfig(true);
5169  UTHFreeFlow(f);
5170  SCFree(httpbuf);
5171  HTPFreeConfig();
5172  ConfDeInit();
5175  PASS;
5176 }
5177 
5178 /** \test Test really long request (same as HTPParserTest14), now with config
5179  * update to allow it */
5180 static int HTPParserTest15(void)
5181 {
5182  Flow *f = NULL;
5183  char *httpbuf = NULL;
5184  size_t len = 18887;
5185  TcpSession ssn;
5186  HtpState *htp_state = NULL;
5187  char input[] = "\
5188 %YAML 1.1\n\
5189 ---\n\
5190 libhtp:\n\
5191 \n\
5192  default-config:\n\
5193  personality: IDS\n\
5194  double-decode-path: no\n\
5195  double-decode-query: no\n\
5196  request-body-limit: 0\n\
5197  response-body-limit: 0\n\
5198  meta-field-limit: 20000\n\
5199 ";
5201 
5202  memset(&ssn, 0, sizeof(ssn));
5203 
5205  ConfInit();
5207  ConfYamlLoadString(input, strlen(input));
5208  HTPConfigure();
5209 
5210  httpbuf = SCMalloc(len);
5211  FAIL_IF_NULL(httpbuf);
5212 
5213  memset(httpbuf, 0x00, len);
5214 
5215  /* create the request with a longer than 18k cookie */
5216  strlcpy(httpbuf, "GET /blah/ HTTP/1.1\r\n"
5217  "Host: myhost.lan\r\n"
5218  "Connection: keep-alive\r\n"
5219  "Accept: */*\r\n"
5220  "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.76 Safari/537.36\r\n"
5221  "Referer: http://blah.lan/\r\n"
5222  "Accept-Encoding: gzip,deflate,sdch\r\nAccept-Language: en-US,en;q=0.8\r\n"
5223  "Cookie: ", len);
5224  size_t o = strlen(httpbuf);
5225  for ( ; o < len - 4; o++) {
5226  httpbuf[o] = 'A';
5227  }
5228  httpbuf[len - 4] = '\r';
5229  httpbuf[len - 3] = '\n';
5230  httpbuf[len - 2] = '\r';
5231  httpbuf[len - 1] = '\n';
5232 
5233  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
5234  FAIL_IF_NULL(f);
5235  f->protoctx = &ssn;
5236  f->proto = IPPROTO_TCP;
5237  f->alproto = ALPROTO_HTTP1;
5238 
5239  StreamTcpInitConfig(true);
5240 
5241  uint32_t u;
5242  for (u = 0; u < len; u++) {
5243  uint8_t flags = 0;
5244 
5245  if (u == 0) flags = STREAM_TOSERVER|STREAM_START;
5246  else if (u == (len - 1)) flags = STREAM_TOSERVER|STREAM_EOF;
5247  else flags = STREAM_TOSERVER;
5248 
5249  int r = AppLayerParserParse(
5250  NULL, alp_tctx, f, ALPROTO_HTTP1, flags, (uint8_t *)&httpbuf[u], 1);
5251  FAIL_IF(r != 0);
5252  }
5253  htp_state = f->alstate;
5254  FAIL_IF_NULL(htp_state);
5255 
5256  htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5257  FAIL_IF_NULL(tx);
5260 
5261  void *txtmp = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, f->alstate, 0);
5262  AppLayerDecoderEvents *decoder_events =
5263  AppLayerParserGetEventsByTx(IPPROTO_TCP, ALPROTO_HTTP1, txtmp);
5264  FAIL_IF_NOT_NULL(decoder_events);
5265 
5267  StreamTcpFreeConfig(true);
5268  UTHFreeFlow(f);
5269  SCFree(httpbuf);
5270  HTPFreeConfig();
5271  ConfDeInit();
5274  PASS;
5275 }
5276 
5277 /** \test Test unusual delims in request line HTP_LOG_CODE_REQUEST_FIELD_TOO_LONG */
5278 static int HTPParserTest16(void)
5279 {
5280  Flow *f = NULL;
5281  TcpSession ssn;
5282  HtpState *htp_state = NULL;
5284 
5285  memset(&ssn, 0, sizeof(ssn));
5286 
5287  uint8_t httpbuf[] = "GET\f/blah/\fHTTP/1.1\r\n"
5288  "Host: myhost.lan\r\n"
5289  "Connection: keep-alive\r\n"
5290  "Accept: */*\r\n"
5291  "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.76 Safari/537.36\r\n"
5292  "Referer: http://blah.lan/\r\n"
5293  "Accept-Encoding: gzip,deflate,sdch\r\nAccept-Language: en-US,en;q=0.8\r\n"
5294  "Cookie: blah\r\n\r\n";
5295  size_t len = sizeof(httpbuf) - 1;
5296 
5297  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
5298  FAIL_IF_NULL(f);
5299  f->protoctx = &ssn;
5300  f->proto = IPPROTO_TCP;
5301  f->alproto = ALPROTO_HTTP1;
5302 
5303  StreamTcpInitConfig(true);
5304 
5305  uint8_t flags = STREAM_TOSERVER|STREAM_START|STREAM_EOF;
5306 
5307  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, flags, (uint8_t *)httpbuf, len);
5308  FAIL_IF(r != 0);
5309 
5310  htp_state = f->alstate;
5311  FAIL_IF_NULL(htp_state);
5312 
5313  htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5314  FAIL_IF_NULL(tx);
5317 
5318 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
5319 //these events are disabled during fuzzing as they are too noisy and consume much resource
5320  void *txtmp = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, f->alstate, 0);
5321  AppLayerDecoderEvents *decoder_events =
5322  AppLayerParserGetEventsByTx(IPPROTO_TCP, ALPROTO_HTTP1, txtmp);
5323 
5324  FAIL_IF_NULL(decoder_events);
5326  FAIL_IF(decoder_events->events[1] != HTP_LOG_CODE_URI_DELIM_NON_COMPLIANT);
5327 
5328 #endif
5329 
5331  StreamTcpFreeConfig(true);
5332  UTHFreeFlow(f);
5333  PASS;
5334 }
5335 
5336 /** \test Test response not HTTP
5337  */
5338 static int HTPParserTest20(void)
5339 {
5340  Flow *f = NULL;
5341  uint8_t httpbuf1[] = "GET /ld/index.php?id=412784631&cid=0064&version=4&"
5342  "name=try HTTP/1.1\r\nAccept: */*\r\nUser-Agent: "
5343  "LD-agent\r\nHost: 209.205.196.16\r\n\r\n";
5344  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
5345  uint8_t httpbuf2[] = "NOTHTTP\r\nSOMEOTHERDATA";
5346  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
5347  uint8_t httpbuf3[] = "STILLNOTHTTP\r\nSOMEMOREOTHERDATA";
5348  uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
5349  TcpSession ssn;
5350  HtpState *http_state = NULL;
5353 
5354  memset(&ssn, 0, sizeof(ssn));
5355 
5356  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
5357  FAIL_IF_NULL(f);
5358  f->protoctx = &ssn;
5359  f->proto = IPPROTO_TCP;
5360  f->alproto = ALPROTO_HTTP1;
5361 
5362  StreamTcpInitConfig(true);
5363 
5364  int r = AppLayerParserParse(
5365  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_START, httpbuf1, httplen1);
5366  FAIL_IF(r != 0);
5367 
5368  r = AppLayerParserParse(
5369  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_START, httpbuf2, httplen2);
5370  FAIL_IF(r != 0);
5371 
5372  r = AppLayerParserParse(
5373  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_START, httpbuf3, httplen3);
5374  FAIL_IF(r != 0);
5375 
5376  http_state = f->alstate;
5377  FAIL_IF_NULL(http_state);
5378  htp_tx_t *tx = HTPStateGetTx(http_state, 0);
5379  FAIL_IF_NULL(tx);
5380  const htp_header_t *h = htp_tx_request_header_index(tx, 0);
5381  FAIL_IF_NULL(h);
5382 
5385 
5388 
5390  StreamTcpFreeConfig(true);
5391  UTHFreeFlow(f);
5392  PASS;
5393 }
5394 
5395 /** \test Test response not HTTP
5396  */
5397 static int HTPParserTest21(void)
5398 {
5399  Flow *f = NULL;
5400  uint8_t httpbuf1[] = "GET /ld/index.php?id=412784631&cid=0064&version=4&"
5401  "name=try HTTP/1.1\r\nAccept: */*\r\nUser-Agent: "
5402  "LD-agent\r\nHost: 209.205.196.16\r\n\r\n";
5403  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
5404  uint8_t httpbuf2[] = "999 NOTHTTP REALLY\r\nSOMEOTHERDATA\r\n";
5405  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
5406  uint8_t httpbuf3[] = "STILLNOTHTTP\r\nSOMEMOREOTHERDATA";
5407  uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
5408  TcpSession ssn;
5409  HtpState *http_state = NULL;
5412 
5413  memset(&ssn, 0, sizeof(ssn));
5414 
5415  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
5416  FAIL_IF_NULL(f);
5417  f->protoctx = &ssn;
5418  f->proto = IPPROTO_TCP;
5419  f->alproto = ALPROTO_HTTP1;
5420 
5421  StreamTcpInitConfig(true);
5422 
5423  int r = AppLayerParserParse(
5424  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_START, httpbuf1, httplen1);
5425  FAIL_IF(r != 0);
5426 
5427  r = AppLayerParserParse(
5428  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_START, httpbuf2, httplen2);
5429  FAIL_IF(r != 0);
5430 
5431  r = AppLayerParserParse(
5432  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_START, httpbuf3, httplen3);
5433  FAIL_IF(r != 0);
5434 
5435  http_state = f->alstate;
5436  FAIL_IF_NULL(http_state);
5437  htp_tx_t *tx = HTPStateGetTx(http_state, 0);
5438  FAIL_IF_NULL(tx);
5439  const htp_header_t *h = htp_tx_request_header_index(tx, 0);
5440  FAIL_IF_NULL(h);
5441 
5444 
5447 
5449  StreamTcpFreeConfig(true);
5450  UTHFreeFlow(f);
5451  PASS;
5452 }
5453 
5454 /** \test Test response not HTTP
5455  */
5456 static int HTPParserTest22(void)
5457 {
5458  Flow *f = NULL;
5459  uint8_t httpbuf1[] = "GET /ld/index.php?id=412784631&cid=0064&version=4&"
5460  "name=try HTTP/1.1\r\nAccept: */*\r\nUser-Agent: "
5461  "LD-agent\r\nHost: 209.205.196.16\r\n\r\n";
5462  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
5463  uint8_t httpbuf2[] = "\r\n0000=0000000/ASDF3_31.zip, 456723\r\n"
5464  "AAAAAA_0000=0000000/AAAAAAAA.zip,46725\r\n";
5465  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
5466  TcpSession ssn;
5467  HtpState *http_state = NULL;
5470 
5471  memset(&ssn, 0, sizeof(ssn));
5472 
5473  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
5474  FAIL_IF_NULL(f);
5475  f->protoctx = &ssn;
5476  f->proto = IPPROTO_TCP;
5477  f->alproto = ALPROTO_HTTP1;
5478 
5479  StreamTcpInitConfig(true);
5480 
5481  int r = AppLayerParserParse(
5482  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_START, httpbuf1, httplen1);
5483  FAIL_IF(r != 0);
5484 
5485  r = AppLayerParserParse(
5486  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_START, httpbuf2, httplen2);
5487  FAIL_IF(r != 0);
5488 
5489  http_state = f->alstate;
5490  FAIL_IF_NULL(http_state);
5491  htp_tx_t *tx = HTPStateGetTx(http_state, 0);
5492  FAIL_IF_NULL(tx);
5493  const htp_header_t *h = htp_tx_request_header_index(tx, 0);
5494  FAIL_IF_NULL(h);
5495 
5498 
5501 
5503  StreamTcpFreeConfig(true);
5504  UTHFreeFlow(f);
5505  PASS;
5506 }
5507 
5508 /** \test Test response not HTTP
5509  */
5510 static int HTPParserTest23(void)
5511 {
5512  Flow *f = NULL;
5513  uint8_t httpbuf1[] = "GET /ld/index.php?id=412784631&cid=0064&version=4&"
5514  "name=try HTTP/1.1\r\nAccept: */*\r\nUser-Agent: "
5515  "LD-agent\r\nHost: 209.205.196.16\r\n\r\n";
5516  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
5517  uint8_t httpbuf2[] = "HTTP0000=0000000/ASDF3_31.zip, 456723\r\n"
5518  "AAAAAA_0000=0000000/AAAAAAAA.zip,46725\r\n";
5519  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
5520  TcpSession ssn;
5521  HtpState *http_state = NULL;
5524 
5525  memset(&ssn, 0, sizeof(ssn));
5526 
5527  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
5528  FAIL_IF_NULL(f);
5529  f->protoctx = &ssn;
5530  f->proto = IPPROTO_TCP;
5531  f->alproto = ALPROTO_HTTP1;
5532 
5533  StreamTcpInitConfig(true);
5534 
5535  int r = AppLayerParserParse(
5536  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_START, httpbuf1, httplen1);
5537  FAIL_IF(r != 0);
5538 
5539  r = AppLayerParserParse(
5540  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_START, httpbuf2, httplen2);
5541  FAIL_IF(r != 0);
5542 
5543  http_state = f->alstate;
5544  FAIL_IF_NULL(http_state);
5545  htp_tx_t *tx = HTPStateGetTx(http_state, 0);
5546  FAIL_IF_NULL(tx);
5547  const htp_header_t *h = htp_tx_request_header_index(tx, 0);
5548  FAIL_IF_NULL(h);
5549 
5552 
5555 
5557  StreamTcpFreeConfig(true);
5558  UTHFreeFlow(f);
5559  PASS;
5560 }
5561 
5562 /** \test Test response not HTTP
5563  */
5564 static int HTPParserTest24(void)
5565 {
5566  Flow *f = NULL;
5567  uint8_t httpbuf1[] = "GET /ld/index.php?id=412784631&cid=0064&version=4&"
5568  "name=try HTTP/1.1\r\nAccept: */*\r\nUser-Agent: "
5569  "LD-agent\r\nHost: 209.205.196.16\r\n\r\n";
5570  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
5571  uint8_t httpbuf2[] = "HTTP/1.0 0000=0000000/ASDF3_31.zip, 456723\r\n"
5572  "AAAAAA_0000=0000000/AAAAAAAA.zip,46725\r\n";
5573  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
5574  TcpSession ssn;
5575  HtpState *http_state = NULL;
5578 
5579  memset(&ssn, 0, sizeof(ssn));
5580 
5581  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
5582  FAIL_IF_NULL(f);
5583  f->protoctx = &ssn;
5584  f->proto = IPPROTO_TCP;
5585  f->alproto = ALPROTO_HTTP1;
5586 
5587  StreamTcpInitConfig(true);
5588 
5589  int r = AppLayerParserParse(
5590  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_START, httpbuf1, httplen1);
5591  FAIL_IF(r != 0);
5592 
5593  r = AppLayerParserParse(
5594  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_START, httpbuf2, httplen2);
5595  FAIL_IF(r != 0);
5596 
5597  http_state = f->alstate;
5598  FAIL_IF_NULL(http_state);
5599  htp_tx_t *tx = HTPStateGetTx(http_state, 0);
5600  FAIL_IF_NULL(tx);
5601  const htp_header_t *h = htp_tx_request_header_index(tx, 0);
5602  FAIL_IF_NULL(h);
5603 
5606 
5609 
5611  StreamTcpFreeConfig(true);
5612  UTHFreeFlow(f);
5613  PASS;
5614 }
5615 
5616 /** \test multi transactions and cleanup */
5617 static int HTPParserTest25(void)
5618 {
5621 
5622  StreamTcpInitConfig(true);
5623  TcpSession ssn;
5624  memset(&ssn, 0, sizeof(ssn));
5625 
5626  Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
5627  FAIL_IF_NULL(f);
5628  f->protoctx = &ssn;
5629  f->proto = IPPROTO_TCP;
5630  f->alproto = ALPROTO_HTTP1;
5631 
5632  const char *str = "GET / HTTP/1.1\r\nHost: www.google.com\r\nUser-Agent: Suricata/1.0\r\n\r\n";
5633  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_START,
5634  (uint8_t *)str, strlen(str));
5635  FAIL_IF_NOT(r == 0);
5636  r = AppLayerParserParse(
5637  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, (uint8_t *)str, strlen(str));
5638  FAIL_IF_NOT(r == 0);
5639  r = AppLayerParserParse(
5640  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, (uint8_t *)str, strlen(str));
5641  FAIL_IF_NOT(r == 0);
5642  r = AppLayerParserParse(
5643  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, (uint8_t *)str, strlen(str));
5644  FAIL_IF_NOT(r == 0);
5645  r = AppLayerParserParse(
5646  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, (uint8_t *)str, strlen(str));
5647  FAIL_IF_NOT(r == 0);
5648  r = AppLayerParserParse(
5649  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, (uint8_t *)str, strlen(str));
5650  FAIL_IF_NOT(r == 0);
5651  r = AppLayerParserParse(
5652  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, (uint8_t *)str, strlen(str));
5653  FAIL_IF_NOT(r == 0);
5654  r = AppLayerParserParse(
5655  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, (uint8_t *)str, strlen(str));
5656  FAIL_IF_NOT(r == 0);
5657 
5658  str = "HTTP 1.1 200 OK\r\nServer: Suricata/1.0\r\nContent-Length: 8\r\n\r\nSuricata";
5659  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_START,
5660  (uint8_t *)str, strlen(str));
5661  FAIL_IF_NOT(r == 0);
5662  r = AppLayerParserParse(
5663  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOCLIENT, (uint8_t *)str, strlen(str));
5664  FAIL_IF_NOT(r == 0);
5665  r = AppLayerParserParse(
5666  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOCLIENT, (uint8_t *)str, strlen(str));
5667  FAIL_IF_NOT(r == 0);
5668  r = AppLayerParserParse(
5669  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOCLIENT, (uint8_t *)str, strlen(str));
5670  FAIL_IF_NOT(r == 0);
5671  r = AppLayerParserParse(
5672  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOCLIENT, (uint8_t *)str, strlen(str));
5673  FAIL_IF_NOT(r == 0);
5674  r = AppLayerParserParse(
5675  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOCLIENT, (uint8_t *)str, strlen(str));
5676  FAIL_IF_NOT(r == 0);
5677  r = AppLayerParserParse(
5678  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOCLIENT, (uint8_t *)str, strlen(str));
5679  FAIL_IF_NOT(r == 0);
5680  r = AppLayerParserParse(
5681  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOCLIENT, (uint8_t *)str, strlen(str));
5682  FAIL_IF_NOT(r == 0);
5683 
5684  AppLayerParserTransactionsCleanup(f, STREAM_TOCLIENT);
5685 
5686  uint64_t ret[4];
5687  UTHAppLayerParserStateGetIds(f->alparser, &ret[0], &ret[1], &ret[2], &ret[3]);
5688  FAIL_IF_NOT(ret[0] == 8); // inspect_id[0]
5689  FAIL_IF_NOT(ret[1] == 8); // inspect_id[1]
5690  FAIL_IF_NOT(ret[2] == 8); // log_id
5691  FAIL_IF_NOT(ret[3] == 8); // min_id
5692 
5693  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_EOF,
5694  (uint8_t *)str, strlen(str));
5695  FAIL_IF_NOT(r == 0);
5696  AppLayerParserTransactionsCleanup(f, STREAM_TOCLIENT);
5697 
5698  UTHAppLayerParserStateGetIds(f->alparser, &ret[0], &ret[1], &ret[2], &ret[3]);
5699  FAIL_IF_NOT(ret[0] == 8); // inspect_id[0] not updated by ..Cleanup() until full tx is done
5700  FAIL_IF_NOT(ret[1] == 8); // inspect_id[1]
5701  FAIL_IF_NOT(ret[2] == 8); // log_id
5702  FAIL_IF_NOT(ret[3] == 8); // min_id
5703 
5704  r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOCLIENT | STREAM_EOF,
5705  (uint8_t *)str, strlen(str));
5706  FAIL_IF_NOT(r == 0);
5707  AppLayerParserTransactionsCleanup(f, STREAM_TOCLIENT);
5708 
5709  UTHAppLayerParserStateGetIds(f->alparser, &ret[0], &ret[1], &ret[2], &ret[3]);
5710  FAIL_IF_NOT(ret[0] == 9); // inspect_id[0]
5711  FAIL_IF_NOT(ret[1] == 9); // inspect_id[1]
5712  FAIL_IF_NOT(ret[2] == 9); // log_id
5713  FAIL_IF_NOT(ret[3] == 9); // min_id
5714 
5715  HtpState *http_state = f->alstate;
5716  FAIL_IF_NULL(http_state);
5717 
5719  StreamTcpFreeConfig(true);
5720  UTHFreeFlow(f);
5721 
5722  PASS;
5723 }
5724 
5725 static int HTPParserTest26(void)
5726 {
5727  char input[] = "\
5728 %YAML 1.1\n\
5729 ---\n\
5730 libhtp:\n\
5731 \n\
5732  default-config:\n\
5733  personality: IDS\n\
5734  request-body-limit: 1\n\
5735  response-body-limit: 1\n\
5736 ";
5738  ConfInit();
5740  ConfYamlLoadString(input, strlen(input));
5741  HTPConfigure();
5742 
5743  Packet *p1 = NULL;
5744  Packet *p2 = NULL;
5745  ThreadVars th_v;
5746  DetectEngineCtx *de_ctx = NULL;
5747  DetectEngineThreadCtx *det_ctx = NULL;
5748  Flow f;
5749  uint8_t httpbuf1[] = "GET /alice.txt HTTP/1.1\r\n\r\n";
5750  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
5751  uint8_t httpbuf2[] = "HTTP/1.1 200 OK\r\n"
5752  "Content-Type: text/plain\r\n"
5753  "Content-Length: 228\r\n\r\n"
5754  "Alice was beginning to get very tired of sitting by her sister on the bank."
5755  "Alice was beginning to get very tired of sitting by her sister on the bank.";
5756  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
5757  uint8_t httpbuf3[] = "Alice was beginning to get very tired of sitting by her sister on the bank.\r\n\r\n";
5758  uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
5759  TcpSession ssn;
5760  HtpState *http_state = NULL;
5763 
5764  memset(&th_v, 0, sizeof(th_v));
5765  memset(&f, 0, sizeof(f));
5766  memset(&ssn, 0, sizeof(ssn));
5767 
5768  p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
5769  p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
5770 
5771  FLOW_INITIALIZE(&f);
5772  f.protoctx = (void *)&ssn;
5773  f.proto = IPPROTO_TCP;
5774  f.flags |= FLOW_IPV4;
5775 
5776  p1->flow = &f;
5780  p2->flow = &f;
5784  f.alproto = ALPROTO_HTTP1;
5785 
5786  StreamTcpInitConfig(true);
5787 
5790 
5791  de_ctx->flags |= DE_QUIET;
5792 
5793  de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
5794  "(filestore; sid:1; rev:1;)");
5796 
5798  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
5799 
5800  int r = AppLayerParserParse(
5801  &th_v, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
5802  FAIL_IF(r != 0);
5803 
5804  http_state = f.alstate;
5805  FAIL_IF_NULL(http_state);
5806 
5807  /* do detect */
5808  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
5809 
5810  FAIL_IF((PacketAlertCheck(p1, 1)));
5811 
5812  /* do detect */
5813  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
5814 
5815  FAIL_IF((PacketAlertCheck(p1, 1)));
5816 
5817  r = AppLayerParserParse(
5818  &th_v, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, httpbuf2, httplen2);
5819  FAIL_IF(r != 0);
5820 
5821  http_state = f.alstate;
5822  FAIL_IF_NULL(http_state);
5823 
5824  /* do detect */
5825  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
5826 
5827  FAIL_IF(!(PacketAlertCheck(p2, 1)));
5828 
5829  r = AppLayerParserParse(
5830  &th_v, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOCLIENT, httpbuf3, httplen3);
5831  FAIL_IF(r != 0);
5832 
5833  http_state = f.alstate;
5834  FAIL_IF_NULL(http_state);
5835 
5836  void *tx_ptr = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, http_state, 0);
5837  FAIL_IF_NULL(tx_ptr);
5838 
5839  AppLayerGetFileState files = HTPGetTxFiles(tx_ptr, STREAM_TOCLIENT);
5840  FileContainer *ffc = files.fc;
5841  FAIL_IF_NULL(ffc);
5842 
5843  File *ptr = ffc->head;
5844  FAIL_IF(ptr->state != FILE_STATE_CLOSED);
5845 
5847  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
5849  StreamTcpFreeConfig(true);
5850 
5851  HTPFreeConfig();
5852  FLOW_DESTROY(&f);
5853  UTHFreePackets(&p1, 1);
5854  UTHFreePackets(&p2, 1);
5855  ConfDeInit();
5858  PASS;
5859 }
5860 
5861 static int HTPParserTest27(void)
5862 {
5863  HTPCfgDir cfg;
5864  memset(&cfg, 0, sizeof(cfg));
5865  cfg.body_limit = 1500;
5867 
5868  uint32_t len = 1000;
5869 
5870  HtpTxUserData *tx_ud = SCMalloc(sizeof(HtpTxUserData));
5871  FAIL_IF_NULL(tx_ud);
5872 
5873  tx_ud->tsflags |= HTP_STREAM_DEPTH_SET;
5874  tx_ud->request_body.content_len_so_far = 2500;
5875 
5876  FAIL_IF(AppLayerHtpCheckDepth(&cfg, &tx_ud->request_body, tx_ud->tsflags));
5877 
5878  len = AppLayerHtpComputeChunkLength(tx_ud->request_body.content_len_so_far,
5879  0,
5881  tx_ud->tsflags,
5882  len);
5883  FAIL_IF(len != 1000);
5884 
5885  SCFree(tx_ud);
5886 
5887  PASS;
5888 }
5889 
5890 /**
5891  * \brief Register the Unit tests for the HTTP protocol
5892  */
5893 static void HTPParserRegisterTests(void)
5894 {
5895  UtRegisterTest("HTPParserTest01", HTPParserTest01);
5896  UtRegisterTest("HTPParserTest01a", HTPParserTest01a);
5897  UtRegisterTest("HTPParserTest01b", HTPParserTest01b);
5898  UtRegisterTest("HTPParserTest01c", HTPParserTest01c);
5899  UtRegisterTest("HTPParserTest02", HTPParserTest02);
5900  UtRegisterTest("HTPParserTest03", HTPParserTest03);
5901  UtRegisterTest("HTPParserTest04", HTPParserTest04);
5902  UtRegisterTest("HTPParserTest05", HTPParserTest05);
5903  UtRegisterTest("HTPParserTest06", HTPParserTest06);
5904  UtRegisterTest("HTPParserTest07", HTPParserTest07);
5905  UtRegisterTest("HTPParserTest08", HTPParserTest08);
5906  UtRegisterTest("HTPParserTest09", HTPParserTest09);
5907  UtRegisterTest("HTPParserTest10", HTPParserTest10);
5908  UtRegisterTest("HTPParserTest11", HTPParserTest11);
5909  UtRegisterTest("HTPParserTest12", HTPParserTest12);
5910  UtRegisterTest("HTPParserTest13", HTPParserTest13);
5911  UtRegisterTest("HTPParserConfigTest01", HTPParserConfigTest01);
5912  UtRegisterTest("HTPParserConfigTest02", HTPParserConfigTest02);
5913  UtRegisterTest("HTPParserConfigTest03", HTPParserConfigTest03);
5914 
5915  UtRegisterTest("HTPParserDecodingTest01", HTPParserDecodingTest01);
5916  UtRegisterTest("HTPParserDecodingTest01a", HTPParserDecodingTest01a);
5917  UtRegisterTest("HTPParserDecodingTest02", HTPParserDecodingTest02);
5918  UtRegisterTest("HTPParserDecodingTest03", HTPParserDecodingTest03);
5919  UtRegisterTest("HTPParserDecodingTest04", HTPParserDecodingTest04);
5920  UtRegisterTest("HTPParserDecodingTest05", HTPParserDecodingTest05);
5921  UtRegisterTest("HTPParserDecodingTest06", HTPParserDecodingTest06);
5922  UtRegisterTest("HTPParserDecodingTest07", HTPParserDecodingTest07);
5923  UtRegisterTest("HTPParserDecodingTest08", HTPParserDecodingTest08);
5924  UtRegisterTest("HTPParserDecodingTest09", HTPParserDecodingTest09);
5925 
5926  UtRegisterTest("HTPBodyReassemblyTest01", HTPBodyReassemblyTest01);
5927 
5928  UtRegisterTest("HTPSegvTest01", HTPSegvTest01);
5929 
5930  UtRegisterTest("HTPParserTest14", HTPParserTest14);
5931  UtRegisterTest("HTPParserTest15", HTPParserTest15);
5932  UtRegisterTest("HTPParserTest16", HTPParserTest16);
5933  UtRegisterTest("HTPParserTest20", HTPParserTest20);
5934  UtRegisterTest("HTPParserTest21", HTPParserTest21);
5935  UtRegisterTest("HTPParserTest22", HTPParserTest22);
5936  UtRegisterTest("HTPParserTest23", HTPParserTest23);
5937  UtRegisterTest("HTPParserTest24", HTPParserTest24);
5938  UtRegisterTest("HTPParserTest25", HTPParserTest25);
5939  UtRegisterTest("HTPParserTest26", HTPParserTest26);
5940  UtRegisterTest("HTPParserTest27", HTPParserTest27);
5941 
5944 }
5945 #endif /* UNITTESTS */
5946 
5947 /**
5948  * @}
5949  */
HtpState
struct HtpState_ HtpState
HtpState_::cfg
const struct HTPCfgRec_ * cfg
Definition: app-layer-htp.h:258
HtpState_::tx_freed
uint64_t tx_freed
Definition: app-layer-htp.h:257
htp_header_value_len
#define htp_header_value_len(h)
Definition: app-layer-htp-libhtp.h:191
HTP_CONFIG_DEFAULT_RESPONSE_BODY_LIMIT
#define HTP_CONFIG_DEFAULT_RESPONSE_BODY_LIMIT
Definition: app-layer-htp.h:115
util-byte.h
FILE_TRUNCATED
#define FILE_TRUNCATED
Definition: util-file.h:45
AppLayerParserRegisterGetStateProgressFunc
void AppLayerParserRegisterGetStateProgressFunc(uint8_t ipproto, AppProto alproto, int(*StateGetProgress)(void *alstate, uint8_t direction))
Definition: app-layer-parser.c:475
FileContainer_
Definition: util-file.h:113
len
uint8_t len
Definition: app-layer-dnp3.h:2
ts
uint64_t ts
Definition: source-erf-file.c:55
HTP_METHOD_UNKNOWN
#define HTP_METHOD_UNKNOWN
Definition: app-layer-htp-libhtp.h:75
app-layer-htp-range.h
AppLayerHtpNeedFileInspection
void AppLayerHtpNeedFileInspection(void)
Sets a flag that informs the HTP app layer that some module in the engine needs the http request file...
Definition: app-layer-htp.c:496
detect-engine.h
HTPFileCloseHandleRange
bool HTPFileCloseHandleRange(const StreamingBufferConfig *sbcfg, FileContainer *files, const uint16_t flags, HttpRangeContainerBlock *c, const uint8_t *data, uint32_t data_len)
close range, add reassembled file if possible
Definition: app-layer-htp-file.c:267
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
HTP_MAX_MESSAGES
#define HTP_MAX_MESSAGES
Definition: app-layer-htp.c:95
htp_tx_data_data
#define htp_tx_data_data(d)
Definition: app-layer-htp-libhtp.h:204
HtpState_::slice
StreamSlice * slice
Definition: app-layer-htp.h:265
AppLayerProtoDetectPMRegisterPatternCI
int AppLayerProtoDetectPMRegisterPatternCI(uint8_t ipproto, AppProto alproto, const char *pattern, uint16_t depth, uint16_t offset, uint8_t direction)
Registers a case-insensitive pattern for protocol detection.
Definition: app-layer-detect-proto.c:1676
FLOW_IS_IPV6
#define FLOW_IS_IPV6(f)
Definition: flow.h:170
PKT_HAS_FLOW
#define PKT_HAS_FLOW
Definition: decode.h:1266
offset
uint64_t offset
Definition: util-streaming-buffer.h:0
AppLayerParserRegisterOptionFlags
void AppLayerParserRegisterOptionFlags(uint8_t ipproto, AppProto alproto, uint32_t flags)
Definition: app-layer-parser.c:414
flow-util.h
htp_tx_request_progress
#define htp_tx_request_progress(tx)
Definition: app-layer-htp-libhtp.h:169
SC_ATOMIC_INIT
#define SC_ATOMIC_INIT(name)
wrapper for initializing an atomic variable.
Definition: util-atomic.h:314
HTP_LOG_CODE_RESPONSE_FIELD_MISSING_COLON
#define HTP_LOG_CODE_RESPONSE_FIELD_MISSING_COLON
Definition: app-layer-htp-libhtp.h:102
htp_radix4_cfg
SCRadix4Config htp_radix4_cfg
Definition: app-layer-htp.c:86
Flow_::startts
SCTime_t startts
Definition: flow.h:488
HtpTxUserData_::request_headers_raw_len
uint32_t request_headers_raw_len
Definition: app-layer-htp.h:232
StreamingBufferConfig_::Calloc
void *(* Calloc)(size_t n, size_t size)
Definition: util-streaming-buffer.h:69
FileReassemblyDepthEnable
void FileReassemblyDepthEnable(uint32_t size)
Definition: util-file.c:127
ConfNode_::val
char * val
Definition: conf.h:34
stream-tcp.h
HTPCfgDir_
Definition: app-layer-htp.h:155
SCRadix6TreeFindBestMatch
SCRadix6Node * SCRadix6TreeFindBestMatch(const SCRadix6Tree *tree, const uint8_t *key, void **user_data)
Definition: util-radix6-tree.c:173
HtpBody_::sb
StreamingBuffer * sb
Definition: app-layer-htp.h:195
HTP_FLAGS_HOST_AMBIGUOUS
#define HTP_FLAGS_HOST_AMBIGUOUS
Definition: app-layer-htp-libhtp.h:69
HtpTxUserData_::files_tc
FileContainer files_tc
Definition: app-layer-htp.h:241
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
HTPFileStoreChunk
int HTPFileStoreChunk(HtpTxUserData *tx, const uint8_t *data, uint32_t data_len, uint8_t direction)
Store a chunk of data in the flow.
Definition: app-layer-htp-file.c:223
AppLayerParserTransactionsCleanup
void AppLayerParserTransactionsCleanup(Flow *f, const uint8_t pkt_dir)
remove obsolete (inspected and logged) transactions
Definition: app-layer-parser.c:882
HTP_METHOD_GET
#define HTP_METHOD_GET
Definition: app-layer-htp-libhtp.h:76
HTPCfgRec_::response
HTPCfgDir response
Definition: app-layer-htp.h:177
SCRadix4AddKeyIPV4String
bool SCRadix4AddKeyIPV4String(SCRadix4Tree *tree, const SCRadix4Config *config, const char *str, void *user)
Adds a new IPV4/netblock to the Radix4 tree from a string.
Definition: util-radix4-tree.c:227
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
HTP_LOG_CODE_UNKNOWN
#define HTP_LOG_CODE_UNKNOWN
Definition: app-layer-htp-libhtp.h:99
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
AppLayerHtpPrintStats
void AppLayerHtpPrintStats(void)
Definition: app-layer-htp.c:2641
AppLayerParserGetEventsByTx
AppLayerDecoderEvents * AppLayerParserGetEventsByTx(uint8_t ipproto, AppProto alproto, void *tx)
Definition: app-layer-parser.c:836
HTPCfgDir_::body_limit
uint32_t body_limit
Definition: app-layer-htp.h:156
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
HTP_AUTH_TYPE_UNRECOGNIZED
#define HTP_AUTH_TYPE_UNRECOGNIZED
Definition: app-layer-htp-libhtp.h:73
Flow_::proto
uint8_t proto
Definition: flow.h:376
AppProto
uint16_t AppProto
Definition: app-layer-protos.h:85
HTP_LOG_CODE_HOST_HEADER_AMBIGUOUS
#define HTP_LOG_CODE_HOST_HEADER_AMBIGUOUS
Definition: app-layer-htp-libhtp.h:126
AppLayerParserConfParserEnabled
int AppLayerParserConfParserEnabled(const char *ipproto, const char *alproto_name)
check if a parser is enabled in the config Returns enabled always if: were running unittests
Definition: app-layer-parser.c:333
PacketAlertCheck
int PacketAlertCheck(Packet *p, uint32_t sid)
Check if a certain sid alerted, this is used in the test functions.
Definition: detect-engine-alert.c:141
AppLayerParserGetStateProgress
int AppLayerParserGetStateProgress(uint8_t ipproto, AppProto alproto, void *alstate, uint8_t flags)
get the progress value for a tx/protocol
Definition: app-layer-parser.c:1070
AppLayerParserTriggerRawStreamReassembly
void AppLayerParserTriggerRawStreamReassembly(Flow *f, int direction)
Definition: app-layer-parser.c:1540
StreamTcpReassemblySetMinInspectDepth
void StreamTcpReassemblySetMinInspectDepth(TcpSession *ssn, int direction, uint32_t depth)
Definition: stream-tcp-reassemble.c:2173
STREAMING_BUFFER_CONFIG_INITIALIZER
#define STREAMING_BUFFER_CONFIG_INITIALIZER
Definition: util-streaming-buffer.h:74
HtpTxUserData_::mime_state
MimeStateHTTP * mime_state
Definition: app-layer-htp.h:235
HTP_LOG_CODE_REQUEST_LINE_INVALID
#define HTP_LOG_CODE_REQUEST_LINE_INVALID
Definition: app-layer-htp-libhtp.h:133
Packet_::flags
uint32_t flags
Definition: decode.h:513
ConfGetNode
ConfNode * ConfGetNode(const char *name)
Get a ConfNode by name.
Definition: conf.c:181
Frame
Definition: app-layer-frames.h:43
Flow_
Flow data structure.
Definition: flow.h:354
File_::state
FileState state
Definition: util-file.h:82
HtpGetTxForH2
void * HtpGetTxForH2(void *alstate)
Definition: app-layer-htp.c:2704
HtpState_::flags
uint16_t flags
Definition: app-layer-htp.h:259
HtpState_::f
Flow * f
Definition: app-layer-htp.h:249
HTP_LOG_CODE_CONTINUE_ALREADY_SEEN
#define HTP_LOG_CODE_CONTINUE_ALREADY_SEEN
Definition: app-layer-htp-libhtp.h:117
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:854
AppLayerParserRegisterStateProgressCompletionStatus
void AppLayerParserRegisterStateProgressCompletionStatus(AppProto alproto, const int ts, const int tc)
Definition: app-layer-parser.c:523
AppLayerParserRegisterParserAcceptableDataDirection
void AppLayerParserRegisterParserAcceptableDataDirection(uint8_t ipproto, AppProto alproto, uint8_t direction)
Definition: app-layer-parser.c:403
htp_tx_request_header_index
#define htp_tx_request_header_index(tx, i)
Definition: app-layer-htp-libhtp.h:199
HTP_LOG_CODE_REQUEST_BODY_UNEXPECTED
#define HTP_LOG_CODE_REQUEST_BODY_UNEXPECTED
Definition: app-layer-htp-libhtp.h:134
AppLayerParserRegisterTxFreeFunc
void AppLayerParserRegisterTxFreeFunc(uint8_t ipproto, AppProto alproto, void(*StateTransactionFree)(void *, uint64_t))
Definition: app-layer-parser.c:485
AppLayerFrameSetTxId
void AppLayerFrameSetTxId(Frame *r, uint64_t tx_id)
Definition: app-layer-frames.c:679
Frame::id
int64_t id
Definition: app-layer-frames.h:51
TAILQ_FOREACH
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:252
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2648
htp_tx_response_header
#define htp_tx_response_header(tx, header)
Definition: app-layer-htp-libhtp.h:185
HTP_CONFIG_DEFAULT_REQUEST_INSPECT_WINDOW
#define HTP_CONFIG_DEFAULT_REQUEST_INSPECT_WINDOW
Definition: app-layer-htp.h:117
HtpTxUserData_::request_body
HtpBody request_body
Definition: app-layer-htp.h:225
htp_tx_request_method_number
#define htp_tx_request_method_number(tx)
Definition: app-layer-htp-libhtp.h:167
AppLayerRequestProtocolChange
bool AppLayerRequestProtocolChange(Flow *f, uint16_t dp, AppProto expect_proto)
request applayer to wrap up this protocol and rerun protocol detection.
Definition: app-layer-detect-proto.c:1818
HTP_FLAGS_HOSTH_INVALID
#define HTP_FLAGS_HOSTH_INVALID
Definition: app-layer-htp-libhtp.h:71
AppLayerParserThreadCtxFree
void AppLayerParserThreadCtxFree(AppLayerParserThreadCtx *tctx)
Destroys the app layer parser thread context obtained using AppLayerParserThreadCtxAlloc().
Definition: app-layer-parser.c:312
SCMutexLock
#define SCMutexLock(mut)
Definition: threads-debug.h:117
HTP_LOG_CODE_INVALID_SERVER_PORT_IN_REQUEST
#define HTP_LOG_CODE_INVALID_SERVER_PORT_IN_REQUEST
Definition: app-layer-htp-libhtp.h:120
FLOW_PKT_TOSERVER
#define FLOW_PKT_TOSERVER
Definition: flow.h:231
HTP_STATUS_OK
#define HTP_STATUS_OK
Definition: app-layer-htp-libhtp.h:52
HTP_LOG_CODE_INVALID_RESPONSE_FIELD_FOLDING
#define HTP_LOG_CODE_INVALID_RESPONSE_FIELD_FOLDING
Definition: app-layer-htp-libhtp.h:128
MIN
#define MIN(x, y)
Definition: suricata-common.h:400
AppLayerDecoderEventsFreeEvents
void AppLayerDecoderEventsFreeEvents(AppLayerDecoderEvents **events)
Definition: app-layer-events.c:136
HTTP_SWF_COMPRESSION_ZLIB
@ HTTP_SWF_COMPRESSION_ZLIB
Definition: app-layer-htp.h:150
DE_QUIET
#define DE_QUIET
Definition: detect.h:325
HtpTxUserData_::request_uri_normalized
bstr * request_uri_normalized
Definition: app-layer-htp.h:228
HTP_LOG_CODE_REQUEST_FIELD_TOO_LONG
#define HTP_LOG_CODE_REQUEST_FIELD_TOO_LONG
Definition: app-layer-htp-libhtp.h:130
UTHBuildPacket
Packet * UTHBuildPacket(uint8_t *payload, uint16_t payload_len, uint8_t ipproto)
UTHBuildPacket is a wrapper that build packets with default ip and port fields.
Definition: util-unittest-helper.c:359
HTPRealloc
void * HTPRealloc(void *ptr, size_t orig_size, size_t size)
Definition: app-layer-htp-mem.c:175
SigMatchSignatures
void SigMatchSignatures(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:1969
SCMUTEX_INITIALIZER
#define SCMUTEX_INITIALIZER
Definition: threads-debug.h:121
RandomGet
long int RandomGet(void)
Definition: util-random.c:130
Flow_::dp
Port dp
Definition: flow.h:370
HtpState_::transaction_cnt
uint64_t transaction_cnt
Definition: app-layer-htp.h:250
HTP_LOG_CODE_REQUEST_LINE_LEADING_WHITESPACE
#define HTP_LOG_CODE_REQUEST_LINE_LEADING_WHITESPACE
Definition: app-layer-htp-libhtp.h:145
HTP_CONFIG_DEFAULT_REQUEST_INSPECT_MIN_SIZE
#define HTP_CONFIG_DEFAULT_REQUEST_INSPECT_MIN_SIZE
Definition: app-layer-htp.h:116
HTPCfgRec_::swf_compress_depth
uint32_t swf_compress_depth
Definition: app-layer-htp.h:174
StreamingBufferGetDataAtOffset
int StreamingBufferGetDataAtOffset(const StreamingBuffer *sb, const uint8_t **data, uint32_t *data_len, uint64_t offset)
Definition: util-streaming-buffer.c:1833
htp_tx_request_method
#define htp_tx_request_method(tx)
Definition: app-layer-htp-libhtp.h:166
AppLayerFrameNewByAbsoluteOffset
Frame * AppLayerFrameNewByAbsoluteOffset(Flow *f, const StreamSlice *stream_slice, const uint64_t frame_start, const int64_t len, int dir, uint8_t frame_type)
create new frame using the absolute offset from the start of the stream
Definition: app-layer-frames.c:598
Packet_::flowflags
uint8_t flowflags
Definition: decode.h:507
HTPStateFree
void HTPStateFree(void *state)
Function to frees the HTTP state memory and also frees the HTTP connection parser memory which was us...
Definition: app-layer-htp.c:386
HTP_LOG_CODE_REQUEST_FIELD_MISSING_COLON
#define HTP_LOG_CODE_REQUEST_FIELD_MISSING_COLON
Definition: app-layer-htp-libhtp.h:101
APP_LAYER_PARSER_EOF_TS
#define APP_LAYER_PARSER_EOF_TS
Definition: app-layer-parser.h:39
Flow_::protoctx
void * protoctx
Definition: flow.h:439
FLOW_IPV4
#define FLOW_IPV4
Definition: flow.h:98
htp_tx_is_protocol_0_9
#define htp_tx_is_protocol_0_9(tx)
Definition: app-layer-htp-libhtp.h:161
GET_IPV6_DST_ADDR
#define GET_IPV6_DST_ADDR(p)
Definition: decode.h:200
AppLayerDecoderEvents_
Data structure to store app layer decoder events.
Definition: app-layer-events.h:36
HTTP_DECODER_EVENT_TOO_MANY_WARNINGS
@ HTTP_DECODER_EVENT_TOO_MANY_WARNINGS
Definition: app-layer-htp.h:103
HTPCfgDir_::inspect_window
uint32_t inspect_window
Definition: app-layer-htp.h:158
util-unittest.h
HTPConfigure
void HTPConfigure(void)
Definition: app-layer-htp.c:2570
HtpState_
Definition: app-layer-htp.h:244
HTPParseMemcap
void HTPParseMemcap(void)
Definition: app-layer-htp-mem.c:43
StringParseU32RangeCheck
int StringParseU32RangeCheck(uint32_t *res, int base, size_t len, const char *str, uint32_t min, uint32_t max)
Definition: util-byte.c:404
ConfValIsTrue
int ConfValIsTrue(const char *val)
Check if a value is true.
Definition: conf.c:536
util-unittest-helper.h
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:82
HTP_LOG_CODE_INVALID_CONTENT_LENGTH_FIELD_IN_RESPONSE
#define HTP_LOG_CODE_INVALID_CONTENT_LENGTH_FIELD_IN_RESPONSE
Definition: app-layer-htp-libhtp.h:111
htp_header_value
#define htp_header_value(h)
Definition: app-layer-htp-libhtp.h:193
SCRadix4TreeRelease
void SCRadix4TreeRelease(SCRadix4Tree *tree, const SCRadix4Config *config)
Definition: util-radix4-tree.c:172
HTPFileOpen
int HTPFileOpen(HtpState *s, HtpTxUserData *tx, const uint8_t *filename, uint16_t filename_len, const uint8_t *data, uint32_t data_len, uint8_t direction)
Open the file with "filename" and pass the first chunk of data if any.
Definition: app-layer-htp-file.c:50
HTP_LOG_CODE_AUTH_UNRECOGNIZED
#define HTP_LOG_CODE_AUTH_UNRECOGNIZED
Definition: app-layer-htp-libhtp.h:139
app-layer-htp-xff.h
HTP_LOG_CODE_REQUEST_HEADER_REPETITION
#define HTP_LOG_CODE_REQUEST_HEADER_REPETITION
Definition: app-layer-htp-libhtp.h:140
strlcpy
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
app-layer-htp-file.h
HTP_LOG_CODE_RESPONSE_INVALID_PROTOCOL
#define HTP_LOG_CODE_RESPONSE_INVALID_PROTOCOL
Definition: app-layer-htp-libhtp.h:153
util-memcmp.h
HtpBody_::content_len_so_far
uint64_t content_len_so_far
Definition: app-layer-htp.h:198
HtpState_::response_frame_id
FrameId response_frame_id
Definition: app-layer-htp.h:267
SCRadix4Tree_
Structure for the radix tree.
Definition: util-radix4-tree.h:66
Flow_::alparser
AppLayerParserState * alparser
Definition: flow.h:473
Flow_::dst
FlowAddress dst
Definition: flow.h:357
HtpTxUserData_::file_range
HttpRangeContainerBlock * file_range
Definition: app-layer-htp.h:237
app-layer-detect-proto.h
StreamTcpInitConfig
void StreamTcpInitConfig(bool)
To initialize the stream global configuration data.
Definition: stream-tcp.c:488
UTHBuildFlow
Flow * UTHBuildFlow(int family, const char *src, const char *dst, Port sp, Port dp)
Definition: util-unittest-helper.c:482
FLOW_INITIALIZE
#define FLOW_INITIALIZE(f)
Definition: flow-util.h:38
app-layer-htp.h
htp_tx_data_tx
#define htp_tx_data_tx(d)
Definition: app-layer-htp-libhtp.h:205
HTP_FILENAME_SET
#define HTP_FILENAME_SET
Definition: app-layer-htp.h:206
APP_LAYER_INCOMPLETE
#define APP_LAYER_INCOMPLETE(c, n)
Definition: app-layer-parser.h:99
HTP_CONFIG_DEFAULT_LZMA_MEMLIMIT
#define HTP_CONFIG_DEFAULT_LZMA_MEMLIMIT
Definition: app-layer-htp.h:125
decode.h
FAIL_IF_NOT_NULL
#define FAIL_IF_NOT_NULL(expr)
Fail a test if expression evaluates to non-NULL.
Definition: util-unittest.h:96
HTP_LOG_CODE_METHOD_DELIM_NON_COMPLIANT
#define HTP_LOG_CODE_METHOD_DELIM_NON_COMPLIANT
Definition: app-layer-htp-libhtp.h:144
HTTP_DECODER_EVENT_REQUEST_TOO_MANY_HEADERS
@ HTTP_DECODER_EVENT_REQUEST_TOO_MANY_HEADERS
Definition: app-layer-htp.h:95
util-debug.h
HtpState_::last_request_data_stamp
uint64_t last_request_data_stamp
Definition: app-layer-htp.h:263
TAILQ_FIRST
#define TAILQ_FIRST(head)
Definition: queue.h:250
htp_warnings
struct @7 htp_warnings[]
HtpBody_::body_parsed
uint64_t body_parsed
Definition: app-layer-htp.h:200
HTP_LOG_CODE_FILE_NAME_TOO_LONG
#define HTP_LOG_CODE_FILE_NAME_TOO_LONG
Definition: app-layer-htp-libhtp.h:132
HTP_RESPONSE_PROGRESS_COMPLETE
#define HTP_RESPONSE_PROGRESS_COMPLETE
Definition: app-layer-htp-libhtp.h:97
HTPCfgRec_::http_body_inline
int http_body_inline
Definition: app-layer-htp.h:169
AppLayerParserState_
Definition: app-layer-parser.c:129
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
HTPCfgRec_::randomize_range
int randomize_range
Definition: app-layer-htp.h:168
GET_IPV4_DST_ADDR_PTR
#define GET_IPV4_DST_ADDR_PTR(p)
Definition: decode.h:195
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:18
HTP_FLAG_STATE_CLOSED_TC
#define HTP_FLAG_STATE_CLOSED_TC
Definition: app-layer-htp.h:137
HTTP_SWF_COMPRESSION_NONE
@ HTTP_SWF_COMPRESSION_NONE
Definition: app-layer-htp.h:149
HtpConfigCreateBackup
void HtpConfigCreateBackup(void)
Definition: app-layer-htp.c:2880
DetectEngineThreadCtx_
Definition: detect.h:1109
SC_FILENAME_MAX
#define SC_FILENAME_MAX
Definition: util-file.h:62
HTP_CONFIG_DEFAULT_COMPRESSION_TIME_LIMIT
#define HTP_CONFIG_DEFAULT_COMPRESSION_TIME_LIMIT
Definition: app-layer-htp.h:128
HTP_ERROR_MAX
#define HTP_ERROR_MAX
Definition: app-layer-htp.c:635
HTPCfgRec_::randomize
int randomize
Definition: app-layer-htp.h:167
HTPCfgDir_::inspect_min_size
uint32_t inspect_min_size
Definition: app-layer-htp.h:157
HTTP_DECODER_EVENT_FAILED_PROTOCOL_CHANGE
@ HTTP_DECODER_EVENT_FAILED_PROTOCOL_CHANGE
Definition: app-layer-htp.h:105
de
uint8_t de
Definition: app-layer-htp.c:560
SCMutexUnlock
#define SCMutexUnlock(mut)
Definition: threads-debug.h:119
HTP_LOG_CODE_RESPONSE_CHUNKED_OLD_PROTO
#define HTP_LOG_CODE_RESPONSE_CHUNKED_OLD_PROTO
Definition: app-layer-htp-libhtp.h:152
HTP_LOG_CODE_URI_DELIM_NON_COMPLIANT
#define HTP_LOG_CODE_URI_DELIM_NON_COMPLIANT
Definition: app-layer-htp-libhtp.h:143
AppLayerHtpEnableRequestBodyCallback
void AppLayerHtpEnableRequestBodyCallback(void)
Sets a flag that informs the HTP app layer that some module in the engine needs the http request body...
Definition: app-layer-htp.c:469
alp_tctx
AppLayerParserThreadCtx * alp_tctx
Definition: fuzz_applayerparserparse.c:22
htp_header_name
#define htp_header_name(h)
Definition: app-layer-htp-libhtp.h:190
util-print.h
AppLayerParserRegisterGetFrameFuncs
void AppLayerParserRegisterGetFrameFuncs(uint8_t ipproto, AppProto alproto, AppLayerParserGetFrameIdByNameFn GetIdByNameFunc, AppLayerParserGetFrameNameByIdFn GetNameByIdFunc)
Definition: app-layer-parser.c:550
SCEnter
#define SCEnter(...)
Definition: util-debug.h:271
FileContainer_::head
File * head
Definition: util-file.h:114
http_decoder_event_table
SCEnumCharMap http_decoder_event_table[]
Definition: app-layer-htp.c:105
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
HtpTxUserData_::response_has_trailers
uint8_t response_has_trailers
Definition: app-layer-htp.h:218
HtpTxUserData_::request_headers_raw
uint8_t * request_headers_raw
Definition: app-layer-htp.h:230
HtpState_::conn
htp_conn_t * conn
Definition: app-layer-htp.h:248
DetectEngineThreadCtxInit
TmEcode DetectEngineThreadCtxInit(ThreadVars *tv, void *initdata, void **data)
initialize thread specific detection engine context
Definition: detect-engine.c:3389
HTPCfgRec_::swf_decompress_depth
uint32_t swf_decompress_depth
Definition: app-layer-htp.h:173
AppLayerParserRegisterStateFuncs
void AppLayerParserRegisterStateFuncs(uint8_t ipproto, AppProto alproto, void *(*StateAlloc)(void *, AppProto), void(*StateFree)(void *))
Definition: app-layer-parser.c:424
HTP_LOG_CODE_MISSING_HOST_HEADER
#define HTP_LOG_CODE_MISSING_HOST_HEADER
Definition: app-layer-htp-libhtp.h:125
HTPCfgRec_::swf_decompression_enabled
int swf_decompression_enabled
Definition: app-layer-htp.h:171
HtpTxUserData_::tx_data
AppLayerTxData tx_data
Definition: app-layer-htp.h:239
HtpState_::state_data
AppLayerStateData state_data
Definition: app-layer-htp.h:268
HTPCalloc
void * HTPCalloc(size_t n, size_t size)
Definition: app-layer-htp-mem.c:154
HTTP_DECODER_EVENT_MULTIPART_INVALID_HEADER
@ HTTP_DECODER_EVENT_MULTIPART_INVALID_HEADER
Definition: app-layer-htp.h:101
HTPAtExitPrintStats
void HTPAtExitPrintStats(void)
Print the stats of the HTTP requests.
Definition: app-layer-htp.c:1651
HTP_LOG_CODE_INVALID_REQUEST_FIELD_FOLDING
#define HTP_LOG_CODE_INVALID_REQUEST_FIELD_FOLDING
Definition: app-layer-htp-libhtp.h:127
HTP_WARNING_MAX
#define HTP_WARNING_MAX
Definition: app-layer-htp.c:636
ConfYamlLoadString
int ConfYamlLoadString(const char *string, size_t len)
Load configuration from a YAML string.
Definition: conf-yaml-loader.c:523
SCLogWarning
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition: util-debug.h:249
SigInit
Signature * SigInit(DetectEngineCtx *de_ctx, const char *sigstr)
Parses a signature and adds it to the Detection Engine Context.
Definition: detect-parse.c:2392
HTP_LOG_CODE_DUPLICATE_CONTENT_LENGTH_FIELD_IN_RESPONSE
#define HTP_LOG_CODE_DUPLICATE_CONTENT_LENGTH_FIELD_IN_RESPONSE
Definition: app-layer-htp-libhtp.h:115
HTP_CONFIG_DEFAULT_FIELD_LIMIT_SOFT
#define HTP_CONFIG_DEFAULT_FIELD_LIMIT_SOFT
Definition: app-layer-htp.h:120
PrintRawDataFp
void PrintRawDataFp(FILE *fp, const uint8_t *buf, uint32_t buflen)
Definition: util-print.c:112
HTP_CONFIG_DEFAULT_LZMA_LAYERS
#define HTP_CONFIG_DEFAULT_LZMA_LAYERS
Definition: app-layer-htp.h:123
app-layer-parser.h
HTPFileParserRegisterTests
void HTPFileParserRegisterTests(void)
Definition: app-layer-htp-file.c:1218
htp_conn_request_data_counter
#define htp_conn_request_data_counter(c)
Definition: app-layer-htp-libhtp.h:208
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:309
HtpTxUserData_::request_has_trailers
uint8_t request_has_trailers
Definition: app-layer-htp.h:217
FLOW_IS_IPV4
#define FLOW_IS_IPV4(f)
Definition: flow.h:168
HTP_FLAG_STATE_CLOSED_TS
#define HTP_FLAG_STATE_CLOSED_TS
Definition: app-layer-htp.h:134
HTTP_DECODER_EVENT_RANGE_INVALID
@ HTTP_DECODER_EVENT_RANGE_INVALID
Definition: app-layer-htp.h:92
AppLayerParserRegisterGetEventInfo
void AppLayerParserRegisterGetEventInfo(uint8_t ipproto, AppProto alproto, int(*StateGetEventInfo)(const char *event_name, uint8_t *event_id, AppLayerEventType *event_type))
Definition: app-layer-parser.c:560
HTP_LOG_CODE_RESPONSE_INVALID_STATUS
#define HTP_LOG_CODE_RESPONSE_INVALID_STATUS
Definition: app-layer-htp-libhtp.h:154
HTTP_DECODER_EVENT_MULTIPART_NO_FILEDATA
@ HTTP_DECODER_EVENT_MULTIPART_NO_FILEDATA
Definition: app-layer-htp.h:100
HTP_CONFIG_DEFAULT_RESPONSE_INSPECT_MIN_SIZE
#define HTP_CONFIG_DEFAULT_RESPONSE_INSPECT_MIN_SIZE
Definition: app-layer-htp.h:118
FileReassemblyDepth
uint32_t FileReassemblyDepth(void)
Definition: util-file.c:133
HTPCfgRec_::uri_include_all
bool uri_include_all
Definition: app-layer-htp.h:179
SCReturn
#define SCReturn
Definition: util-debug.h:273
SC_ATOMIC_DECLARE
SC_ATOMIC_DECLARE(uint32_t, htp_config_flags)
AppLayerParserRegisterProtocolUnittests
void AppLayerParserRegisterProtocolUnittests(uint8_t ipproto, AppProto alproto, void(*RegisterUnittests)(void))
Definition: app-layer-parser.c:1804
HTP_LOG_CODE_RESPONSE_HEADER_REPETITION
#define HTP_LOG_CODE_RESPONSE_HEADER_REPETITION
Definition: app-layer-htp-libhtp.h:141
HTP_CONFIG_DEFAULT_REQUEST_BODY_LIMIT
#define HTP_CONFIG_DEFAULT_REQUEST_BODY_LIMIT
Definition: app-layer-htp.h:114
HTP_LOG_CODE_DOUBLE_ENCODED_URI
#define HTP_LOG_CODE_DOUBLE_ENCODED_URI
Definition: app-layer-htp-libhtp.h:142
app-layer-htp-body.h
Packet_
Definition: decode.h:476
detect-engine-build.h
conf-yaml-loader.h
APP_LAYER_PARSER_EOF_TC
#define APP_LAYER_PARSER_EOF_TC
Definition: app-layer-parser.h:40
htp_tx_flags
#define htp_tx_flags(tx)
Definition: app-layer-htp-libhtp.h:160
htp_tx_request_protocol_number
#define htp_tx_request_protocol_number(tx)
Definition: app-layer-htp-libhtp.h:171
detect-engine-alert.h
conf.h
htp_header_value_ptr
#define htp_header_value_ptr(h)
Definition: app-layer-htp-libhtp.h:192
HTP_STATUS_ERROR
#define HTP_STATUS_ERROR
Definition: app-layer-htp-libhtp.h:53
Frame::len
int64_t len
Definition: app-layer-frames.h:50
SC_RADIX4_TREE_INITIALIZER
#define SC_RADIX4_TREE_INITIALIZER
Definition: util-radix4-tree.h:78
name
const char * name
Definition: tm-threads.c:2081
SCReturnPtr
#define SCReturnPtr(x, type)
Definition: util-debug.h:287
HtpBodyPrune
void HtpBodyPrune(HtpState *state, HtpBody *body, int direction)
Free request body chunks that are already fully parsed.
Definition: app-layer-htp-body.c:128
AppLayerParserRegisterGetTxFilesFunc
void AppLayerParserRegisterGetTxFilesFunc(uint8_t ipproto, AppProto alproto, AppLayerGetFileState(*GetTxFiles)(void *, uint8_t))
Definition: app-layer-parser.c:447
detect-engine-state.h
Data structures and function prototypes for keeping state for the detection engine.
AppLayerProtoDetectRegisterProtocol
void AppLayerProtoDetectRegisterProtocol(AppProto alproto, const char *alproto_name)
Registers a protocol for protocol detection phase.
Definition: app-layer-detect-proto.c:1767
HTP_STREAM_DEPTH_SET
#define HTP_STREAM_DEPTH_SET
Definition: app-layer-htp.h:208
AppLayerHtpEnableResponseBodyCallback
void AppLayerHtpEnableResponseBodyCallback(void)
Sets a flag that informs the HTP app layer that some module in the engine needs the http request body...
Definition: app-layer-htp.c:482
AppLayerParserRegisterSetStreamDepthFlag
void AppLayerParserRegisterSetStreamDepthFlag(uint8_t ipproto, AppProto alproto, void(*SetStreamDepthFlag)(void *tx, uint8_t flags))
Definition: app-layer-parser.c:601
ConfCreateContextBackup
void ConfCreateContextBackup(void)
Creates a backup of the conf_hash hash_table used by the conf API.
Definition: conf.c:669
HTP_LOG_CODE_RESPONSE_ABNORMAL_TRANSFER_ENCODING
#define HTP_LOG_CODE_RESPONSE_ABNORMAL_TRANSFER_ENCODING
Definition: app-layer-htp-libhtp.h:150
IF_HTP_PERSONALITY_NUM
#define IF_HTP_PERSONALITY_NUM(p)
HTPCfgRec_::swf_compression_type
HtpSwfCompressType swf_compression_type
Definition: app-layer-htp.h:172
HTP_LOG_CODE_RESPONSE_HEADER_INVALID
#define HTP_LOG_CODE_RESPONSE_HEADER_INVALID
Definition: app-layer-htp-libhtp.h:124
ALPROTO_HTTP2
@ ALPROTO_HTTP2
Definition: app-layer-protos.h:70
HTP_REQUIRE_RESPONSE_BODY
#define HTP_REQUIRE_RESPONSE_BODY
Definition: app-layer-htp.h:276
HTP_LOG_CODE_GZIP_DECOMPRESSION_FAILED
#define HTP_LOG_CODE_GZIP_DECOMPRESSION_FAILED
Definition: app-layer-htp-libhtp.h:100
FLOW_PKT_TOCLIENT
#define FLOW_PKT_TOCLIENT
Definition: flow.h:232
HTP_LOG_CODE_INVALID_TRANSFER_ENCODING_VALUE_IN_REQUEST
#define HTP_LOG_CODE_INVALID_TRANSFER_ENCODING_VALUE_IN_REQUEST
Definition: app-layer-htp-libhtp.h:105
HTP_LOG_CODE_RESPONSE_FIELD_TOO_LONG
#define HTP_LOG_CODE_RESPONSE_FIELD_TOO_LONG
Definition: app-layer-htp-libhtp.h:131
HtpBodyFree
void HtpBodyFree(HtpBody *body)
Print the information and chunks of a Body.
Definition: app-layer-htp-body.c:99
HtpTxUserData_::response_body
HtpBody response_body
Definition: app-layer-htp.h:226
SCLogInfo
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:224
HTP_LOG_CODE_INVALID_REQUEST_CHUNK_LEN
#define HTP_LOG_CODE_INVALID_REQUEST_CHUNK_LEN
Definition: app-layer-htp-libhtp.h:103
AppLayerParserGetTx
void * AppLayerParserGetTx(uint8_t ipproto, AppProto alproto, void *alstate, uint64_t tx_id)
Definition: app-layer-parser.c:1092
AppLayerParserRegisterParser
int AppLayerParserRegisterParser(uint8_t ipproto, AppProto alproto, uint8_t direction, AppLayerParserFPtr Parser)
Register app layer parser for the protocol.
Definition: app-layer-parser.c:391
WarnInvalidConfEntry
#define WarnInvalidConfEntry(param_name, format, value)
Generic API that can be used by all to log an invalid conf entry.
Definition: util-misc.h:35
DetectEngineStateFree
void DetectEngineStateFree(DetectEngineState *state)
Frees a DetectEngineState object.
Definition: detect-engine-state.c:169
HTP_BODY_REQUEST_PUT
@ HTP_BODY_REQUEST_PUT
Definition: app-layer-htp.h:145
DETECT_ENGINE_STATE_FLAG_FILE_NEW
#define DETECT_ENGINE_STATE_FLAG_FILE_NEW
Definition: detect-engine-state.h:70
SigGroupBuild
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
Definition: detect-engine-build.c:2113
HTPCfgRec_::next
struct HTPCfgRec_ * next
Definition: app-layer-htp.h:164
UTHFreeFlow
void UTHFreeFlow(Flow *flow)
Definition: util-unittest-helper.c:487
htp_tx_response_protocol_number
#define htp_tx_response_protocol_number(tx)
Definition: app-layer-htp-libhtp.h:182
AppLayerParserThreadCtxAlloc
AppLayerParserThreadCtx * AppLayerParserThreadCtxAlloc(void)
Gets a new app layer protocol's parser thread context.
Definition: app-layer-parser.c:285
AppLayerParserRegisterGetTx
void AppLayerParserRegisterGetTx(uint8_t ipproto, AppProto alproto, void *(StateGetTx)(void *alstate, uint64_t tx_id))
Definition: app-layer-parser.c:505
ConfNodeLookupChild
ConfNode * ConfNodeLookupChild(const ConfNode *node, const char *name)
Lookup a child configuration node by name.
Definition: conf.c:781
htp_sbcfg
StreamingBufferConfig htp_sbcfg
Definition: app-layer-htp.c:92
HTP_LOG_CODE_INVALID_AUTHORITY_PORT
#define HTP_LOG_CODE_INVALID_AUTHORITY_PORT
Definition: app-layer-htp-libhtp.h:122
HttpFrameTypes
HttpFrameTypes
Definition: app-layer-htp.c:180
FILE_STATE_CLOSED
@ FILE_STATE_CLOSED
Definition: util-file.h:71
File_
Definition: util-file.h:79
APP_LAYER_OK
#define APP_LAYER_OK
Definition: app-layer-parser.h:87
AppLayerTxData
struct AppLayerTxData AppLayerTxData
Definition: detect.h:1382
HtpTxUserData_::request_body_type
uint8_t request_body_type
Definition: app-layer-htp.h:223
HTPCfgRec_::cfg
htp_cfg_t * cfg
Definition: app-layer-htp.h:163
app-layer-frames.h
SCMapEnumValueToName
const char * SCMapEnumValueToName(int enum_value, SCEnumCharMap *table)
Maps an enum value to a string name, from the supplied table.
Definition: util-enum.c:68
Packet_::flow
struct Flow_ * flow
Definition: decode.h:515
SCReturnStruct
#define SCReturnStruct(x)
Definition: util-debug.h:291
HTP_BODY_REQUEST_POST
@ HTP_BODY_REQUEST_POST
Definition: app-layer-htp.h:144
HTP_LOG_CODE_URI_HOST_INVALID
#define HTP_LOG_CODE_URI_HOST_INVALID
Definition: app-layer-htp-libhtp.h:137
SCRadix6Config_
Definition: util-radix6-tree.h:69
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
Definition: util-unittest.h:71
HtpBody_
Definition: app-layer-htp.h:191
StreamTcpFreeConfig
void StreamTcpFreeConfig(bool quiet)
Definition: stream-tcp.c:859
SCMapEnumNameToValue
int SCMapEnumNameToValue(const char *enum_name, SCEnumCharMap *table)
Maps a string name to an enum value from the supplied table. Please specify the last element of any m...
Definition: util-enum.c:40
HTPXFFParserRegisterTests
void HTPXFFParserRegisterTests(void)
Definition: app-layer-htp-xff.c:333
flags
uint8_t flags
Definition: decode-gre.h:0
SCRadix4Config_
Definition: util-radix4-tree.h:71
AppLayerParserParse
int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto, uint8_t flags, const uint8_t *input, uint32_t input_len)
Definition: app-layer-parser.c:1274
HTP_FLAGS_REQUEST_INVALID_T_E
#define HTP_FLAGS_REQUEST_INVALID_T_E
Definition: app-layer-htp-libhtp.h:66
suricata-common.h
HTPCfgRec_::request
HTPCfgDir request
Definition: app-layer-htp.h:176
HTP_REQUIRE_REQUEST_BODY
#define HTP_REQUIRE_REQUEST_BODY
Definition: app-layer-htp.h:272
HTP_LOG_CODE_INVALID_CONTENT_LENGTH_FIELD_IN_REQUEST
#define HTP_LOG_CODE_INVALID_CONTENT_LENGTH_FIELD_IN_REQUEST
Definition: app-layer-htp-libhtp.h:109
HtpTxUserData_::response_headers_raw
uint8_t * response_headers_raw
Definition: app-layer-htp.h:231
SCEnumCharMap_
Definition: util-enum.h:27
ALPROTO_HTTP1
@ ALPROTO_HTTP1
Definition: app-layer-protos.h:36
AppLayerDecoderEventsSetEventRaw
void AppLayerDecoderEventsSetEventRaw(AppLayerDecoderEvents **sevents, uint8_t event)
Set an app layer decoder event.
Definition: app-layer-events.c:94
ConfNode_::name
char * name
Definition: conf.h:33
HtpState_::connp
htp_connp_t * connp
Definition: app-layer-htp.h:246
TAILQ_NEXT
#define TAILQ_NEXT(elm, field)
Definition: queue.h:307
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *tv, void *data)
Definition: detect-engine.c:3616
HTP_BOUNDARY_SET
#define HTP_BOUNDARY_SET
Definition: app-layer-htp.h:205
SCLogPerf
#define SCLogPerf(...)
Definition: util-debug.h:230
HtpTxUserData_::tcflags
uint8_t tcflags
Definition: app-layer-htp.h:221
SCTIME_SECS
#define SCTIME_SECS(t)
Definition: util-time.h:57
htp_tx_response_progress
#define htp_tx_response_progress(tx)
Definition: app-layer-htp-libhtp.h:181
HTP_METHOD_POST
#define HTP_METHOD_POST
Definition: app-layer-htp-libhtp.h:77
AppLayerParserRegisterStateDataFunc
void AppLayerParserRegisterStateDataFunc(uint8_t ipproto, AppProto alproto, AppLayerStateData *(*GetStateData)(void *state))
Definition: app-layer-parser.c:581
ConfRestoreContextBackup
void ConfRestoreContextBackup(void)
Restores the backup of the hash_table present in backup_conf_hash back to conf_hash.
Definition: conf.c:679
htp_radix6_cfg
SCRadix6Config htp_radix6_cfg
Definition: app-layer-htp.c:87
HTP_LOG_CODE_UNABLE_TO_MATCH_RESPONSE_TO_REQUEST
#define HTP_LOG_CODE_UNABLE_TO_MATCH_RESPONSE_TO_REQUEST
Definition: app-layer-htp-libhtp.h:118
FatalError
#define FatalError(...)
Definition: util-debug.h:502
DetectEngineCtx_::sig_list
Signature * sig_list
Definition: detect.h:862
AppLayerParserRegisterTxDataFunc
void AppLayerParserRegisterTxDataFunc(uint8_t ipproto, AppProto alproto, AppLayerTxData *(*GetTxData)(void *tx))
Definition: app-layer-parser.c:571
htp_tx_request_port_number
#define htp_tx_request_port_number(tx)
Definition: app-layer-htp-libhtp.h:168
ALPROTO_WEBSOCKET
@ ALPROTO_WEBSOCKET
Definition: app-layer-protos.h:65
HTP_DONTSTORE
#define HTP_DONTSTORE
Definition: app-layer-htp.h:207
HTP_CONFIG_DEFAULT_RANDOMIZE
#define HTP_CONFIG_DEFAULT_RANDOMIZE
Definition: app-layer-htp.h:130
HTP_LOG_CODE_INVALID_RESPONSE_CHUNK_LEN
#define HTP_LOG_CODE_INVALID_RESPONSE_CHUNK_LEN
Definition: app-layer-htp-libhtp.h:104
HtpTxUserData_
Definition: app-layer-htp.h:212
HtpState_::last_response_data_stamp
uint64_t last_response_data_stamp
Definition: app-layer-htp.h:264
AppLayerFrameGetById
Frame * AppLayerFrameGetById(Flow *f, const int dir, const FrameId frame_id)
Definition: app-layer-frames.c:694
HTP_LOG_CODE_INVALID_TRANSFER_ENCODING_VALUE_IN_RESPONSE
#define HTP_LOG_CODE_INVALID_TRANSFER_ENCODING_VALUE_IN_RESPONSE
Definition: app-layer-htp-libhtp.h:107
HTP_LOG_CODE_TOO_MANY_ENCODING_LAYERS
#define HTP_LOG_CODE_TOO_MANY_ENCODING_LAYERS
Definition: app-layer-htp-libhtp.h:147
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:32
SCRadix4TreeFindBestMatch
SCRadix4Node * SCRadix4TreeFindBestMatch(const SCRadix4Tree *tree, const uint8_t *key, void **user_data)
Definition: util-radix4-tree.c:154
ParseSizeStringU32
int ParseSizeStringU32(const char *size, uint32_t *res)
Definition: util-misc.c:173
HTP_BODY_REQUEST_MULTIPART
@ HTP_BODY_REQUEST_MULTIPART
Definition: app-layer-htp.h:143
util-validate.h
HtpConfigRestoreBackup
void HtpConfigRestoreBackup(void)
Definition: app-layer-htp.c:2885
StreamingBufferConfig_
Definition: util-streaming-buffer.h:65
FileContainerRecycle
void FileContainerRecycle(FileContainer *ffc, const StreamingBufferConfig *cfg)
Recycle a FileContainer.
Definition: util-file.c:513
HTTP_DECODER_EVENT_REQUEST_CHUNK_EXTENSION
@ HTTP_DECODER_EVENT_REQUEST_CHUNK_EXTENSION
Definition: app-layer-htp.h:93
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
SCLogConfig
struct SCLogConfig_ SCLogConfig
Holds the config state used by the logging api.
HtpState_::events
uint16_t events
Definition: app-layer-htp.h:260
ConfInit
void ConfInit(void)
Initialize the configuration system.
Definition: conf.c:120
APP_LAYER_PARSER_OPT_ACCEPT_GAPS
#define APP_LAYER_PARSER_OPT_ACCEPT_GAPS
Definition: app-layer-parser.h:46
HTP_LOG_CODE_DUPLICATE_CONTENT_LENGTH_FIELD_IN_REQUEST
#define HTP_LOG_CODE_DUPLICATE_CONTENT_LENGTH_FIELD_IN_REQUEST
Definition: app-layer-htp-libhtp.h:113
HTP_PROTOCOL_V1_1
#define HTP_PROTOCOL_V1_1
Definition: app-layer-htp-libhtp.h:84
HttpRangeFreeBlock
void HttpRangeFreeBlock(HttpRangeContainerBlock *b)
Definition: app-layer-htp-range.c:607
HtpTxUserData_::response_body_init
uint8_t response_body_init
Definition: app-layer-htp.h:215
HTTP_FRAME_RESPONSE
@ HTTP_FRAME_RESPONSE
Definition: app-layer-htp.c:182
str
#define str(s)
Definition: suricata-common.h:300
HTP_CONFIG_DEFAULT_COMPRESSION_BOMB_LIMIT
#define HTP_CONFIG_DEFAULT_COMPRESSION_BOMB_LIMIT
Definition: app-layer-htp.h:126
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:261
app-layer-htp-libhtp.h
SCRadix6Tree_
Structure for the radix tree.
Definition: util-radix6-tree.h:64
SCFree
#define SCFree(p)
Definition: util-mem.h:61
ConfNode_
Definition: conf.h:32
HTTP_DECODER_EVENT_MULTIPART_GENERIC_ERROR
@ HTTP_DECODER_EVENT_MULTIPART_GENERIC_ERROR
Definition: app-layer-htp.h:99
Flow_::alstate
void * alstate
Definition: flow.h:474
HTP_PROTOCOL_V0_9
#define HTP_PROTOCOL_V0_9
Definition: app-layer-htp-libhtp.h:86
HTP_PROTOCOL_V1_0
#define HTP_PROTOCOL_V1_0
Definition: app-layer-htp-libhtp.h:85
Flow_::flags
uint32_t flags
Definition: flow.h:419
AppLayerParserGetDecoderEvents
AppLayerDecoderEvents * AppLayerParserGetDecoderEvents(AppLayerParserState *pstate)
Definition: app-layer-parser.c:828
HTP_FLAGS_HOST_MISSING
#define HTP_FLAGS_HOST_MISSING
Definition: app-layer-htp-libhtp.h:68
StreamingBufferConfig_::Free
void(* Free)(void *ptr, size_t size)
Definition: util-streaming-buffer.h:71
HTP_REQUEST_PROGRESS_COMPLETE
#define HTP_REQUEST_PROGRESS_COMPLETE
Definition: app-layer-htp-libhtp.h:92
detect-parse.h
HTP_FLAGS_HOSTU_INVALID
#define HTP_FLAGS_HOSTU_INVALID
Definition: app-layer-htp-libhtp.h:70
FAIL
#define FAIL
Fail a test.
Definition: util-unittest.h:60
HTTP_SWF_COMPRESSION_BOTH
@ HTTP_SWF_COMPRESSION_BOTH
Definition: app-layer-htp.h:152
UTHAppLayerParserStateGetIds
void UTHAppLayerParserStateGetIds(void *ptr, uint64_t *i1, uint64_t *i2, uint64_t *log, uint64_t *min)
Definition: app-layer-parser.c:203
HTPCfgRec_
Definition: app-layer-htp.h:162
ConfValIsFalse
int ConfValIsFalse(const char *val)
Check if a value is false.
Definition: conf.c:561
HTP_LOG_CODE_REQUEST_LINE_INCOMPLETE
#define HTP_LOG_CODE_REQUEST_LINE_INCOMPLETE
Definition: app-layer-htp-libhtp.h:155
HTP_CONFIG_DEFAULT_RESPONSE_INSPECT_WINDOW
#define HTP_CONFIG_DEFAULT_RESPONSE_INSPECT_WINDOW
Definition: app-layer-htp.h:119
RegisterHTPParsers
void RegisterHTPParsers(void)
Register the HTTP protocol and state handling functions to APP layer of the engine.
Definition: app-layer-htp.c:2812
HTP_LOG_CODE_REQUEST_SERVER_PORT_TCP_PORT_MISMATCH
#define HTP_LOG_CODE_REQUEST_SERVER_PORT_TCP_PORT_MISMATCH
Definition: app-layer-htp-libhtp.h:135
SCRadix6AddKeyIPV6String
bool SCRadix6AddKeyIPV6String(SCRadix6Tree *tree, const SCRadix6Config *config, const char *str, void *user)
Adds a new IPV6/netblock to the Radix6 tree from a string.
Definition: util-radix6-tree.c:262
HTTP_SWF_COMPRESSION_LZMA
@ HTTP_SWF_COMPRESSION_LZMA
Definition: app-layer-htp.h:151
ALPROTO_UNKNOWN
@ ALPROTO_UNKNOWN
Definition: app-layer-protos.h:29
util-random.h
FLOW_PKT_ESTABLISHED
#define FLOW_PKT_ESTABLISHED
Definition: flow.h:233
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2609
AppLayerParserStateAlloc
AppLayerParserState * AppLayerParserStateAlloc(void)
Definition: app-layer-parser.c:224
HTP_METHOD_CONNECT
#define HTP_METHOD_CONNECT
Definition: app-layer-htp-libhtp.h:79
HtpState_::request_frame_id
FrameId request_frame_id
Definition: app-layer-htp.h:266
app-layer-protos.h
app-layer-htp-mem.h
EngineModeIsIPS
int EngineModeIsIPS(void)
Definition: suricata.c:232
suricata.h
HTPMalloc
void * HTPMalloc(size_t size)
Definition: app-layer-htp-mem.c:133
HTP_LOG_CODE_REQUEST_HEADER_INVALID
#define HTP_LOG_CODE_REQUEST_HEADER_INVALID
Definition: app-layer-htp-libhtp.h:123
AppLayerParserRegisterGetTxCnt
void AppLayerParserRegisterGetTxCnt(uint8_t ipproto, AppProto alproto, uint64_t(*StateGetTxCnt)(void *alstate))
Definition: app-layer-parser.c:495
HTTP_FRAME_REQUEST
@ HTTP_FRAME_REQUEST
Definition: app-layer-htp.c:181
StringParseInt8
int StringParseInt8(int8_t *res, int base, size_t len, const char *str)
Definition: util-byte.c:672
APP_LAYER_ERROR
#define APP_LAYER_ERROR
Definition: app-layer-parser.h:91
HTP_METHOD_PUT
#define HTP_METHOD_PUT
Definition: app-layer-htp-libhtp.h:78
htp_errors
struct @6 htp_errors[]
HTP_STREAM_STATE_TUNNEL
#define HTP_STREAM_STATE_TUNNEL
Definition: app-layer-htp-libhtp.h:82
ConfDeInit
void ConfDeInit(void)
De-initializes the configuration system.
Definition: conf.c:688
HTTP_DECODER_EVENT_RESPONSE_TOO_MANY_HEADERS
@ HTTP_DECODER_EVENT_RESPONSE_TOO_MANY_HEADERS
Definition: app-layer-htp.h:96
htp_conn_response_data_counter
#define htp_conn_response_data_counter(c)
Definition: app-layer-htp-libhtp.h:209
AppLayerParserRegisterGetEventInfoById
void AppLayerParserRegisterGetEventInfoById(uint8_t ipproto, AppProto alproto, int(*StateGetEventInfoById)(uint8_t event_id, const char **event_name, AppLayerEventType *event_type))
Definition: app-layer-parser.c:538
SCRadix6TreeRelease
void SCRadix6TreeRelease(SCRadix6Tree *tree, const SCRadix6Config *config)
Definition: util-radix6-tree.c:366
SC_RADIX6_TREE_INITIALIZER
#define SC_RADIX6_TREE_INITIALIZER
Definition: util-radix6-tree.h:76
htp_tx_data_len
#define htp_tx_data_len(d)
Definition: app-layer-htp-libhtp.h:203
likely
#define likely(expr)
Definition: util-optimize.h:32
HTP_LOG_CODE_COMPRESSION_BOMB
#define HTP_LOG_CODE_COMPRESSION_BOMB
Definition: app-layer-htp-libhtp.h:157
HTPFileClose
int HTPFileClose(HtpTxUserData *tx, const uint8_t *data, uint32_t data_len, uint8_t flags, uint8_t direction)
Close the file in the flow.
Definition: app-layer-htp-file.c:309
HtpTxUserData_::files_ts
FileContainer files_ts
Definition: app-layer-htp.h:240
DetectEngineCtx_::flags
uint8_t flags
Definition: detect.h:856
AppLayerParserThreadCtx_
Definition: app-layer-parser.c:58
SCHTPGenerateNormalizedUri
bstr * SCHTPGenerateNormalizedUri(htp_tx_t *tx, htp_uri_t *uri, bool uri_include_all)
Generates the normalized uri.
Definition: app-layer-htp-libhtp.c:64
HTPFree
void HTPFree(void *ptr, size_t size)
Definition: app-layer-htp-mem.c:199
Flow_::sp
Port sp
Definition: flow.h:359
SC_ATOMIC_GET
#define SC_ATOMIC_GET(name)
Get the value from the atomic variable.
Definition: util-atomic.h:375
htp_tx_response_status_number
#define htp_tx_response_status_number(tx)
Definition: app-layer-htp-libhtp.h:180
TcpSession_
Definition: stream-tcp-private.h:283
util-misc.h
HTPFreeConfig
void HTPFreeConfig(void)
Clears the HTTP server configuration memory used by HTP library.
Definition: app-layer-htp.c:1664
HTP_STREAM_STATE_ERROR
#define HTP_STREAM_STATE_ERROR
Definition: app-layer-htp-libhtp.h:81
HTP_CONFIG_DEFAULT_FIELD_LIMIT_HARD
#define HTP_CONFIG_DEFAULT_FIELD_LIMIT_HARD
Definition: app-layer-htp.h:121
HtpTxUserData_::response_headers_raw_len
uint32_t response_headers_raw_len
Definition: app-layer-htp.h:233
AppLayerParserStateIssetFlag
uint16_t AppLayerParserStateIssetFlag(AppLayerParserState *pstate, uint16_t flag)
Definition: app-layer-parser.c:1793
msg
const char * msg
Definition: app-layer-htp.c:559
HTP_LOG_CODE_HEADER_HOST_INVALID
#define HTP_LOG_CODE_HEADER_HOST_INVALID
Definition: app-layer-htp-libhtp.h:138
Flow_::alproto
AppProto alproto
application level protocol
Definition: flow.h:448
HtpTxUserData_::request_body_init
uint8_t request_body_init
Definition: app-layer-htp.h:214
HTP_CONFIG_DEFAULT_RANDOMIZE_RANGE
#define HTP_CONFIG_DEFAULT_RANDOMIZE_RANGE
Definition: app-layer-htp.h:131
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:275
HTP_SERVER_PERSONALITY_APACHE_2
#define HTP_SERVER_PERSONALITY_APACHE_2
Definition: app-layer-htp-libhtp.h:55
HTPFileOpenWithRange
int HTPFileOpenWithRange(HtpState *s, HtpTxUserData *txud, const uint8_t *filename, uint16_t filename_len, const uint8_t *data, uint32_t data_len, const htp_tx_t *tx, const bstr *rawvalue, HtpTxUserData *htud)
Sets range for a file.
Definition: app-layer-htp-file.c:149
http_frame_table
SCEnumCharMap http_frame_table[]
Definition: app-layer-htp.c:185
AppLayerProtoDetectConfProtoDetectionEnabled
int AppLayerProtoDetectConfProtoDetectionEnabled(const char *ipproto, const char *alproto)
Given a protocol name, checks if proto detection is enabled in the conf file.
Definition: app-layer-detect-proto.c:1959
HTP_LOG_CODE_RESPONSE_MULTIPART_BYTERANGES
#define HTP_LOG_CODE_RESPONSE_MULTIPART_BYTERANGES
Definition: app-layer-htp-libhtp.h:149
AppLayerDecoderEvents_::events
uint8_t * events
Definition: app-layer-events.h:38
SCMutex
#define SCMutex
Definition: threads-debug.h:114
HtpBodyAppendChunk
int HtpBodyAppendChunk(HtpBody *body, const uint8_t *data, uint32_t len)
Append a chunk of body to the HtpBody struct.
Definition: app-layer-htp-body.c:48
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:102
FLOW_DESTROY
#define FLOW_DESTROY(f)
Definition: flow-util.h:119
SCAppLayerGetEventIdByName
int SCAppLayerGetEventIdByName(const char *event_name, SCEnumCharMap *table, uint8_t *event_id)
Definition: app-layer-events.c:28
HTP_LOG_CODE_ABNORMAL_CE_HEADER
#define HTP_LOG_CODE_ABNORMAL_CE_HEADER
Definition: app-layer-htp-libhtp.h:148
htp_tx_request_auth_type
#define htp_tx_request_auth_type(tx)
Definition: app-layer-htp-libhtp.h:162
HTP_REQUIRE_REQUEST_FILE
#define HTP_REQUIRE_REQUEST_FILE
Definition: app-layer-htp.h:274
HTP_FLAGS_REQUEST_INVALID_C_L
#define HTP_FLAGS_REQUEST_INVALID_C_L
Definition: app-layer-htp-libhtp.h:67
StreamingBufferConfig_::Realloc
void *(* Realloc)(void *ptr, size_t orig_size, size_t size)
Definition: util-streaming-buffer.h:70
HTP_LOG_CODE_LZMA_MEMLIMIT_REACHED
#define HTP_LOG_CODE_LZMA_MEMLIMIT_REACHED
Definition: app-layer-htp-libhtp.h:156
HTTP_DECODER_EVENT_REQUEST_LINE_MISSING_PROTOCOL
@ HTTP_DECODER_EVENT_REQUEST_LINE_MISSING_PROTOCOL
Definition: app-layer-htp.h:94
htp_tx_request_header
#define htp_tx_request_header(tx, header)
Definition: app-layer-htp-libhtp.h:184
HtpTxUserData_::tsflags
uint8_t tsflags
Definition: app-layer-htp.h:220
PKT_STREAM_EST
#define PKT_STREAM_EST
Definition: decode.h:1263
HtpBody_::body_inspected
uint64_t body_inspected
Definition: app-layer-htp.h:202
AppLayerProtoDetectGetProtoName
const char * AppLayerProtoDetectGetProtoName(AppProto alproto)
Definition: app-layer-detect-proto.c:2088
SC_ATOMIC_OR
#define SC_ATOMIC_OR(name, val)
Bitwise OR a value to our atomic variable.
Definition: util-atomic.h:350
app-layer.h
SCTIME_USECS
#define SCTIME_USECS(t)
Definition: util-time.h:56
g_disable_randomness
int g_disable_randomness
Definition: suricata.c:192
HtpState_::htp_messages_offset
uint16_t htp_messages_offset
Definition: app-layer-htp.h:261
UTHFreePackets
void UTHFreePackets(Packet **p, int numpkts)
UTHFreePackets: function to release the allocated data from UTHBuildPacket and the packet itself.
Definition: util-unittest-helper.c:450