99 #define HTP_MAX_MESSAGES 512
105 static uint64_t htp_state_memuse = 0;
106 static uint64_t htp_state_memcnt = 0;
116 {
"INVALID_TRANSFER_ENCODING_VALUE_IN_REQUEST",
118 {
"INVALID_TRANSFER_ENCODING_VALUE_IN_RESPONSE",
120 {
"INVALID_CONTENT_LENGTH_FIELD_IN_REQUEST",
122 {
"INVALID_CONTENT_LENGTH_FIELD_IN_RESPONSE",
124 {
"DUPLICATE_CONTENT_LENGTH_FIELD_IN_REQUEST",
126 {
"DUPLICATE_CONTENT_LENGTH_FIELD_IN_RESPONSE",
129 {
"UNABLE_TO_MATCH_RESPONSE_TO_REQUEST",
144 {
"REQUEST_SERVER_PORT_TCP_PORT_MISMATCH",
158 {
"RESPONSE_ABNORMAL_TRANSFER_ENCODING",
200 static int HTTPGetFrameIdByName(
const char *frame_name)
209 static const char *HTTPGetFrameNameById(
const uint8_t frame_id)
215 static void *HTPStateGetTx(
void *alstate, uint64_t tx_id);
216 static int HTPStateGetAlstateProgress(
void *tx, uint8_t direction);
217 static uint64_t HTPStateGetTxCnt(
void *alstate);
219 static void HTPParserRegisterTests(
void);
222 static inline uint64_t HtpGetActiveRequestTxID(
HtpState *s)
224 uint64_t
id = HTPStateGetTxCnt(s);
229 static inline uint64_t HtpGetActiveResponseTxID(
HtpState *s)
242 static const char *HTPLookupPersonalityString(
int p)
244 #define CASE_HTP_PERSONALITY_STRING(p) \
245 case HTP_SERVER_ ## p: return #p
248 CASE_HTP_PERSONALITY_STRING(MINIMAL);
249 CASE_HTP_PERSONALITY_STRING(GENERIC);
250 CASE_HTP_PERSONALITY_STRING(IDS);
251 CASE_HTP_PERSONALITY_STRING(IIS_4_0);
252 CASE_HTP_PERSONALITY_STRING(IIS_5_0);
253 CASE_HTP_PERSONALITY_STRING(IIS_5_1);
254 CASE_HTP_PERSONALITY_STRING(IIS_6_0);
255 CASE_HTP_PERSONALITY_STRING(IIS_7_0);
256 CASE_HTP_PERSONALITY_STRING(IIS_7_5);
257 CASE_HTP_PERSONALITY_STRING(APACHE_2);
271 static int HTPLookupPersonality(
const char *
str)
273 #define IF_HTP_PERSONALITY_NUM(p) \
274 if (strcasecmp(#p, str) == 0) return HTP_SERVER_ ## p
286 if (strcasecmp(
"TOMCAT_6_0",
str) == 0) {
288 "longer supported by libhtp.",
291 }
else if ((strcasecmp(
"APACHE",
str) == 0) ||
292 (strcasecmp(
"APACHE_2_2",
str) == 0))
295 "longer supported by libhtp, failing back to "
296 "Apache2 personality.",
298 return HTP_SERVER_APACHE_2;
305 const uint8_t dir,
const uint8_t e)
315 const uint64_t tx_id = (dir == STREAM_TOSERVER) ?
316 HtpGetActiveRequestTxID(s) : HtpGetActiveResponseTxID(s);
318 htp_tx_t *tx = HTPStateGetTx(s, tx_id);
319 if (tx == NULL && tx_id > 0)
320 tx = HTPStateGetTx(s, tx_id - 1);
335 static void *HTPStateAlloc(
void *orig_state,
AppProto proto_orig)
349 htp_state_memuse +=
sizeof(
HtpState);
350 SCLogDebug(
"htp memory %"PRIu64
" (%"PRIu64
")", htp_state_memuse, htp_state_memcnt);
370 if (htud->
tx_data.de_state != NULL) {
396 if (s->
connp != NULL) {
400 uint64_t total_txs = HTPStateGetTxCnt(state);
402 if (s->
conn != NULL) {
403 for (tx_id = 0; tx_id < total_txs; tx_id++) {
404 htp_tx_t *tx = HTPStateGetTx(s, tx_id);
407 HtpTxUserDataFree(s, htud);
408 htp_tx_set_user_data(tx, NULL);
412 htp_connp_destroy_all(s->
connp);
420 htp_state_memuse -=
sizeof(
HtpState);
421 SCLogDebug(
"htp memory %"PRIu64
" (%"PRIu64
")", htp_state_memuse, htp_state_memcnt);
434 static void HTPStateTransactionFree(
void *state, uint64_t
id)
442 htp_tx_t *tx = HTPStateGetTx(s,
id);
446 HtpTxUserDataFree(s, htud);
447 htp_tx_set_user_data(tx, NULL);
454 tx->request_progress == HTP_REQUEST_COMPLETE &&
455 tx->response_progress == HTP_RESPONSE_COMPLETE)))
457 tx->request_progress = HTP_REQUEST_COMPLETE;
458 tx->response_progress = HTP_RESPONSE_COMPLETE;
496 static void AppLayerHtpNeedMultipartHeader(
void)
514 AppLayerHtpNeedMultipartHeader();
522 static void AppLayerHtpSetStreamDepthFlag(
void *tx,
const uint8_t
flags)
527 if (
flags & STREAM_TOCLIENT) {
537 SCLogDebug(
"cfg->body_limit %u stream_depth %u body->content_len_so_far %" PRIu64,
554 static uint32_t AppLayerHtpComputeChunkLength(uint64_t content_len_so_far, uint32_t body_limit,
555 uint32_t stream_depth, uint8_t
flags, uint32_t data_len)
557 uint32_t chunk_len = 0;
559 (content_len_so_far < (uint64_t)body_limit) &&
560 (content_len_so_far + (uint64_t)data_len) > body_limit)
562 chunk_len = body_limit - content_len_so_far;
564 (content_len_so_far < (uint64_t)stream_depth) &&
565 (content_len_so_far + (uint64_t)data_len) > stream_depth)
567 chunk_len = stream_depth - content_len_so_far;
570 return (chunk_len == 0 ? data_len : chunk_len);
634 #define HTP_ERROR_MAX (sizeof(htp_errors) / sizeof(htp_errors[0]))
635 #define HTP_WARNING_MAX (sizeof(htp_warnings) / sizeof(htp_warnings[0]))
646 static uint8_t HTPHandleWarningGetId(
const char *
msg)
670 static uint8_t HTPHandleErrorGetId(
const char *
msg)
694 static void HTPHandleError(
HtpState *s,
const uint8_t dir)
696 if (s == NULL || s->
conn == NULL ||
697 s->
conn->messages == NULL) {
701 size_t size = htp_list_size(s->
conn->messages);
716 htp_log_t *log = htp_list_get(s->
conn->messages,
msg);
721 htp_tx_t *tx = log->tx;
727 uint8_t
id = HTPHandleErrorGetId(log->msg);
729 id = HTPHandleWarningGetId(log->msg);
735 HTPSetEvent(s, htud, dir,
id);
742 static inline void HTPErrorCheckTxRequestFlags(
HtpState *s, htp_tx_t *tx)
745 BUG_ON(s == NULL || tx == NULL);
747 if (tx->flags & ( HTP_REQUEST_INVALID_T_E|HTP_REQUEST_INVALID_C_L|
748 HTP_HOST_MISSING|HTP_HOST_AMBIGUOUS|HTP_HOSTU_INVALID|
755 if (tx->flags & HTP_REQUEST_INVALID_T_E)
756 HTPSetEvent(s, htud, STREAM_TOSERVER,
758 if (tx->flags & HTP_REQUEST_INVALID_C_L)
759 HTPSetEvent(s, htud, STREAM_TOSERVER,
761 if (tx->flags & HTP_HOST_MISSING)
762 HTPSetEvent(s, htud, STREAM_TOSERVER,
764 if (tx->flags & HTP_HOST_AMBIGUOUS)
765 HTPSetEvent(s, htud, STREAM_TOSERVER,
767 if (tx->flags & HTP_HOSTU_INVALID)
768 HTPSetEvent(s, htud, STREAM_TOSERVER,
770 if (tx->flags & HTP_HOSTH_INVALID)
771 HTPSetEvent(s, htud, STREAM_TOSERVER,
774 if (tx->request_auth_type == HTP_AUTH_UNRECOGNIZED) {
778 HTPSetEvent(s, htud, STREAM_TOSERVER,
781 if (tx->is_protocol_0_9 && tx->request_method_number == HTP_M_UNKNOWN &&
782 (tx->request_protocol_number == HTP_PROTOCOL_INVALID ||
783 tx->request_protocol_number == HTP_PROTOCOL_UNKNOWN)) {
787 HTPSetEvent(s, htud, STREAM_TOSERVER,
798 htp_cfg_t *htp = cfglist.
cfg;
799 void *user_data = NULL;
814 if (user_data != NULL) {
815 htp_cfg_rec = user_data;
816 htp = htp_cfg_rec->
cfg;
819 SCLogDebug(
"Using default HTP config: %p", htp);
823 #ifdef DEBUG_VALIDATION
830 hstate->
connp = htp_connp_create(htp);
831 if (hstate->
connp == NULL) {
835 hstate->
conn = htp_connp_get_connection(hstate->
connp);
837 htp_connp_set_user_data(hstate->
connp, (
void *)hstate);
838 hstate->
cfg = htp_cfg_rec;
843 htp_connp_open(hstate->
connp, NULL, f->
sp, NULL, f->
dp, &
tv);
865 StreamSlice stream_slice,
void *local_data)
875 if (NULL == hstate->
conn) {
876 if (Setup(f, hstate) != 0) {
881 hstate->
slice = &stream_slice;
883 const uint8_t *input = StreamSliceGetData(&stream_slice);
884 uint32_t input_len = StreamSliceGetDataLen(&stream_slice);
889 const int r = htp_connp_req_data(hstate->
connp, &
ts, input, input_len);
891 case HTP_STREAM_ERROR:
897 HTPHandleError(hstate, STREAM_TOSERVER);
904 htp_connp_req_close(hstate->
connp, &
ts);
906 SCLogDebug(
"stream eof encountered, closing htp handle for ts");
910 hstate->
slice = NULL;
932 StreamSlice stream_slice,
void *local_data)
938 const uint8_t *input = StreamSliceGetData(&stream_slice);
939 uint32_t input_len = StreamSliceGetDataLen(&stream_slice);
945 if (NULL == hstate->
conn) {
946 if (Setup(f, hstate) != 0) {
951 hstate->
slice = &stream_slice;
957 const int r = htp_connp_res_data(hstate->
connp, &
ts, input, input_len);
959 case HTP_STREAM_ERROR:
962 case HTP_STREAM_TUNNEL:
963 tx = htp_connp_get_out_tx(hstate->
connp);
964 if (tx != NULL && tx->response_status_number == 101) {
966 (htp_header_t *)htp_table_get_c(tx->response_headers,
"Upgrade");
967 if (h == NULL || bstr_cmp_c(h->value,
"h2c") != 0) {
975 if (tx->request_port_number != -1) {
976 dp = (uint16_t)tx->request_port_number;
978 consumed = htp_connp_res_data_consumed(hstate->
connp);
979 hstate->
slice = NULL;
981 HTPSetEvent(hstate, NULL, STREAM_TOCLIENT,
986 if (consumed > 0 && consumed < input_len) {
995 HTPHandleError(hstate, STREAM_TOCLIENT);
1002 htp_connp_close(hstate->
connp, &
ts);
1007 hstate->
slice = NULL;
1018 static int HTTPParseContentDispositionHeader(uint8_t *name,
size_t name_len,
1019 uint8_t *data,
size_t len, uint8_t **retptr,
size_t *retlen)
1022 printf(
"DATA START: \n");
1024 printf(
"DATA END: \n");
1029 for (x = 0; x <
len; x++) {
1030 if (!(isspace(data[x])))
1037 uint8_t *line = data+x;
1038 size_t line_len =
len-x;
1041 printf(
"LINE START: \n");
1043 printf(
"LINE END: \n");
1045 for (x = 0 ; x < line_len; x++) {
1047 if (line[x - 1] !=
'\\' && line[x] ==
'\"') {
1051 if (((line[x - 1] !=
'\\' && line[x] ==
';') || ((x + 1) == line_len)) && (quote == 0 || quote % 2 == 0)) {
1052 uint8_t *token = line +
offset;
1053 size_t token_len = x -
offset;
1055 if ((x + 1) == line_len) {
1066 printf(
"TOKEN START: \n");
1068 printf(
"TOKEN END: \n");
1070 if (token_len > name_len) {
1071 if (name == NULL || SCMemcmpLowercase(name, token, name_len) == 0) {
1072 uint8_t *value = token + name_len;
1073 size_t value_len = token_len - name_len;
1075 if (value[0] ==
'\"') {
1079 if (value[value_len-1] ==
'\"') {
1083 printf(
"VALUE START: \n");
1085 printf(
"VALUE END: \n");
1088 *retlen = value_len;
1102 static int HTTPParseContentTypeHeader(uint8_t *name,
size_t name_len,
1103 uint8_t *data,
size_t len, uint8_t **retptr,
size_t *retlen)
1107 printf(
"DATA START: \n");
1109 printf(
"DATA END: \n");
1114 for (x = 0; x <
len; x++) {
1115 if (!(isspace(data[x])))
1123 uint8_t *line = data+x;
1124 size_t line_len =
len-x;
1127 printf(
"LINE START: \n");
1129 printf(
"LINE END: \n");
1131 for (x = 0 ; x < line_len; x++) {
1133 if (line[x - 1] !=
'\\' && line[x] ==
'\"') {
1137 if (((line[x - 1] !=
'\\' && line[x] ==
';') || ((x + 1) == line_len)) && (quote == 0 || quote % 2 == 0)) {
1138 uint8_t *token = line +
offset;
1139 size_t token_len = x -
offset;
1141 if ((x + 1) == line_len) {
1152 printf(
"TOKEN START: \n");
1154 printf(
"TOKEN END: \n");
1156 if (token_len > name_len) {
1157 if (name == NULL || SCMemcmpLowercase(name, token, name_len) == 0) {
1158 uint8_t *value = token + name_len;
1159 size_t value_len = token_len - name_len;
1161 if (value[0] ==
'\"') {
1165 if (value[value_len-1] ==
'\"') {
1169 printf(
"VALUE START: \n");
1171 printf(
"VALUE END: \n");
1174 *retlen = value_len;
1198 static int HtpRequestBodySetupMultipart(htp_tx_t *tx,
HtpTxUserData *htud)
1200 htp_header_t *h = (htp_header_t *)htp_table_get_c(tx->request_headers,
1202 if (h != NULL && bstr_len(h->value) > 0) {
1203 uint8_t *boundary = NULL;
1204 size_t boundary_len = 0;
1206 int r = HTTPParseContentTypeHeader((uint8_t *)
"boundary=", 9,
1207 (uint8_t *) bstr_ptr(h->value), bstr_len(h->value),
1208 &boundary, &boundary_len);
1211 printf(
"BOUNDARY START: \n");
1213 printf(
"BOUNDARY END: \n");
1221 memcpy(htud->
boundary, boundary, boundary_len);
1235 #define C_D_HDR "content-disposition:"
1236 #define C_D_HDR_LEN 20
1237 #define C_T_HDR "content-type:"
1238 #define C_T_HDR_LEN 13
1240 static void HtpRequestBodyMultipartParseHeader(
HtpState *hstate,
1242 uint8_t *header, uint32_t header_len,
1243 uint8_t **filename, uint16_t *filename_len,
1244 uint8_t **filetype, uint16_t *filetype_len)
1252 printf(
"HEADER START: \n");
1254 printf(
"HEADER END: \n");
1257 while (header_len > 0) {
1258 uint8_t *next_line =
Bs2bmSearch(header, header_len, (uint8_t *)
"\r\n", 2);
1259 uint8_t *line = header;
1262 if (next_line == NULL) {
1263 line_len = header_len;
1265 line_len = next_line - header;
1267 uint8_t *sc = (uint8_t *)memchr(line,
':', line_len);
1269 HTPSetEvent(hstate, htud, STREAM_TOSERVER,
1273 }
else if (line_len > 0 && sc == &line[line_len - 1]) {
1274 HTPSetEvent(hstate, htud, STREAM_TOSERVER,
1278 printf(
"LINE START: \n");
1280 printf(
"LINE END: \n");
1288 (void)HTTPParseContentDispositionHeader((uint8_t *)
"filename=", 9,
1289 value, value_len, &fn, &fn_len);
1296 (void)HTTPParseContentTypeHeader(NULL, 0,
1297 value, value_len, &ft, &ft_len);
1301 if (next_line == NULL) {
1305 header_len -= ((next_line + 2) - header);
1306 header = next_line + 2;
1309 if (fn_len > USHRT_MAX)
1311 if (ft_len > USHRT_MAX)
1315 *filename_len = (uint16_t)fn_len;
1317 *filetype_len = (uint16_t)ft_len;
1328 const uint8_t **chunks_buffer, uint32_t *chunks_buffer_len)
1331 chunks_buffer, chunks_buffer_len,
1335 static void FlagDetectStateNewFile(
HtpTxUserData *tx,
int dir)
1338 if (tx && tx->
tx_data.de_state) {
1339 if (dir == STREAM_TOSERVER) {
1340 SCLogDebug(
"DETECT_ENGINE_STATE_FLAG_FILE_NEW set");
1342 }
else if (STREAM_TOCLIENT) {
1343 SCLogDebug(
"DETECT_ENGINE_STATE_FLAG_FILE_NEW set");
1352 static void HtpRequestBodySetupBoundary(
HtpTxUserData *htud,
1353 uint8_t *boundary, uint32_t boundary_len)
1355 memset(boundary,
'-', boundary_len);
1360 const uint8_t *chunks_buffer, uint32_t chunks_buffer_len)
1364 uint16_t expected_boundary_len = htud->
boundary_len + 2;
1365 uint16_t expected_boundary_end_len = htud->
boundary_len + 4;
1366 int tx_progress = 0;
1369 printf(
"CHUNK START: \n");
1371 printf(
"CHUNK END: \n");
1374 HtpRequestBodySetupBoundary(htud, boundary, htud->
boundary_len + 4);
1377 const uint8_t *header_start =
Bs2bmSearch(chunks_buffer, chunks_buffer_len,
1378 boundary, expected_boundary_len);
1380 const uint8_t *form_end = NULL;
1382 const uint8_t *header_end = NULL;
1383 if (header_start != NULL) {
1384 header_end =
Bs2bmSearch(header_start, chunks_buffer_len - (header_start - chunks_buffer),
1385 (uint8_t *)
"\r\n\r\n", 4);
1386 form_end =
Bs2bmSearch(header_start, chunks_buffer_len - (header_start - chunks_buffer),
1387 boundary, expected_boundary_end_len);
1390 SCLogDebug(
"header_start %p, header_end %p, form_end %p", header_start,
1391 header_end, form_end);
1398 if (header_start != NULL || (tx_progress > HTP_REQUEST_BODY)) {
1401 const uint8_t *filedata = chunks_buffer;
1402 uint32_t filedata_len = 0;
1405 if (header_start != NULL) {
1406 if (header_start == filedata + 2) {
1408 SCLogDebug(
"last chunk had all data, but not the boundary");
1410 }
else if (header_start > filedata + 2) {
1411 SCLogDebug(
"some data from last file before the boundary");
1413 filedata_len = header_start - filedata - 2;
1418 if (tx_progress > HTP_REQUEST_BODY) {
1419 filedata_len = chunks_buffer_len;
1423 if (filedata_len > chunks_buffer_len) {
1424 HTPSetEvent(hstate, htud, STREAM_TOSERVER,
1429 printf(
"FILEDATA (final chunk) START: \n");
1431 printf(
"FILEDATA (final chunk) END: \n");
1434 if (
HTPFileClose(hstate, htud, filedata, filedata_len,
flags, STREAM_TOSERVER) ==
1444 SCLogDebug(
"not yet at the end of the file");
1446 if (chunks_buffer_len > expected_boundary_end_len) {
1447 const uint8_t *filedata = chunks_buffer;
1448 uint32_t filedata_len = chunks_buffer_len - expected_boundary_len;
1449 for (; filedata_len < chunks_buffer_len; filedata_len++) {
1451 if (chunks_buffer[filedata_len] ==
'\r') {
1452 if (filedata_len + 1 == chunks_buffer_len ||
1453 chunks_buffer[filedata_len + 1] ==
'\n') {
1460 printf(
"FILEDATA (part) START: \n");
1462 printf(
"FILEDATA (part) END: \n");
1467 hstate, htud, filedata, filedata_len, STREAM_TOSERVER);
1470 }
else if (result == -2) {
1478 SCLogDebug(
"chunk too small to already process in part");
1485 while (header_start != NULL && header_end != NULL &&
1486 header_end != form_end &&
1487 header_start < (chunks_buffer + chunks_buffer_len) &&
1488 header_end < (chunks_buffer + chunks_buffer_len) &&
1489 header_start < header_end)
1491 uint8_t *filename = NULL;
1492 uint16_t filename_len = 0;
1493 uint8_t *filetype = NULL;
1494 uint16_t filetype_len = 0;
1496 uint32_t header_len = header_end - header_start;
1498 uint8_t *header = (uint8_t *)header_start;
1501 if (expected_boundary_len == header_len) {
1503 }
else if ((uint32_t)(expected_boundary_len + 2) <= header_len) {
1504 header_len -= (expected_boundary_len + 2);
1505 header = (uint8_t *)header_start + (expected_boundary_len + 2);
1508 HtpRequestBodyMultipartParseHeader(hstate, htud, header, header_len,
1509 &filename, &filename_len, &filetype, &filetype_len);
1511 if (filename != NULL) {
1512 const uint8_t *filedata = NULL;
1513 uint32_t filedata_len = 0;
1524 if (form_end != NULL) {
1527 filedata = header_end + 4;
1528 if (form_end == filedata) {
1529 HTPSetEvent(hstate, htud, STREAM_TOSERVER,
1532 }
else if (form_end < filedata) {
1533 HTPSetEvent(hstate, htud, STREAM_TOSERVER,
1538 filedata_len = form_end - (header_end + 4 + 2);
1539 SCLogDebug(
"filedata_len %"PRIuMAX, (uintmax_t)filedata_len);
1542 uint8_t *header_next =
Bs2bmSearch(filedata, filedata_len,
1543 boundary, expected_boundary_len);
1544 if (header_next != NULL) {
1545 filedata_len -= (form_end - header_next);
1548 if (filedata_len > chunks_buffer_len) {
1549 HTPSetEvent(hstate, htud, STREAM_TOSERVER,
1553 SCLogDebug(
"filedata_len %"PRIuMAX, (uintmax_t)filedata_len);
1555 printf(
"FILEDATA START: \n");
1557 printf(
"FILEDATA END: \n");
1560 result =
HTPFileOpen(hstate, htud, filename, filename_len, filedata, filedata_len,
1561 HtpGetActiveRequestTxID(hstate), STREAM_TOSERVER);
1564 }
else if (result == -2) {
1567 if (
HTPFileClose(hstate, htud, NULL, 0, 0, STREAM_TOSERVER) == -1) {
1571 FlagDetectStateNewFile(htud, STREAM_TOSERVER);
1576 SCLogDebug(
"chunk doesn't contain form end");
1578 filedata = header_end + 4;
1579 filedata_len = chunks_buffer_len - (filedata - chunks_buffer);
1580 SCLogDebug(
"filedata_len %u (chunks_buffer_len %u)", filedata_len, chunks_buffer_len);
1582 if (filedata_len > chunks_buffer_len) {
1583 HTPSetEvent(hstate, htud, STREAM_TOSERVER,
1589 printf(
"FILEDATA START: \n");
1591 printf(
"FILEDATA END: \n");
1595 uint8_t *header_next =
Bs2bmSearch(filedata, filedata_len,
1596 boundary, expected_boundary_len);
1598 if (header_next == NULL) {
1601 uint32_t
offset = (header_end + 4) - chunks_buffer;
1605 if (filedata_len >= (uint32_t)(expected_boundary_len + 2)) {
1606 filedata_len -= (expected_boundary_len + 2 - 1);
1607 SCLogDebug(
"opening file with partial data");
1612 result =
HTPFileOpen(hstate, htud, filename, filename_len, filedata,
1613 filedata_len, HtpGetActiveRequestTxID(hstate), STREAM_TOSERVER);
1616 }
else if (result == -2) {
1619 FlagDetectStateNewFile(htud, STREAM_TOSERVER);
1623 }
else if (header_next - filedata > 2) {
1624 filedata_len = header_next - filedata - 2;
1627 result =
HTPFileOpen(hstate, htud, filename, filename_len, filedata,
1628 filedata_len, HtpGetActiveRequestTxID(hstate), STREAM_TOSERVER);
1631 }
else if (result == -2) {
1634 if (
HTPFileClose(hstate, htud, NULL, 0, 0, STREAM_TOSERVER) == -1) {
1638 FlagDetectStateNewFile(htud, STREAM_TOSERVER);
1646 SCLogDebug(
"header_start %p, header_end %p, form_end %p",
1647 header_start, header_end, form_end);
1650 uint32_t cursizeread = header_end - chunks_buffer;
1652 chunks_buffer_len - (cursizeread + 4),
1653 boundary, expected_boundary_len);
1654 if (header_start != NULL) {
1656 chunks_buffer_len - (cursizeread + 4),
1657 (uint8_t *)
"\r\n\r\n", 4);
1664 if (chunks_buffer_len > expected_boundary_end_len) {
1665 uint32_t move = chunks_buffer_len - expected_boundary_end_len + 1;
1668 SCLogDebug(
"form not ready, file not set, parsing non-file "
1669 "record: moved %u", move);
1682 htp_tx_t *tx, uint8_t *data, uint32_t data_len)
1689 uint8_t *filename = NULL;
1690 size_t filename_len = 0;
1693 if (tx->parsed_uri != NULL && tx->parsed_uri->path != NULL) {
1694 filename = (uint8_t *)bstr_ptr(tx->parsed_uri->path);
1695 filename_len = bstr_len(tx->parsed_uri->path);
1698 if (filename != NULL) {
1704 result =
HTPFileOpen(hstate, htud, filename, (uint16_t)filename_len, data, data_len,
1705 HtpGetActiveRequestTxID(hstate), STREAM_TOSERVER);
1708 }
else if (result == -2) {
1711 FlagDetectStateNewFile(htud, STREAM_TOSERVER);
1725 }
else if (result == -2) {
1738 htp_tx_t *tx, uint8_t *data, uint32_t data_len)
1749 (tx->response_line != NULL || tx->is_protocol_0_9))
1753 uint8_t *filename = NULL;
1754 size_t filename_len = 0;
1757 htp_header_t *h = (htp_header_t *)htp_table_get_c(tx->response_headers,
1758 "Content-Disposition");
1759 if (h != NULL && bstr_len(h->value) > 0) {
1761 (void)HTTPParseContentDispositionHeader((uint8_t *)
"filename=", 9,
1762 (uint8_t *) bstr_ptr(h->value), bstr_len(h->value), &filename, &filename_len);
1766 if (filename == NULL) {
1768 if (tx->parsed_uri != NULL && tx->parsed_uri->path != NULL) {
1769 filename = (uint8_t *)bstr_ptr(tx->parsed_uri->path);
1770 filename_len = bstr_len(tx->parsed_uri->path);
1774 if (filename != NULL) {
1776 htp_header_t *h_content_range = htp_table_get_c(tx->response_headers,
"content-range");
1782 if (h_content_range != NULL) {
1784 data_len, HtpGetActiveResponseTxID(hstate), h_content_range->value, htud);
1786 result =
HTPFileOpen(hstate, htud, filename, (uint16_t)filename_len, data, data_len,
1787 HtpGetActiveResponseTxID(hstate), STREAM_TOCLIENT);
1792 }
else if (result == -2) {
1795 FlagDetectStateNewFile(htud, STREAM_TOCLIENT);
1801 else if (tx->response_line != NULL || tx->is_protocol_0_9)
1810 }
else if (result == -2) {
1828 static int HTPCallbackRequestBodyData(htp_tx_data_t *d)
1839 printf(
"HTPBODY START: \n");
1841 printf(
"HTPBODY END: \n");
1844 HtpState *hstate = htp_connp_get_user_data(d->tx->connp);
1845 if (hstate == NULL) {
1849 SCLogDebug(
"New request body data available at %p -> %p -> %p, bodylen "
1850 "%"PRIu32
"", hstate, d, d->data, (uint32_t)d->len);
1853 if (tx_ud == NULL) {
1861 if (d->tx->request_method_number == HTP_M_POST) {
1863 int r = HtpRequestBodySetupMultipart(d->tx, tx_ud);
1866 }
else if (r == 0) {
1870 }
else if (d->tx->request_method_number == HTP_M_PUT) {
1893 const uint8_t *chunks_buffer = NULL;
1894 uint32_t chunks_buffer_len = 0;
1902 HtpRequestBodyReassemble(tx_ud, &chunks_buffer, &chunks_buffer_len);
1903 if (chunks_buffer == NULL) {
1907 printf(
"REASSCHUNK START: \n");
1909 printf(
"REASSCHUNK END: \n");
1912 HtpRequestBodyHandleMultipart(hstate, tx_ud, d->tx, chunks_buffer, chunks_buffer_len);
1916 HtpRequestBodyHandlePOSTorPUT(hstate, tx_ud, d->tx, (uint8_t *)d->data,
len);
1921 SCLogDebug(
"closing file that was being stored");
1928 if (hstate->
conn != NULL) {
1929 SCLogDebug(
"checking body size %"PRIu64
" against inspect limit %u (cur %"PRIu64
", last %"PRIu64
")",
1943 const uint32_t data_size = (uint32_t)(
1964 static int HTPCallbackResponseBodyData(htp_tx_data_t *d)
1974 HtpState *hstate = htp_connp_get_user_data(d->tx->connp);
1975 if (hstate == NULL) {
1979 SCLogDebug(
"New response body data available at %p -> %p -> %p, bodylen "
1980 "%"PRIu32
"", hstate, d, d->data, (uint32_t)d->len);
1983 if (tx_ud == NULL) {
2009 HtpResponseBodyHandle(hstate, tx_ud, d->tx, (uint8_t *)d->data,
len);
2012 SCLogDebug(
"closing file that was being stored");
2018 if (hstate->
conn != NULL) {
2019 SCLogDebug(
"checking body size %"PRIu64
" against inspect limit %u (cur %"PRIu64
", last %"PRIu64
")",
2032 const uint32_t data_size = (uint32_t)((uint64_t)hstate->
conn->out_data_counter -
2056 SCLogDebug(
"http_state_memcnt %"PRIu64
", http_state_memuse %"PRIu64
"",
2057 htp_state_memcnt, htp_state_memuse);
2077 htp_config_destroy(cfglist.
cfg);
2078 while (nextrec != NULL) {
2080 nextrec = nextrec->
next;
2082 htp_config_destroy(htprec->
cfg);
2088 static int HTPCallbackRequestHasTrailer(htp_tx_t *tx)
2097 static int HTPCallbackResponseHasTrailer(htp_tx_t *tx)
2110 static int HTPCallbackRequestStart(htp_tx_t *tx)
2112 HtpState *hstate = htp_connp_get_user_data(tx->connp);
2113 if (hstate == NULL) {
2117 uint64_t consumed = hstate->
slice->offset + htp_connp_req_data_consumed(hstate->
connp);
2118 SCLogDebug(
"HTTP request start: data offset %" PRIu64
", in_data_counter %" PRIu64, consumed,
2119 (uint64_t)hstate->
conn->in_data_counter);
2136 if (tx_ud == NULL) {
2141 tx_ud->
tx_data.file_tx = STREAM_TOSERVER | STREAM_TOCLIENT;
2142 htp_tx_set_user_data(tx, tx_ud);
2151 static int HTPCallbackResponseStart(htp_tx_t *tx)
2153 HtpState *hstate = htp_connp_get_user_data(tx->connp);
2154 if (hstate == NULL) {
2158 uint64_t consumed = hstate->
slice->offset + htp_connp_res_data_consumed(hstate->
connp);
2159 SCLogDebug(
"HTTP response start: data offset %" PRIu64
", out_data_counter %" PRIu64, consumed,
2160 (uint64_t)hstate->
conn->out_data_counter);
2175 if (tx_ud == NULL) {
2182 htp_tx_set_user_data(tx, tx_ud);
2193 static int HTPCallbackRequestComplete(htp_tx_t *tx)
2201 HtpState *hstate = htp_connp_get_user_data(tx->connp);
2202 if (hstate == NULL) {
2206 const uint64_t abs_right_edge =
2207 hstate->
slice->offset + htp_connp_req_data_consumed(hstate->
connp);
2215 SCLogDebug(
"HTTP request complete: data offset %" PRIu64
", request_size %" PRIu64,
2217 SCLogDebug(
"frame %p/%" PRIi64
" setting len to %" PRIu64, frame, frame->
id,
2219 frame->
len = (int64_t)request_size;
2225 SCLogDebug(
"transaction_cnt %"PRIu64
", list_size %"PRIu64,
2230 HTPErrorCheckTxRequestFlags(hstate, tx);
2235 SCLogDebug(
"closing file that was being stored");
2236 (void)
HTPFileClose(hstate, htud, NULL, 0, 0, STREAM_TOSERVER);
2238 if (abs_right_edge < (uint64_t)UINT32_MAX) {
2240 hstate->
f->
protoctx, STREAM_TOSERVER, (uint32_t)abs_right_edge);
2258 static int HTPCallbackResponseComplete(htp_tx_t *tx)
2262 HtpState *hstate = htp_connp_get_user_data(tx->connp);
2263 if (hstate == NULL) {
2270 const uint64_t abs_right_edge =
2271 hstate->
slice->offset + htp_connp_res_data_consumed(hstate->
connp);
2278 SCLogDebug(
"HTTP response complete: data offset %" PRIu64
", response_size %" PRIu64,
2280 SCLogDebug(
"frame %p/%" PRIi64
" setting len to %" PRIu64, frame, frame->
id,
2282 frame->
len = (int64_t)response_size;
2290 SCLogDebug(
"closing file that was being stored");
2291 (void)
HTPFileClose(hstate, htud, NULL, 0, 0, STREAM_TOCLIENT);
2301 if (tx->request_method_number == HTP_M_CONNECT) {
2304 if ((tx->response_status_number >= 200) &&
2305 (tx->response_status_number < 300) &&
2308 if (tx->request_port_number != -1) {
2309 dp = (uint16_t)tx->request_port_number;
2316 tx->request_progress = HTP_REQUEST_COMPLETE;
2317 tx->response_progress = HTP_RESPONSE_COMPLETE;
2325 static int HTPCallbackRequestLine(htp_tx_t *tx)
2328 bstr *request_uri_normalized;
2329 HtpState *hstate = htp_connp_get_user_data(tx->connp);
2333 if (request_uri_normalized == NULL)
2336 tx_ud = htp_tx_get_user_data(tx);
2338 bstr_free(request_uri_normalized);
2346 HTPErrorCheckTxRequestFlags(hstate, tx);
2351 static int HTPCallbackDoubleDecodeUriPart(htp_tx_t *tx, bstr *part)
2357 size_t prevlen = bstr_len(part);
2358 htp_status_t res = htp_urldecode_inplace(tx->cfg, HTP_DECODER_URLENCODED, part, &
flags);
2360 if (res == HTP_OK && prevlen > bstr_len(part)) {
2364 HtpState *s = htp_connp_get_user_data(tx->connp);
2367 HTPSetEvent(s, htud, STREAM_TOSERVER,
2374 static int HTPCallbackDoubleDecodeQuery(htp_tx_t *tx)
2376 if (tx->parsed_uri == NULL)
2379 return HTPCallbackDoubleDecodeUriPart(tx, tx->parsed_uri->query);
2382 static int HTPCallbackDoubleDecodePath(htp_tx_t *tx)
2384 if (tx->parsed_uri == NULL)
2387 return HTPCallbackDoubleDecodeUriPart(tx, tx->parsed_uri->path);
2390 static int HTPCallbackRequestHeaderData(htp_tx_data_t *tx_data)
2393 if (tx_data->len == 0 || tx_data->tx == NULL)
2397 if (tx_ud == NULL) {
2409 tx_data->data, tx_data->len);
2412 if (tx_data->tx && tx_data->tx->flags) {
2413 HtpState *hstate = htp_connp_get_user_data(tx_data->tx->connp);
2414 HTPErrorCheckTxRequestFlags(hstate, tx_data->tx);
2419 static int HTPCallbackResponseHeaderData(htp_tx_data_t *tx_data)
2422 if (tx_data->len == 0 || tx_data->tx == NULL)
2426 if (tx_ud == NULL) {
2438 tx_data->data, tx_data->len);
2447 static void HTPConfigSetDefaultsPhase1(
HTPCfgRec *cfg_prec)
2464 htp_config_register_request_header_data(cfg_prec->
cfg, HTPCallbackRequestHeaderData);
2465 htp_config_register_request_trailer_data(cfg_prec->
cfg, HTPCallbackRequestHeaderData);
2466 htp_config_register_response_header_data(cfg_prec->
cfg, HTPCallbackResponseHeaderData);
2467 htp_config_register_response_trailer_data(cfg_prec->
cfg, HTPCallbackResponseHeaderData);
2469 htp_config_register_request_trailer(cfg_prec->
cfg, HTPCallbackRequestHasTrailer);
2470 htp_config_register_response_trailer(cfg_prec->
cfg, HTPCallbackResponseHasTrailer);
2472 htp_config_register_request_body_data(cfg_prec->
cfg, HTPCallbackRequestBodyData);
2473 htp_config_register_response_body_data(cfg_prec->
cfg, HTPCallbackResponseBodyData);
2475 htp_config_register_request_start(cfg_prec->
cfg, HTPCallbackRequestStart);
2476 htp_config_register_request_complete(cfg_prec->
cfg, HTPCallbackRequestComplete);
2478 htp_config_register_response_start(cfg_prec->
cfg, HTPCallbackResponseStart);
2479 htp_config_register_response_complete(cfg_prec->
cfg, HTPCallbackResponseComplete);
2481 htp_config_set_parse_request_cookies(cfg_prec->
cfg, 0);
2484 htp_config_set_plusspace_decode(cfg_prec->
cfg, HTP_DECODER_URLENCODED, 0);
2486 htp_config_set_request_decompression(cfg_prec->
cfg, 1);
2487 #ifdef HAVE_HTP_CONFIG_SET_LZMA_LAYERS
2491 #ifdef HAVE_HTP_CONFIG_SET_LZMA_MEMLIMIT
2492 htp_config_set_lzma_memlimit(cfg_prec->
cfg,
2495 #ifdef HAVE_HTP_CONFIG_SET_COMPRESSION_BOMB_LIMIT
2496 htp_config_set_compression_bomb_limit(cfg_prec->
cfg,
2499 #ifdef HAVE_HTP_CONFIG_SET_COMPRESSION_TIME_LIMIT
2508 htp_config_set_field_limits(cfg_prec->
cfg,
2517 static int RandomGetWrap(
void)
2523 }
while(r >= ULONG_MAX - (ULONG_MAX % RAND_MAX));
2525 return r % RAND_MAX;
2534 static void HTPConfigSetDefaultsPhase2(
const char *name,
HTPCfgRec *cfg_prec)
2540 long int r = RandomGetWrap();
2542 ((
double)r / RAND_MAX - 0.5) * rdrange / 100);
2544 r = RandomGetWrap();
2546 ((
double)r / RAND_MAX - 0.5) * rdrange / 100);
2547 SCLogConfig(
"'%s' server has 'request-body-minimal-inspect-size' set to"
2548 " %u and 'request-body-inspect-window' set to %u after"
2552 r = RandomGetWrap();
2554 ((
double)r / RAND_MAX - 0.5) * rdrange / 100);
2556 r = RandomGetWrap();
2558 ((
double)r / RAND_MAX - 0.5) * rdrange / 100);
2560 SCLogConfig(
"'%s' server has 'response-body-minimal-inspect-size' set to"
2561 " %u and 'response-body-inspect-window' set to %u after"
2566 htp_config_register_request_line(cfg_prec->
cfg, HTPCallbackRequestLine);
2573 if (cfg_prec == NULL || s == NULL || tree == NULL)
2581 if (strcasecmp(
"address", p->
name) == 0) {
2589 if (strchr(pval->
val,
':') != NULL) {
2590 SCLogDebug(
"LIBHTP adding ipv6 server %s at %s: %p",
2594 "add ipv6 server %s, ignoring",
2598 SCLogDebug(
"LIBHTP adding ipv4 server %s at %s: %p",
2602 "to add ipv4 server %s, ignoring",
2608 }
else if (strcasecmp(
"personality", p->
name) == 0) {
2610 int personality = HTPLookupPersonality(p->
val);
2614 if (personality >= 0) {
2617 if (htp_config_set_server_personality(cfg_prec->
cfg, personality) == HTP_ERROR){
2619 "personality \"%s\", ignoring",
2623 HTPLookupPersonalityString(personality));
2629 htp_config_set_convert_lowercase(cfg_prec->
cfg, HTP_DECODER_URL_PATH, 0);
2637 }
else if (strcasecmp(
"request-body-limit", p->
name) == 0 ||
2638 strcasecmp(
"request_body_limit", p->
name) == 0) {
2640 SCLogError(
"Error parsing request-body-limit "
2641 "from conf file - %s. Killing engine",
2646 }
else if (strcasecmp(
"response-body-limit", p->
name) == 0) {
2648 SCLogError(
"Error parsing response-body-limit "
2649 "from conf file - %s. Killing engine",
2654 }
else if (strcasecmp(
"request-body-minimal-inspect-size", p->
name) == 0) {
2656 SCLogError(
"Error parsing request-body-minimal-inspect-size "
2657 "from conf file - %s. Killing engine",
2662 }
else if (strcasecmp(
"request-body-inspect-window", p->
name) == 0) {
2664 SCLogError(
"Error parsing request-body-inspect-window "
2665 "from conf file - %s. Killing engine",
2670 }
else if (strcasecmp(
"double-decode-query", p->
name) == 0) {
2672 htp_config_register_request_line(cfg_prec->
cfg,
2673 HTPCallbackDoubleDecodeQuery);
2676 }
else if (strcasecmp(
"double-decode-path", p->
name) == 0) {
2678 htp_config_register_request_line(cfg_prec->
cfg,
2679 HTPCallbackDoubleDecodePath);
2682 }
else if (strcasecmp(
"response-body-minimal-inspect-size", p->
name) == 0) {
2684 SCLogError(
"Error parsing response-body-minimal-inspect-size "
2685 "from conf file - %s. Killing engine",
2690 }
else if (strcasecmp(
"response-body-inspect-window", p->
name) == 0) {
2692 SCLogError(
"Error parsing response-body-inspect-window "
2693 "from conf file - %s. Killing engine",
2698 }
else if (strcasecmp(
"response-body-decompress-layer-limit", p->
name) == 0) {
2701 SCLogError(
"Error parsing response-body-inspect-window "
2702 "from conf file - %s. Killing engine",
2706 #ifdef HAVE_HTP_CONFIG_SET_RESPONSE_DECOMPRESSION_LAYER_LIMIT
2707 htp_config_set_response_decompression_layer_limit(cfg_prec->
cfg, value);
2709 SCLogWarning(
"can't set response-body-decompress-layer-limit "
2710 "to %u, libhtp version too old",
2713 }
else if (strcasecmp(
"path-convert-backslash-separators", p->
name) == 0) {
2714 htp_config_set_backslash_convert_slashes(cfg_prec->
cfg,
2715 HTP_DECODER_URL_PATH,
2717 }
else if (strcasecmp(
"path-bestfit-replacement-char", p->
name) == 0) {
2718 if (strlen(p->
val) == 1) {
2719 htp_config_set_bestfit_replacement_byte(cfg_prec->
cfg,
2720 HTP_DECODER_URL_PATH,
2724 "for libhtp param path-bestfit-replacement-char");
2726 }
else if (strcasecmp(
"path-convert-lowercase", p->
name) == 0) {
2727 htp_config_set_convert_lowercase(cfg_prec->
cfg,
2728 HTP_DECODER_URL_PATH,
2730 }
else if (strcasecmp(
"path-nul-encoded-terminates", p->
name) == 0) {
2731 htp_config_set_nul_encoded_terminates(cfg_prec->
cfg,
2732 HTP_DECODER_URL_PATH,
2734 }
else if (strcasecmp(
"path-nul-raw-terminates", p->
name) == 0) {
2735 htp_config_set_nul_raw_terminates(cfg_prec->
cfg,
2736 HTP_DECODER_URL_PATH,
2738 }
else if (strcasecmp(
"path-separators-compress", p->
name) == 0) {
2739 htp_config_set_path_separators_compress(cfg_prec->
cfg,
2740 HTP_DECODER_URL_PATH,
2742 }
else if (strcasecmp(
"path-separators-decode", p->
name) == 0) {
2743 htp_config_set_path_separators_decode(cfg_prec->
cfg,
2744 HTP_DECODER_URL_PATH,
2746 }
else if (strcasecmp(
"path-u-encoding-decode", p->
name) == 0) {
2747 htp_config_set_u_encoding_decode(cfg_prec->
cfg,
2748 HTP_DECODER_URL_PATH,
2750 }
else if (strcasecmp(
"path-url-encoding-invalid-handling", p->
name) == 0) {
2751 enum htp_url_encoding_handling_t handling;
2752 if (strcasecmp(p->
val,
"preserve_percent") == 0) {
2753 handling = HTP_URL_DECODE_PRESERVE_PERCENT;
2754 }
else if (strcasecmp(p->
val,
"remove_percent") == 0) {
2755 handling = HTP_URL_DECODE_REMOVE_PERCENT;
2756 }
else if (strcasecmp(p->
val,
"decode_invalid") == 0) {
2757 handling = HTP_URL_DECODE_PROCESS_INVALID;
2760 "for libhtp param path-url-encoding-invalid-handling");
2763 htp_config_set_url_encoding_invalid_handling(cfg_prec->
cfg,
2764 HTP_DECODER_URL_PATH,
2766 }
else if (strcasecmp(
"path-utf8-convert-bestfit", p->
name) == 0) {
2767 htp_config_set_utf8_convert_bestfit(cfg_prec->
cfg,
2768 HTP_DECODER_URL_PATH,
2770 }
else if (strcasecmp(
"uri-include-all", p->
name) == 0) {
2774 }
else if (strcasecmp(
"query-plusspace-decode", p->
name) == 0) {
2775 htp_config_set_plusspace_decode(cfg_prec->
cfg,
2776 HTP_DECODER_URLENCODED,
2778 }
else if (strcasecmp(
"meta-field-limit", p->
name) == 0) {
2782 "from conf file - %s. Killing engine",
2788 "from conf file cannot be 0. Killing engine");
2791 htp_config_set_field_limits(cfg_prec->
cfg,
2794 #ifdef HAVE_HTP_CONFIG_SET_LZMA_MEMLIMIT
2795 }
else if (strcasecmp(
"lzma-memlimit", p->
name) == 0) {
2798 FatalError(
"failed to parse 'lzma-memlimit' "
2799 "from conf file - %s.",
2804 "from conf file cannot be 0.");
2807 SCLogConfig(
"Setting HTTP LZMA memory limit to %"PRIu32
" bytes", limit);
2808 htp_config_set_lzma_memlimit(cfg_prec->
cfg, (
size_t)limit);
2810 #ifdef HAVE_HTP_CONFIG_SET_LZMA_LAYERS
2811 }
else if (strcasecmp(
"lzma-enabled", p->
name) == 0) {
2813 htp_config_set_lzma_layers(cfg_prec->
cfg, 1);
2818 "from conf file - %s.",
2821 SCLogConfig(
"Setting HTTP LZMA decompression layers to %" PRIu32
"", (
int)limit);
2822 htp_config_set_lzma_layers(cfg_prec->
cfg, limit);
2825 #ifdef HAVE_HTP_CONFIG_SET_COMPRESSION_BOMB_LIMIT
2826 }
else if (strcasecmp(
"compression-bomb-limit", p->
name) == 0) {
2829 FatalError(
"failed to parse 'compression-bomb-limit' "
2830 "from conf file - %s.",
2835 "from conf file cannot be 0.");
2838 SCLogConfig(
"Setting HTTP compression bomb limit to %"PRIu32
" bytes", limit);
2839 htp_config_set_compression_bomb_limit(cfg_prec->
cfg, (
size_t)limit);
2841 #ifdef HAVE_HTP_CONFIG_SET_COMPRESSION_TIME_LIMIT
2842 }
else if (strcasecmp(
"decompression-time-limit", p->
name) == 0) {
2846 FatalError(
"failed to parse 'decompression-time-limit' "
2847 "from conf file - %s.",
2850 SCLogConfig(
"Setting HTTP decompression time limit to %" PRIu32
" usec", limit);
2851 htp_config_set_compression_time_limit(cfg_prec->
cfg, (
size_t)limit);
2853 }
else if (strcasecmp(
"randomize-inspection-sizes", p->
name) == 0) {
2857 }
else if (strcasecmp(
"randomize-inspection-range", p->
name) == 0) {
2860 (
const char *)p->
val, 0, 100) < 0) {
2862 "-inspection-range setting from conf file - \"%s\"."
2863 " It should be a valid integer less than or equal to 100."
2869 }
else if (strcasecmp(
"http-body-inline", p->
name) == 0) {
2875 if (strcmp(
"auto", p->
val) != 0) {
2884 }
else if (strcasecmp(
"swf-decompression", p->
name) == 0) {
2888 if (strcasecmp(
"enabled", pval->
name) == 0) {
2896 }
else if (strcasecmp(
"type", pval->
name) == 0) {
2897 if (strcasecmp(
"no", pval->
val) == 0) {
2899 }
else if (strcasecmp(
"deflate", pval->
val) == 0) {
2901 }
else if (strcasecmp(
"lzma", pval->
val) == 0) {
2903 }
else if (strcasecmp(
"both", pval->
val) == 0) {
2907 "swf-decompression.type: %s - "
2912 }
else if (strcasecmp(
"compress-depth", pval->
name) == 0) {
2914 SCLogError(
"Error parsing swf-decompression.compression-depth "
2915 "from conf file - %s. Killing engine",
2919 }
else if (strcasecmp(
"decompress-depth", pval->
name) == 0) {
2921 SCLogError(
"Error parsing swf-decompression.decompression-depth "
2922 "from conf file - %s. Killing engine",
2932 "default config: %s",
2944 cfglist.
next = NULL;
2951 if (NULL == cfgtree)
2955 cfglist.
cfg = htp_config_create();
2956 if (NULL == cfglist.
cfg) {
2957 FatalError(
"Failed to create HTP default config");
2960 HTPConfigSetDefaultsPhase1(&cfglist);
2961 if (
ConfGetNode(
"app-layer.protocols.http.libhtp") == NULL) {
2962 HTPConfigParseParameters(&cfglist,
ConfGetNode(
"libhtp.default-config"),
2965 HTPConfigParseParameters(&cfglist,
ConfGetNode(
"app-layer.protocols.http.libhtp.default-config"), cfgtree);
2967 HTPConfigSetDefaultsPhase2(
"default", &cfglist);
2973 if (server_config == NULL) {
2974 server_config =
ConfGetNode(
"libhtp.server-config");
2975 if (server_config == NULL) {
2976 SCLogDebug(
"LIBHTP Configuring %p", server_config);
2980 SCLogDebug(
"LIBHTP Configuring %p", server_config);
2998 memset(htprec, 0x00,
sizeof(*htprec));
3000 cfglist.
next = htprec;
3003 cfglist.
next->
cfg = htp_config_create();
3004 if (NULL == cfglist.
next->
cfg) {
3005 FatalError(
"Failed to create HTP server config");
3008 HTPConfigSetDefaultsPhase1(htprec);
3009 HTPConfigParseParameters(htprec, s, cfgtree);
3010 HTPConfigSetDefaultsPhase2(s->
name, htprec);
3020 SCLogPerf(
"htp memory %"PRIu64
" (%"PRIu64
")", htp_state_memuse, htp_state_memcnt);
3031 static AppLayerGetFileState HTPGetTxFiles(
void *state,
void *txv, uint8_t direction)
3033 AppLayerGetFileState files = { .fc = NULL, .cfg = &
htp_sbcfg };
3034 htp_tx_t *tx = (htp_tx_t *)txv;
3037 if (direction & STREAM_TOCLIENT) {
3046 static int HTPStateGetAlstateProgress(
void *tx, uint8_t direction)
3048 if (direction & STREAM_TOSERVER)
3049 return ((htp_tx_t *)tx)->request_progress;
3051 return ((htp_tx_t *)tx)->response_progress;
3054 static uint64_t HTPStateGetTxCnt(
void *alstate)
3058 if (http_state != NULL && http_state->
conn != NULL) {
3059 const int64_t size = (int64_t)htp_list_size(http_state->
conn->transactions);
3063 return (uint64_t)size;
3069 static void *HTPStateGetTx(
void *alstate, uint64_t tx_id)
3073 if (http_state != NULL && http_state->
conn != NULL)
3074 return htp_list_get(http_state->
conn->transactions, tx_id);
3083 if (http_state != NULL && http_state->
conn != NULL) {
3084 size_t txid = htp_list_array_size(http_state->
conn->transactions);
3086 return htp_list_get(http_state->
conn->transactions, txid - 1);
3092 static int HTPStateGetEventInfo(
const char *event_name,
3096 if (*event_id == -1) {
3098 "http's enum map table.",
3109 static int HTPStateGetEventInfoById(
int event_id,
const char **event_name,
3113 if (*event_name == NULL) {
3115 "http's enum map table.",
3128 htp_tx_t *tx = (htp_tx_t *)vtx;
3136 static AppLayerStateData *HTPGetStateData(
void *vstate)
3142 static int HTPRegisterPatternsForProtocolDetection(
void)
3144 const char *methods[] = {
"GET",
"PUT",
"POST",
"HEAD",
"TRACE",
"OPTIONS",
3145 "CONNECT",
"DELETE",
"PATCH",
"PROPFIND",
"PROPPATCH",
"MKCOL",
3146 "COPY",
"MOVE",
"LOCK",
"UNLOCK",
"CHECKOUT",
"UNCHECKOUT",
"CHECKIN",
3147 "UPDATE",
"LABEL",
"REPORT",
"MKWORKSPACE",
"MKACTIVITY",
"MERGE",
3148 "INVALID",
"VERSION-CONTROL",
"BASELINE-CONTROL", NULL};
3149 const char *spacings[] = {
"|20|",
"|09|", NULL };
3150 const char *versions[] = {
"HTTP/0.9",
"HTTP/1.0",
"HTTP/1.1", NULL };
3155 int register_result;
3156 char method_buffer[32] =
"";
3159 for (methods_pos = 0; methods[methods_pos]; methods_pos++) {
3160 for (spacings_pos = 0; spacings[spacings_pos]; spacings_pos++) {
3163 snprintf(method_buffer,
sizeof(method_buffer),
"%s%s", methods[methods_pos], spacings[spacings_pos]);
3170 method_buffer, (uint16_t)strlen(method_buffer) - 3, 0, STREAM_TOSERVER);
3171 if (register_result < 0) {
3178 for (versions_pos = 0; versions[versions_pos]; versions_pos++) {
3180 versions[versions_pos], (uint16_t)strlen(versions[versions_pos]), 0,
3182 if (register_result < 0) {
3198 const char *proto_name =
"http";
3203 if (HTPRegisterPatternsForProtocolDetection() < 0)
3206 SCLogInfo(
"Protocol detection and parser disabled for %s protocol",
3221 ALPROTO_HTTP1, HTP_REQUEST_COMPLETE, HTP_RESPONSE_COMPLETE);
3233 IPPROTO_TCP,
ALPROTO_HTTP1, STREAM_TOSERVER, HTPHandleRequestData);
3235 IPPROTO_TCP,
ALPROTO_HTTP1, STREAM_TOCLIENT, HTPHandleResponseData);
3241 IPPROTO_TCP,
ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_TOCLIENT);
3244 IPPROTO_TCP,
ALPROTO_HTTP1, HTTPGetFrameIdByName, HTTPGetFrameNameById);
3248 SCLogInfo(
"Parsed disabled for %s protocol. Protocol detection"
3249 "still on.", proto_name);
3265 cfglist_backup = cfglist;
3272 cfglist = cfglist_backup;
3279 static int HTPParserTest01(
void)
3281 uint8_t httpbuf1[] =
"POST / HTTP/1.0\r\nUser-Agent: Victor/1.0\r\n\r\nPost"
3283 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3286 memset(&ssn, 0,
sizeof(ssn));
3294 f->
proto = IPPROTO_TCP;
3300 for (u = 0; u < httplen1; u++) {
3304 flags = STREAM_TOSERVER|STREAM_START;
3305 else if (u == (httplen1 - 1))
3306 flags = STREAM_TOSERVER|STREAM_EOF;
3308 flags = STREAM_TOSERVER;
3317 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3320 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3323 FAIL_IF(strcmp(bstr_util_strdup_to_c(h->value),
"Victor/1.0"));
3324 FAIL_IF(tx->request_method_number != HTP_M_POST);
3325 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_0);
3334 static int HTPParserTest01b(
void)
3336 uint8_t httpbuf1[] =
"POST / HTTP/1.0\r\nUser-Agent:\r\n Victor/1.0\r\n\r\nPost"
3338 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3341 memset(&ssn, 0,
sizeof(ssn));
3349 f->
proto = IPPROTO_TCP;
3354 uint8_t
flags =STREAM_TOSERVER|STREAM_START|STREAM_EOF;
3361 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3364 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3367 FAIL_IF(strcmp(bstr_util_strdup_to_c(h->value),
"Victor/1.0"));
3368 FAIL_IF(tx->request_method_number != HTP_M_POST);
3369 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_0);
3378 static int HTPParserTest01c(
void)
3380 uint8_t httpbuf1[] =
"POST / HTTP/1.0\r\nUser-Agent:\r\n Victor/1.0\r\n\r\nPost"
3382 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3385 memset(&ssn, 0,
sizeof(ssn));
3393 f->
proto = IPPROTO_TCP;
3399 for (u = 0; u < httplen1; u++) {
3403 flags = STREAM_TOSERVER|STREAM_START;
3404 else if (u == (httplen1 - 1))
3405 flags = STREAM_TOSERVER|STREAM_EOF;
3407 flags = STREAM_TOSERVER;
3416 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3419 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3422 FAIL_IF(strcmp(bstr_util_strdup_to_c(h->value),
"Victor/1.0"));
3423 FAIL_IF(tx->request_method_number != HTP_M_POST);
3424 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_0);
3434 static int HTPParserTest01a(
void)
3438 uint8_t httpbuf1[] =
" POST / HTTP/1.0\r\nUser-Agent: Victor/1.0\r\n\r\nPost"
3440 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3446 memset(&ssn, 0,
sizeof(ssn));
3448 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
3452 f->
proto = IPPROTO_TCP;
3458 for (u = 0; u < httplen1; u++) {
3462 flags = STREAM_TOSERVER|STREAM_START;
3463 else if (u == (httplen1 - 1))
3464 flags = STREAM_TOSERVER|STREAM_EOF;
3466 flags = STREAM_TOSERVER;
3470 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
3477 if (htp_state == NULL) {
3478 printf(
"no http state: ");
3482 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3483 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3484 if (strcmp(bstr_util_strdup_to_c(h->value),
"Victor/1.0")
3485 || tx->request_method_number != HTP_M_POST ||
3486 tx->request_protocol_number != HTP_PROTOCOL_1_0)
3488 printf(
"expected header value: Victor/1.0 and got %s: and expected"
3489 " method: POST and got %s, expected protocol number HTTP/1.0"
3490 " and got: %s \n", bstr_util_strdup_to_c(h->value),
3491 bstr_util_strdup_to_c(tx->request_method),
3492 bstr_util_strdup_to_c(tx->request_protocol));
3505 static int HTPParserTest02(
void)
3509 uint8_t httpbuf1[] =
"POST";
3510 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3515 memset(&ssn, 0,
sizeof(ssn));
3517 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
3521 f->
proto = IPPROTO_TCP;
3527 STREAM_TOSERVER | STREAM_START | STREAM_EOF, httpbuf1, httplen1);
3529 printf(
"toserver chunk 1 returned %" PRId32
", expected 0: ", r);
3534 if (http_state == NULL) {
3535 printf(
"no http state: ");
3539 htp_tx_t *tx = HTPStateGetTx(http_state, 0);
3541 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3545 char *method = bstr_util_strdup_to_c(tx->request_method);
3548 FAIL_IF(strcmp(method,
"POST") != 0);
3562 static int HTPParserTest03(
void)
3566 uint8_t httpbuf1[] =
"HELLO / HTTP/1.0\r\n";
3567 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3573 memset(&ssn, 0,
sizeof(ssn));
3575 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
3579 f->
proto = IPPROTO_TCP;
3585 for (u = 0; u < httplen1; u++) {
3588 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
3589 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
3590 else flags = STREAM_TOSERVER;
3594 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
3600 if (htp_state == NULL) {
3601 printf(
"no http state: ");
3605 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3607 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3608 if (tx->request_method_number != HTP_M_UNKNOWN ||
3609 h != NULL || tx->request_protocol_number != HTP_PROTOCOL_1_0)
3611 printf(
"expected method M_UNKNOWN and got %s: , expected protocol "
3612 "HTTP/1.0 and got %s \n", bstr_util_strdup_to_c(tx->request_method),
3613 bstr_util_strdup_to_c(tx->request_protocol));
3627 static int HTPParserTest04(
void)
3632 uint8_t httpbuf1[] =
"World!\r\n";
3633 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3638 memset(&ssn, 0,
sizeof(ssn));
3640 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
3644 f->
proto = IPPROTO_TCP;
3650 STREAM_TOSERVER | STREAM_START | STREAM_EOF, httpbuf1, httplen1);
3656 if (htp_state == NULL) {
3657 printf(
"no http state: ");
3661 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3662 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3663 if (tx->request_method_number != HTP_M_UNKNOWN ||
3664 h != NULL || tx->request_protocol_number != HTP_PROTOCOL_0_9)
3666 printf(
"expected method M_UNKNOWN and got %s: , expected protocol "
3667 "NULL and got %s \n", bstr_util_strdup_to_c(tx->request_method),
3668 bstr_util_strdup_to_c(tx->request_protocol));
3682 static int HTPParserTest05(
void)
3684 uint8_t httpbuf1[] =
"POST / HTTP/1.0\r\nUser-Agent: Victor/1.0\r\nContent-Length: 17\r\n\r\n";
3685 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3686 uint8_t httpbuf2[] =
"Post D";
3687 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
3688 uint8_t httpbuf3[] =
"ata is c0oL!";
3689 uint32_t httplen3 =
sizeof(httpbuf3) - 1;
3691 uint8_t httpbuf4[] =
"HTTP/1.0 200 OK\r\nServer: VictorServer/1.0\r\n\r\n";
3692 uint32_t httplen4 =
sizeof(httpbuf4) - 1;
3693 uint8_t httpbuf5[] =
"post R";
3694 uint32_t httplen5 =
sizeof(httpbuf5) - 1;
3695 uint8_t httpbuf6[] =
"esults are tha bomb!";
3696 uint32_t httplen6 =
sizeof(httpbuf6) - 1;
3699 memset(&ssn, 0,
sizeof(ssn));
3707 f->
proto = IPPROTO_TCP;
3737 htp_tx_t *tx = HTPStateGetTx(http_state, 0);
3739 FAIL_IF_NOT(tx->request_method_number == HTP_M_POST);
3740 FAIL_IF_NOT(tx->request_protocol_number == HTP_PROTOCOL_1_0);
3742 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3755 static int HTPParserTest06(
void)
3757 uint8_t httpbuf1[] =
"GET /ld/index.php?id=412784631&cid=0064&version=4&"
3758 "name=try HTTP/1.1\r\nAccept: */*\r\nUser-Agent: "
3759 "LD-agent\r\nHost: 209.205.196.16\r\n\r\n";
3760 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3761 uint8_t httpbuf2[] =
"HTTP/1.1 200 OK\r\nDate: Sat, 03 Oct 2009 10:16:02 "
3763 "Server: Apache/1.3.37 (Unix) mod_ssl/2.8.28 "
3764 "OpenSSL/0.9.7a PHP/4.4.7 mod_perl/1.29 "
3765 "FrontPage/5.0.2.2510\r\n"
3766 "X-Powered-By: PHP/4.4.7\r\nTransfer-Encoding: "
3768 "Content-Type: text/html\r\n\r\n"
3770 "W2dyb3VwMV0NCnBob25lMT1wMDB3ODgyMTMxMzAyMTINCmxvZ2lu"
3771 "MT0NCnBhc3N3b3JkMT0NCnBob25lMj1wMDB3ODgyMTMxMzAyMTIN"
3772 "CmxvZ2luMj0NCnBhc3N3b3JkMj0NCnBob25lMz0NCmxvZ2luMz0N"
3773 "CnBhc3N3b3JkMz0NCnBob25lND0NCmxvZ2luND0NCnBhc3N3b3Jk"
3774 "ND0NCnBob25lNT0NCmxvZ2luNT0NCnBhc3N3b3JkNT0NCnBob25l"
3775 "Nj0NCmxvZ2luNj0NCnBhc3N3b3JkNj0NCmNhbGxfdGltZTE9MzIN"
3776 "CmNhbGxfdGltZTI9MjMyDQpkYXlfbGltaXQ9NQ0KbW9udGhfbGlt"
3777 "aXQ9MTUNCltncm91cDJdDQpwaG9uZTE9DQpsb2dpbjE9DQpwYXNz"
3778 "d29yZDE9DQpwaG9uZTI9DQpsb2dpbjI9DQpwYXNzd29yZDI9DQpw"
3779 "aG9uZTM9DQpsb2dpbjM9DQpwYXNzd29yZDM9DQpwaG9uZTQ9DQps"
3780 "b2dpbjQ9DQpwYXNzd29yZDQ9DQpwaG9uZTU9DQpsb2dpbjU9DQpw"
3781 "YXNzd29yZDU9DQpwaG9uZTY9DQpsb2dpbjY9DQpwYXNzd29yZDY9"
3782 "DQpjYWxsX3RpbWUxPQ0KY2FsbF90aW1lMj0NCmRheV9saW1pdD0N"
3783 "Cm1vbnRoX2xpbWl0PQ0KW2dyb3VwM10NCnBob25lMT0NCmxvZ2lu"
3784 "MT0NCnBhc3N3b3JkMT0NCnBob25lMj0NCmxvZ2luMj0NCnBhc3N3"
3785 "b3JkMj0NCnBob25lMz0NCmxvZ2luMz0NCnBhc3N3b3JkMz0NCnBo"
3786 "b25lND0NCmxvZ2luND0NCnBhc3N3b3JkND0NCnBob25lNT0NCmxv"
3787 "Z2luNT0NCnBhc3N3b3JkNT0NCnBob25lNj0NCmxvZ2luNj0NCnBh"
3788 "c3N3b3JkNj0NCmNhbGxfdGltZTE9DQpjYWxsX3RpbWUyPQ0KZGF5"
3789 "X2xpbWl0PQ0KbW9udGhfbGltaXQ9DQpbZ3JvdXA0XQ0KcGhvbmUx"
3790 "PQ0KbG9naW4xPQ0KcGFzc3dvcmQxPQ0KcGhvbmUyPQ0KbG9naW4y"
3791 "PQ0KcGFzc3dvcmQyPQ0KcGhvbmUzPQ0KbG9naW4zPQ0KcGFzc3dv"
3792 "cmQzPQ0KcGhvbmU0PQ0KbG9naW40PQ0KcGFzc3dvcmQ0PQ0KcGhv"
3793 "bmU1PQ0KbG9naW41PQ0KcGFzc3dvcmQ1PQ0KcGhvbmU2PQ0KbG9n"
3794 "aW42PQ0KcGFzc3dvcmQ2PQ0KY2FsbF90aW1lMT0NCmNhbGxfdGlt"
3795 "ZTI9DQpkYXlfbGltaXQ9DQptb250aF9saW1pdD0NCltmaWxlc10N"
3796 "Cmxpbms9aHR0cDovLzIwOS4yMDUuMTk2LjE2L2xkL2dldGJvdC5w"
3797 "aHA=\r\n0\r\n\r\n";
3798 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
3804 memset(&ssn, 0,
sizeof(ssn));
3809 f->
proto = IPPROTO_TCP;
3824 htp_tx_t *tx = HTPStateGetTx(http_state, 0);
3827 FAIL_IF(tx->request_method_number != HTP_M_GET);
3828 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_1);
3830 FAIL_IF(tx->response_status_number != 200);
3831 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_1);
3833 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3844 static int HTPParserTest07(
void)
3848 uint8_t httpbuf1[] =
"GET /awstats.pl?/migratemigrate%20=%20| HTTP/1.0\r\n\r\n";
3849 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3855 memset(&ssn, 0,
sizeof(ssn));
3857 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
3861 f->
proto = IPPROTO_TCP;
3867 for (u = 0; u < httplen1; u++) {
3871 flags = STREAM_TOSERVER|STREAM_START;
3872 else if (u == (httplen1 - 1))
3873 flags = STREAM_TOSERVER|STREAM_EOF;
3875 flags = STREAM_TOSERVER;
3879 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
3886 if (htp_state == NULL) {
3887 printf(
"no http state: ");
3891 uint8_t ref[] =
"/awstats.pl?/migratemigrate = |";
3892 size_t reflen =
sizeof(ref) - 1;
3894 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3900 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
3909 printf(
"normalized uri \"");
3931 static int HTPParserTest08(
void)
3935 uint8_t httpbuf1[] =
"GET /secondhouse/image/js/\%ce\%de\%ce\%fd_RentCity.js?v=2011.05.02 HTTP/1.0\r\n\r\n";
3936 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3958 memset(&ssn, 0,
sizeof(ssn));
3960 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
3964 f->
proto = IPPROTO_TCP;
3970 flags = STREAM_TOSERVER|STREAM_START|STREAM_EOF;
3974 printf(
"toserver chunk returned %" PRId32
", expected"
3981 if (htp_state == NULL) {
3982 printf(
"no http state: ");
3987 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4012 static int HTPParserTest09(
void)
4016 uint8_t httpbuf1[] =
"GET /secondhouse/image/js/\%ce\%de\%ce\%fd_RentCity.js?v=2011.05.02 HTTP/1.0\r\n\r\n";
4017 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4027 personality: Apache_2_2\n\
4040 memset(&ssn, 0,
sizeof(ssn));
4042 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
4046 f->
proto = IPPROTO_TCP;
4052 flags = STREAM_TOSERVER|STREAM_START|STREAM_EOF;
4056 printf(
"toserver chunk returned %" PRId32
", expected"
4062 if (htp_state == NULL) {
4063 printf(
"no http state: ");
4067 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4092 static int HTPParserTest10(
void)
4096 uint8_t httpbuf1[] =
"GET / HTTP/1.0\r\nHost:www.google.com\r\n\r\n";
4097 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4103 memset(&ssn, 0,
sizeof(ssn));
4105 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
4109 f->
proto = IPPROTO_TCP;
4115 for (u = 0; u < httplen1; u++) {
4119 flags = STREAM_TOSERVER|STREAM_START;
4120 else if (u == (httplen1 - 1))
4121 flags = STREAM_TOSERVER|STREAM_EOF;
4123 flags = STREAM_TOSERVER;
4127 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
4134 if (htp_state == NULL) {
4135 printf(
"no http state: ");
4139 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4140 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
4145 char *name = bstr_util_strdup_to_c(h->name);
4150 if (strcmp(name,
"Host") != 0) {
4151 printf(
"header name not \"Host\", instead \"%s\": ", name);
4157 char *value = bstr_util_strdup_to_c(h->value);
4158 if (value == NULL) {
4162 if (strcmp(value,
"www.google.com") != 0) {
4163 printf(
"header value not \"www.google.com\", instead \"%s\": ", value);
4180 static int HTPParserTest11(
void)
4184 uint8_t httpbuf1[] =
"GET /%2500 HTTP/1.0\r\n\r\n";
4185 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4191 memset(&ssn, 0,
sizeof(ssn));
4193 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
4197 f->
proto = IPPROTO_TCP;
4203 for (u = 0; u < httplen1; u++) {
4207 flags = STREAM_TOSERVER|STREAM_START;
4208 else if (u == (httplen1 - 1))
4209 flags = STREAM_TOSERVER|STREAM_EOF;
4211 flags = STREAM_TOSERVER;
4215 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
4222 if (htp_state == NULL) {
4223 printf(
"no http state: ");
4227 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4233 printf(
"normalized uri len should be 2, is %"PRIuMAX,
4243 printf(
"normalized uri \"");
4261 static int HTPParserTest12(
void)
4265 uint8_t httpbuf1[] =
"GET /?a=%2500 HTTP/1.0\r\n\r\n";
4266 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4272 memset(&ssn, 0,
sizeof(ssn));
4274 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
4278 f->
proto = IPPROTO_TCP;
4284 for (u = 0; u < httplen1; u++) {
4288 flags = STREAM_TOSERVER|STREAM_START;
4289 else if (u == (httplen1 - 1))
4290 flags = STREAM_TOSERVER|STREAM_EOF;
4292 flags = STREAM_TOSERVER;
4296 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
4303 if (htp_state == NULL) {
4304 printf(
"no http state: ");
4308 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4314 printf(
"normalized uri len should be 5, is %"PRIuMAX,
4327 printf(
"normalized uri \"");
4345 static int HTPParserTest13(
void)
4349 uint8_t httpbuf1[] =
"GET / HTTP/1.0\r\nHost:www.google.com\rName: Value\r\n\r\n";
4350 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4356 memset(&ssn, 0,
sizeof(ssn));
4358 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
4362 f->
proto = IPPROTO_TCP;
4368 for (u = 0; u < httplen1; u++) {
4372 flags = STREAM_TOSERVER|STREAM_START;
4373 else if (u == (httplen1 - 1))
4374 flags = STREAM_TOSERVER|STREAM_EOF;
4376 flags = STREAM_TOSERVER;
4380 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
4387 if (htp_state == NULL) {
4388 printf(
"no http state: ");
4392 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4393 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
4398 char *name = bstr_util_strdup_to_c(h->name);
4403 if (strcmp(name,
"Host") != 0) {
4404 printf(
"header name not \"Host\", instead \"%s\": ", name);
4410 char *value = bstr_util_strdup_to_c(h->value);
4411 if (value == NULL) {
4415 if (strcmp(value,
"www.google.com\rName: Value") != 0) {
4416 printf(
"header value not \"www.google.com\", instead \"");
4434 static int HTPParserConfigTest01(
void)
4448 address: [192.168.1.0/24, 127.0.0.0/8, \"::1\"]\n\
4449 personality: Tomcat_6_0\n\
4454 - 192.168.10.0/24\n\
4455 personality: IIS_7_0\n\
4464 outputs =
ConfGetNode(
"libhtp.default-config.personality");
4465 if (outputs == NULL) {
4470 if (outputs == NULL) {
4478 if (strcmp(node->
name,
"0") != 0) {
4485 if (strcmp(node->
name,
"apache-tomcat") != 0) {
4493 if (node2 == NULL) {
4496 if (strcmp(node2->
val,
"Tomcat_6_0") != 0) {
4511 if (strcmp(n->
name,
"0") != 0) {
4514 if (strcmp(n->
val,
"192.168.1.0/24") != 0) {
4519 if (strcmp(n->
name,
"1") != 0) {
4522 if (strcmp(n->
val,
"127.0.0.0/8") != 0) {
4527 if (strcmp(n->
name,
"2") != 0) {
4530 if (strcmp(n->
val,
"::1") != 0) {
4541 if (outputs == NULL) {
4550 if (strcmp(node->
name,
"1") != 0) {
4557 if (strcmp(node->
name,
"iis7") != 0) {
4562 if (node2 == NULL) {
4565 if (strcmp(node2->
val,
"IIS_7_0") != 0) {
4582 if (strcmp(n->
name,
"0") != 0) {
4585 if (strcmp(n->
val,
"192.168.0.0/24") != 0) {
4590 if (strcmp(n->
name,
"1") != 0) {
4593 if (strcmp(n->
val,
"192.168.10.0/24") != 0) {
4613 static int HTPParserConfigTest02(
void)
4627 address: [192.168.1.0/24, 127.0.0.0/8, \"::1\"]\n\
4628 personality: Tomcat_6_0\n\
4633 - 192.168.10.0/24\n\
4634 personality: IIS_7_0\n\
4645 if (cfglist.
cfg == NULL) {
4646 printf(
"No default config created.\n");
4650 if (cfgtree == NULL) {
4651 printf(
"No config tree created.\n");
4655 htp_cfg_t *htp = cfglist.
cfg;
4658 void *user_data = NULL;
4660 addr =
"192.168.10.42";
4661 if (inet_pton(AF_INET, addr, buf) == 1) {
4663 if (user_data != NULL) {
4665 htp = htp_cfg_rec->
cfg;
4669 printf(
"Could not get config for: %s\n", addr);
4674 printf(
"Failed to parse address: %s\n", addr);
4680 if (inet_pton(AF_INET6, addr, buf) == 1) {
4682 if (user_data != NULL) {
4684 htp = htp_cfg_rec->
cfg;
4688 printf(
"Could not get config for: %s\n", addr);
4693 printf(
"Failed to parse address: %s\n", addr);
4709 static int HTPParserConfigTest03(
void)
4713 uint8_t httpbuf1[] =
"POST / HTTP/1.0\r\nUser-Agent: Victor/1.0\r\n\r\nPost"
4715 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4732 address: [192.168.1.0/24, 127.0.0.0/8, \"::1\"]\n\
4733 personality: Tomcat_6_0\n\
4738 - 192.168.10.0/24\n\
4739 personality: IIS_7_0\n\
4750 const char *addr =
"192.168.10.42";
4752 memset(&ssn, 0,
sizeof(ssn));
4758 f->
proto = IPPROTO_TCP;
4761 htp_cfg_t *htp = cfglist.
cfg;
4763 void *user_data = NULL;
4765 if (user_data != NULL) {
4767 htp = htp_cfg_rec->
cfg;
4771 printf(
"Could not get config for: %s\n", addr);
4778 for (u = 0; u < httplen1; u++) {
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;
4787 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
4795 if (htp_state == NULL) {
4796 printf(
"no http state: ");
4801 if (HTPStateGetTxCnt(htp_state) != 2) {
4802 printf(
"HTPStateGetTxCnt(htp_state) failure\n");
4806 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4809 if (tx->cfg != htp) {
4810 printf(
"wrong HTP config (%p instead of %p - default=%p): ",
4811 tx->cfg, htp, cfglist.
cfg);
4814 tx = HTPStateGetTx(htp_state, 1);
4817 if (tx->cfg != htp) {
4818 printf(
"wrong HTP config (%p instead of %p - default=%p): ",
4819 tx->cfg, htp, cfglist.
cfg);
4838 static int HTPParserConfigTest04(
void)
4849 path-control-char-handling: status_400\n\
4850 path-convert-utf8: yes\n\
4851 path-invalid-encoding-handling: remove_percent\n\
4856 personality: Tomcat_6_0\n\
4857 path-invalid-utf8-handling: none\n\
4858 path-nul-encoded-handling: status_404\n\
4859 path-nul-raw-handling: status_400\n\
4862 personality: IIS_7_0\n\
4863 path-replacement-char: o\n\
4864 path-unicode-mapping: status_400\n\
4876 if (cfg_rec->
cfg->path_control_char_handling != STATUS_400 ||
4877 cfg_rec->
cfg->path_convert_utf8 != 1 ||
4878 cfg_rec->
cfg->path_invalid_encoding_handling != URL_DECODER_REMOVE_PERCENT) {
4879 printf(
"failed 1\n");
4883 cfg_rec = cfg_rec->
next;
4884 if (cfg_rec->
cfg->bestfit_replacement_char !=
'o' ||
4885 cfg_rec->
cfg->path_unicode_mapping != STATUS_400) {
4886 printf(
"failed 2\n");
4890 cfg_rec = cfg_rec->
next;
4891 if (cfg_rec->
cfg->path_invalid_utf8_handling != NONE ||
4892 cfg_rec->
cfg->path_nul_encoded_handling != STATUS_404 ||
4893 cfg_rec->
cfg->path_nul_raw_handling != STATUS_400) {
4894 printf(
"failed 3\n");
4916 static int HTPParserDecodingTest01(
void)
4918 uint8_t httpbuf1[] =
4919 "GET /abc%2fdef HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
4920 "GET /abc/def?ghi%2fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
4921 "GET /abc/def?ghi%252fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
4922 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4933 personality: Apache_2\n\
4941 const char *addr =
"4.3.2.1";
4942 memset(&ssn, 0,
sizeof(ssn));
4947 f->
proto = IPPROTO_TCP;
4952 for (uint32_t u = 0; u < httplen1; u++) {
4954 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
4955 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
4956 else flags = STREAM_TOSERVER;
4965 uint8_t ref1[] =
"/abc%2fdef";
4966 size_t reflen =
sizeof(ref1) - 1;
4968 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4978 uint8_t ref2[] =
"/abc/def?ghi/jkl";
4979 reflen =
sizeof(ref2) - 1;
4981 tx = HTPStateGetTx(htp_state, 1);
4991 uint8_t ref3[] =
"/abc/def?ghi%2fjkl";
4992 reflen =
sizeof(ref3) - 1;
4993 tx = HTPStateGetTx(htp_state, 2);
5014 static int HTPParserDecodingTest01a(
void)
5016 uint8_t httpbuf1[] =
"GET /abc%2fdef HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
5017 "GET /abc/def?ghi%2fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
5018 "GET /abc/def?ghi%252fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5019 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5030 personality: Apache_2\n\
5038 const char *addr =
"4.3.2.1";
5039 memset(&ssn, 0,
sizeof(ssn));
5044 f->
proto = IPPROTO_TCP;
5050 (STREAM_TOSERVER | STREAM_START | STREAM_EOF), httpbuf1, httplen1);
5056 uint8_t ref1[] =
"/abc%2fdef";
5057 size_t reflen =
sizeof(ref1) - 1;
5059 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5069 uint8_t ref2[] =
"/abc/def?ghi/jkl";
5070 reflen =
sizeof(ref2) - 1;
5072 tx = HTPStateGetTx(htp_state, 1);
5082 uint8_t ref3[] =
"/abc/def?ghi%2fjkl";
5083 reflen =
sizeof(ref3) - 1;
5084 tx = HTPStateGetTx(htp_state, 2);
5111 static int HTPParserDecodingTest02(
void)
5115 uint8_t httpbuf1[] =
5116 "GET /abc%2fdef HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
5117 "GET /abc/def?ghi%2fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
5118 "GET /abc/def?ghi%252fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5119 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5132 double-decode-path: no\n\
5133 double-decode-query: no\n\
5141 const char *addr =
"4.3.2.1";
5142 memset(&ssn, 0,
sizeof(ssn));
5148 f->
proto = IPPROTO_TCP;
5154 for (u = 0; u < httplen1; u++) {
5157 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
5158 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
5159 else flags = STREAM_TOSERVER;
5163 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5170 if (htp_state == NULL) {
5171 printf(
"no http state: ");
5175 uint8_t ref1[] =
"/abc/def";
5176 size_t reflen =
sizeof(ref1) - 1;
5178 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5184 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5193 printf(
"normalized uri \"");
5202 uint8_t ref2[] =
"/abc/def?ghi/jkl";
5203 reflen =
sizeof(ref2) - 1;
5205 tx = HTPStateGetTx(htp_state, 1);
5211 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5220 printf(
"normalized uri \"");
5229 uint8_t ref3[] =
"/abc/def?ghi%2fjkl";
5230 reflen =
sizeof(ref3) - 1;
5231 tx = HTPStateGetTx(htp_state, 2);
5237 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX
" (3): ",
5246 printf(
"normalized uri \"");
5275 static int HTPParserDecodingTest03(
void)
5279 uint8_t httpbuf1[] =
5280 "GET /abc%252fdef HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
5281 "GET /abc/def?ghi%252fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5282 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5295 double-decode-path: yes\n\
5296 double-decode-query: yes\n\
5304 const char *addr =
"4.3.2.1";
5305 memset(&ssn, 0,
sizeof(ssn));
5311 f->
proto = IPPROTO_TCP;
5317 for (u = 0; u < httplen1; u++) {
5320 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
5321 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
5322 else flags = STREAM_TOSERVER;
5326 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5333 if (htp_state == NULL) {
5334 printf(
"no http state: ");
5338 uint8_t ref1[] =
"/abc/def";
5339 size_t reflen =
sizeof(ref1) - 1;
5341 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5347 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5356 printf(
"normalized uri \"");
5365 uint8_t ref2[] =
"/abc/def?ghi/jkl";
5366 reflen =
sizeof(ref2) - 1;
5368 tx = HTPStateGetTx(htp_state, 1);
5374 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5383 printf(
"normalized uri \"");
5409 static int HTPParserDecodingTest04(
void)
5413 uint8_t httpbuf1[] =
5414 "GET /abc/def?a=http://www.abc.com/ HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5415 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5428 double-decode-path: yes\n\
5429 double-decode-query: yes\n\
5437 const char *addr =
"4.3.2.1";
5438 memset(&ssn, 0,
sizeof(ssn));
5444 f->
proto = IPPROTO_TCP;
5450 for (u = 0; u < httplen1; u++) {
5453 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
5454 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
5455 else flags = STREAM_TOSERVER;
5459 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5466 if (htp_state == NULL) {
5467 printf(
"no http state: ");
5471 uint8_t ref1[] =
"/abc/def?a=http://www.abc.com/";
5472 size_t reflen =
sizeof(ref1) - 1;
5474 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5480 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5489 printf(
"normalized uri \"");
5515 static int HTPParserDecodingTest05(
void)
5519 uint8_t httpbuf1[] =
5520 "GET /index?id=\\\"<script>alert(document.cookie)</script> HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5521 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5534 double-decode-path: yes\n\
5535 double-decode-query: yes\n\
5543 const char *addr =
"4.3.2.1";
5544 memset(&ssn, 0,
sizeof(ssn));
5550 f->
proto = IPPROTO_TCP;
5556 for (u = 0; u < httplen1; u++) {
5559 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
5560 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
5561 else flags = STREAM_TOSERVER;
5565 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5572 if (htp_state == NULL) {
5573 printf(
"no http state: ");
5577 uint8_t ref1[] =
"/index?id=\\\"<script>alert(document.cookie)</script>";
5578 size_t reflen =
sizeof(ref1) - 1;
5580 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5586 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5595 printf(
"normalized uri \"");
5621 static int HTPParserDecodingTest06(
void)
5625 uint8_t httpbuf1[] =
5626 "GET /put.php?ip=1.2.3.4&port=+6000 HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5627 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5640 double-decode-path: yes\n\
5641 double-decode-query: yes\n\
5649 const char *addr =
"4.3.2.1";
5650 memset(&ssn, 0,
sizeof(ssn));
5656 f->
proto = IPPROTO_TCP;
5662 for (u = 0; u < httplen1; u++) {
5665 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
5666 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
5667 else flags = STREAM_TOSERVER;
5671 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5678 if (htp_state == NULL) {
5679 printf(
"no http state: ");
5683 uint8_t ref1[] =
"/put.php?ip=1.2.3.4&port=+6000";
5684 size_t reflen =
sizeof(ref1) - 1;
5686 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5692 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5701 printf(
"normalized uri \"");
5727 static int HTPParserDecodingTest07(
void)
5731 uint8_t httpbuf1[] =
5732 "GET /put.php?ip=1.2.3.4&port=+6000 HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5733 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5746 double-decode-path: yes\n\
5747 double-decode-query: yes\n\
5748 query-plusspace-decode: yes\n\
5756 const char *addr =
"4.3.2.1";
5757 memset(&ssn, 0,
sizeof(ssn));
5763 f->
proto = IPPROTO_TCP;
5769 for (u = 0; u < httplen1; u++) {
5772 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
5773 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
5774 else flags = STREAM_TOSERVER;
5778 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5785 if (htp_state == NULL) {
5786 printf(
"no http state: ");
5790 uint8_t ref1[] =
"/put.php?ip=1.2.3.4&port= 6000";
5791 size_t reflen =
sizeof(ref1) - 1;
5793 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5799 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5808 printf(
"normalized uri \"");
5834 static int HTPParserDecodingTest08(
void)