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