100 #define HTP_MAX_MESSAGES 512
106 static uint64_t htp_state_memuse = 0;
107 static uint64_t htp_state_memcnt = 0;
117 {
"INVALID_TRANSFER_ENCODING_VALUE_IN_REQUEST",
119 {
"INVALID_TRANSFER_ENCODING_VALUE_IN_RESPONSE",
121 {
"INVALID_CONTENT_LENGTH_FIELD_IN_REQUEST",
123 {
"INVALID_CONTENT_LENGTH_FIELD_IN_RESPONSE",
125 {
"DUPLICATE_CONTENT_LENGTH_FIELD_IN_REQUEST",
127 {
"DUPLICATE_CONTENT_LENGTH_FIELD_IN_RESPONSE",
130 {
"UNABLE_TO_MATCH_RESPONSE_TO_REQUEST",
145 {
"REQUEST_SERVER_PORT_TCP_PORT_MISMATCH",
159 {
"RESPONSE_ABNORMAL_TRANSFER_ENCODING",
203 static int HTTPGetFrameIdByName(
const char *frame_name)
212 static const char *HTTPGetFrameNameById(
const uint8_t frame_id)
218 static void *HTPStateGetTx(
void *alstate, uint64_t tx_id);
219 static int HTPStateGetAlstateProgress(
void *tx, uint8_t direction);
220 static uint64_t HTPStateGetTxCnt(
void *alstate);
222 static void HTPParserRegisterTests(
void);
225 static inline uint64_t HtpGetActiveRequestTxID(
HtpState *s)
227 uint64_t
id = HTPStateGetTxCnt(s);
232 static inline uint64_t HtpGetActiveResponseTxID(
HtpState *s)
245 static const char *HTPLookupPersonalityString(
int p)
247 #define CASE_HTP_PERSONALITY_STRING(p) \
248 case HTP_SERVER_ ## p: return #p
251 CASE_HTP_PERSONALITY_STRING(MINIMAL);
252 CASE_HTP_PERSONALITY_STRING(GENERIC);
253 CASE_HTP_PERSONALITY_STRING(IDS);
254 CASE_HTP_PERSONALITY_STRING(IIS_4_0);
255 CASE_HTP_PERSONALITY_STRING(IIS_5_0);
256 CASE_HTP_PERSONALITY_STRING(IIS_5_1);
257 CASE_HTP_PERSONALITY_STRING(IIS_6_0);
258 CASE_HTP_PERSONALITY_STRING(IIS_7_0);
259 CASE_HTP_PERSONALITY_STRING(IIS_7_5);
260 CASE_HTP_PERSONALITY_STRING(APACHE_2);
274 static int HTPLookupPersonality(
const char *
str)
276 #define IF_HTP_PERSONALITY_NUM(p) \
277 if (strcasecmp(#p, str) == 0) return HTP_SERVER_ ## p
289 if (strcasecmp(
"TOMCAT_6_0",
str) == 0) {
291 "longer supported by libhtp.",
294 }
else if ((strcasecmp(
"APACHE",
str) == 0) ||
295 (strcasecmp(
"APACHE_2_2",
str) == 0))
298 "longer supported by libhtp, failing back to "
299 "Apache2 personality.",
301 return HTP_SERVER_APACHE_2;
308 const uint8_t dir,
const uint8_t e)
318 const uint64_t tx_id = (dir == STREAM_TOSERVER) ?
319 HtpGetActiveRequestTxID(s) : HtpGetActiveResponseTxID(s);
321 htp_tx_t *tx = HTPStateGetTx(s, tx_id);
322 if (tx == NULL && tx_id > 0)
323 tx = HTPStateGetTx(s, tx_id - 1);
338 static void *HTPStateAlloc(
void *orig_state,
AppProto proto_orig)
352 htp_state_memuse +=
sizeof(
HtpState);
353 SCLogDebug(
"htp memory %"PRIu64
" (%"PRIu64
")", htp_state_memuse, htp_state_memcnt);
373 if (htud->
tx_data.de_state != NULL) {
399 if (s->
connp != NULL) {
403 uint64_t total_txs = HTPStateGetTxCnt(state);
405 if (s->
conn != NULL) {
406 for (tx_id = s->
tx_freed; tx_id < total_txs; tx_id++) {
407 htp_tx_t *tx = HTPStateGetTx(s, tx_id);
410 HtpTxUserDataFree(s, htud);
411 htp_tx_set_user_data(tx, NULL);
415 htp_connp_destroy_all(s->
connp);
423 htp_state_memuse -=
sizeof(
HtpState);
424 SCLogDebug(
"htp memory %"PRIu64
" (%"PRIu64
")", htp_state_memuse, htp_state_memcnt);
437 static void HTPStateTransactionFree(
void *state, uint64_t
id)
445 htp_tx_t *tx = HTPStateGetTx(s,
id);
449 HtpTxUserDataFree(s, htud);
450 htp_tx_set_user_data(tx, NULL);
457 tx->request_progress == HTP_REQUEST_COMPLETE &&
458 tx->response_progress == HTP_RESPONSE_COMPLETE)))
460 tx->request_progress = HTP_REQUEST_COMPLETE;
461 tx->response_progress = HTP_RESPONSE_COMPLETE;
501 static void AppLayerHtpNeedMultipartHeader(
void)
519 AppLayerHtpNeedMultipartHeader();
527 static void AppLayerHtpSetStreamDepthFlag(
void *tx,
const uint8_t
flags)
532 if (
flags & STREAM_TOCLIENT) {
542 SCLogDebug(
"cfg->body_limit %u stream_depth %u body->content_len_so_far %" PRIu64,
559 static uint32_t AppLayerHtpComputeChunkLength(uint64_t content_len_so_far, uint32_t body_limit,
560 uint32_t stream_depth, uint8_t
flags, uint32_t data_len)
562 uint32_t chunk_len = 0;
564 (content_len_so_far < (uint64_t)body_limit) &&
565 (content_len_so_far + (uint64_t)data_len) > body_limit)
567 chunk_len = body_limit - content_len_so_far;
569 (content_len_so_far < (uint64_t)stream_depth) &&
570 (content_len_so_far + (uint64_t)data_len) > stream_depth)
572 chunk_len = stream_depth - content_len_so_far;
575 return (chunk_len == 0 ? data_len : chunk_len);
622 {
"Request line: URI contains non-compliant delimiter",
624 {
"Request line: non-compliant delimiter between Method and URI",
633 {
"Transfer-encoding has abnormal chunked value",
635 {
"Chunked transfer-encoding on HTTP/0.9 or HTTP/1.0",
638 {
"Invalid response line: invalid response status",
644 {
"Ambiguous response C-L value",
650 #define HTP_ERROR_MAX (sizeof(htp_errors) / sizeof(htp_errors[0]))
651 #define HTP_WARNING_MAX (sizeof(htp_warnings) / sizeof(htp_warnings[0]))
662 static uint8_t HTPHandleWarningGetId(
const char *
msg)
686 static uint8_t HTPHandleErrorGetId(
const char *
msg)
710 static void HTPHandleError(
HtpState *s,
const uint8_t dir)
712 if (s == NULL || s->
conn == NULL ||
713 s->
conn->messages == NULL) {
717 size_t size = htp_list_size(s->
conn->messages);
732 htp_log_t *log = htp_list_get(s->
conn->messages,
msg);
737 htp_tx_t *tx = log->tx;
743 uint8_t
id = HTPHandleErrorGetId(log->msg);
745 id = HTPHandleWarningGetId(log->msg);
751 HTPSetEvent(s, htud, dir,
id);
758 static inline void HTPErrorCheckTxRequestFlags(
HtpState *s, htp_tx_t *tx)
761 BUG_ON(s == NULL || tx == NULL);
763 if (tx->flags & ( HTP_REQUEST_INVALID_T_E|HTP_REQUEST_INVALID_C_L|
764 HTP_HOST_MISSING|HTP_HOST_AMBIGUOUS|HTP_HOSTU_INVALID|
771 if (tx->flags & HTP_REQUEST_INVALID_T_E)
772 HTPSetEvent(s, htud, STREAM_TOSERVER,
774 if (tx->flags & HTP_REQUEST_INVALID_C_L)
775 HTPSetEvent(s, htud, STREAM_TOSERVER,
777 if (tx->flags & HTP_HOST_MISSING)
778 HTPSetEvent(s, htud, STREAM_TOSERVER,
780 if (tx->flags & HTP_HOST_AMBIGUOUS)
781 HTPSetEvent(s, htud, STREAM_TOSERVER,
783 if (tx->flags & HTP_HOSTU_INVALID)
784 HTPSetEvent(s, htud, STREAM_TOSERVER,
786 if (tx->flags & HTP_HOSTH_INVALID)
787 HTPSetEvent(s, htud, STREAM_TOSERVER,
790 if (tx->request_auth_type == HTP_AUTH_UNRECOGNIZED) {
794 HTPSetEvent(s, htud, STREAM_TOSERVER,
797 if (tx->is_protocol_0_9 && tx->request_method_number == HTP_M_UNKNOWN &&
798 (tx->request_protocol_number == HTP_PROTOCOL_INVALID ||
799 tx->request_protocol_number == HTP_PROTOCOL_UNKNOWN)) {
803 HTPSetEvent(s, htud, STREAM_TOSERVER,
814 htp_cfg_t *htp = cfglist.
cfg;
815 void *user_data = NULL;
830 if (user_data != NULL) {
831 htp_cfg_rec = user_data;
832 htp = htp_cfg_rec->
cfg;
835 SCLogDebug(
"Using default HTP config: %p", htp);
839 #ifdef DEBUG_VALIDATION
846 hstate->
connp = htp_connp_create(htp);
847 if (hstate->
connp == NULL) {
851 hstate->
conn = htp_connp_get_connection(hstate->
connp);
853 htp_connp_set_user_data(hstate->
connp, (
void *)hstate);
854 hstate->
cfg = htp_cfg_rec;
859 htp_connp_open(hstate->
connp, NULL, f->
sp, NULL, f->
dp, &
tv);
881 StreamSlice stream_slice,
void *local_data)
891 if (NULL == hstate->
conn) {
892 if (Setup(f, hstate) != 0) {
897 hstate->
slice = &stream_slice;
899 const uint8_t *input = StreamSliceGetData(&stream_slice);
900 uint32_t input_len = StreamSliceGetDataLen(&stream_slice);
905 const int r = htp_connp_req_data(hstate->
connp, &
ts, input, input_len);
907 case HTP_STREAM_ERROR:
913 HTPHandleError(hstate, STREAM_TOSERVER);
920 htp_connp_req_close(hstate->
connp, &
ts);
922 SCLogDebug(
"stream eof encountered, closing htp handle for ts");
926 hstate->
slice = NULL;
948 StreamSlice stream_slice,
void *local_data)
954 const uint8_t *input = StreamSliceGetData(&stream_slice);
955 uint32_t input_len = StreamSliceGetDataLen(&stream_slice);
961 if (NULL == hstate->
conn) {
962 if (Setup(f, hstate) != 0) {
967 hstate->
slice = &stream_slice;
973 const int r = htp_connp_res_data(hstate->
connp, &
ts, input, input_len);
975 case HTP_STREAM_ERROR:
978 case HTP_STREAM_TUNNEL:
979 tx = htp_connp_get_out_tx(hstate->
connp);
980 if (tx != NULL && tx->response_status_number == 101) {
982 (htp_header_t *)htp_table_get_c(tx->response_headers,
"Upgrade");
987 if (tx->request_port_number != -1) {
988 dp = (uint16_t)tx->request_port_number;
990 consumed = htp_connp_res_data_consumed(hstate->
connp);
991 if (bstr_cmp_c(h->value,
"h2c") == 0) {
996 hstate->
slice = NULL;
998 HTPSetEvent(hstate, NULL, STREAM_TOCLIENT,
1003 if (consumed > 0 && consumed < input_len) {
1007 }
else if (bstr_cmp_c_nocase(h->value,
"WebSocket") == 0) {
1012 hstate->
slice = NULL;
1014 HTPSetEvent(hstate, NULL, STREAM_TOCLIENT,
1019 if (consumed > 0 && consumed < input_len) {
1029 HTPHandleError(hstate, STREAM_TOCLIENT);
1036 htp_connp_close(hstate->
connp, &
ts);
1041 hstate->
slice = NULL;
1052 static int HTTPParseContentDispositionHeader(uint8_t *name,
size_t name_len,
1053 uint8_t *data,
size_t len, uint8_t **retptr,
size_t *retlen)
1056 printf(
"DATA START: \n");
1058 printf(
"DATA END: \n");
1063 for (x = 0; x <
len; x++) {
1064 if (!(isspace(data[x])))
1071 uint8_t *line = data+x;
1072 size_t line_len =
len-x;
1075 printf(
"LINE START: \n");
1077 printf(
"LINE END: \n");
1079 for (x = 0 ; x < line_len; x++) {
1081 if (line[x - 1] !=
'\\' && line[x] ==
'\"') {
1085 if (((line[x - 1] !=
'\\' && line[x] ==
';') || ((x + 1) == line_len)) && (quote == 0 || quote % 2 == 0)) {
1086 uint8_t *token = line +
offset;
1087 size_t token_len = x -
offset;
1089 if ((x + 1) == line_len) {
1100 printf(
"TOKEN START: \n");
1102 printf(
"TOKEN END: \n");
1104 if (token_len > name_len) {
1105 if (name == NULL || SCMemcmpLowercase(name, token, name_len) == 0) {
1106 uint8_t *value = token + name_len;
1107 size_t value_len = token_len - name_len;
1109 if (value[0] ==
'\"') {
1113 if (value[value_len-1] ==
'\"') {
1117 printf(
"VALUE START: \n");
1119 printf(
"VALUE END: \n");
1122 *retlen = value_len;
1136 static int HTTPParseContentTypeHeader(uint8_t *name,
size_t name_len,
1137 uint8_t *data,
size_t len, uint8_t **retptr,
size_t *retlen)
1141 printf(
"DATA START: \n");
1143 printf(
"DATA END: \n");
1148 for (x = 0; x <
len; x++) {
1149 if (!(isspace(data[x])))
1157 uint8_t *line = data+x;
1158 size_t line_len =
len-x;
1161 printf(
"LINE START: \n");
1163 printf(
"LINE END: \n");
1165 for (x = 0 ; x < line_len; x++) {
1167 if (line[x - 1] !=
'\\' && line[x] ==
'\"') {
1171 if (((line[x - 1] !=
'\\' && line[x] ==
';') || ((x + 1) == line_len)) && (quote == 0 || quote % 2 == 0)) {
1172 uint8_t *token = line +
offset;
1173 size_t token_len = x -
offset;
1175 if ((x + 1) == line_len) {
1186 printf(
"TOKEN START: \n");
1188 printf(
"TOKEN END: \n");
1190 if (token_len > name_len) {
1191 if (name == NULL || SCMemcmpLowercase(name, token, name_len) == 0) {
1192 uint8_t *value = token + name_len;
1193 size_t value_len = token_len - name_len;
1195 if (value[0] ==
'\"') {
1199 if (value[value_len-1] ==
'\"') {
1203 printf(
"VALUE START: \n");
1205 printf(
"VALUE END: \n");
1208 *retlen = value_len;
1232 static int HtpRequestBodySetupMultipart(htp_tx_t *tx,
HtpTxUserData *htud)
1234 htp_header_t *h = (htp_header_t *)htp_table_get_c(tx->request_headers,
1236 if (h != NULL && bstr_len(h->value) > 0) {
1237 uint8_t *boundary = NULL;
1238 size_t boundary_len = 0;
1240 int r = HTTPParseContentTypeHeader((uint8_t *)
"boundary=", 9,
1241 (uint8_t *) bstr_ptr(h->value), bstr_len(h->value),
1242 &boundary, &boundary_len);
1245 printf(
"BOUNDARY START: \n");
1247 printf(
"BOUNDARY END: \n");
1255 memcpy(htud->
boundary, boundary, boundary_len);
1269 #define C_D_HDR "content-disposition:"
1270 #define C_D_HDR_LEN 20
1271 #define C_T_HDR "content-type:"
1272 #define C_T_HDR_LEN 13
1274 static void HtpRequestBodyMultipartParseHeader(
HtpState *hstate,
1276 uint8_t *header, uint32_t header_len,
1277 uint8_t **filename, uint16_t *filename_len,
1278 uint8_t **filetype, uint16_t *filetype_len)
1286 printf(
"HEADER START: \n");
1288 printf(
"HEADER END: \n");
1291 while (header_len > 0) {
1292 uint8_t *next_line =
Bs2bmSearch(header, header_len, (uint8_t *)
"\r\n", 2);
1293 uint8_t *line = header;
1296 if (next_line == NULL) {
1297 line_len = header_len;
1299 line_len = next_line - header;
1301 uint8_t *sc = (uint8_t *)memchr(line,
':', line_len);
1303 HTPSetEvent(hstate, htud, STREAM_TOSERVER,
1307 }
else if (line_len > 0 && sc == &line[line_len - 1]) {
1308 HTPSetEvent(hstate, htud, STREAM_TOSERVER,
1312 printf(
"LINE START: \n");
1314 printf(
"LINE END: \n");
1322 (void)HTTPParseContentDispositionHeader((uint8_t *)
"filename=", 9,
1323 value, value_len, &fn, &fn_len);
1330 (void)HTTPParseContentTypeHeader(NULL, 0,
1331 value, value_len, &ft, &ft_len);
1335 if (next_line == NULL) {
1339 header_len -= ((next_line + 2) - header);
1340 header = next_line + 2;
1343 if (fn_len > USHRT_MAX)
1345 if (ft_len > USHRT_MAX)
1349 *filename_len = (uint16_t)fn_len;
1351 *filetype_len = (uint16_t)ft_len;
1362 const uint8_t **chunks_buffer, uint32_t *chunks_buffer_len)
1365 chunks_buffer, chunks_buffer_len,
1369 static void FlagDetectStateNewFile(
HtpTxUserData *tx,
int dir)
1372 if (tx && tx->
tx_data.de_state) {
1373 if (dir == STREAM_TOSERVER) {
1374 SCLogDebug(
"DETECT_ENGINE_STATE_FLAG_FILE_NEW set");
1376 }
else if (STREAM_TOCLIENT) {
1377 SCLogDebug(
"DETECT_ENGINE_STATE_FLAG_FILE_NEW set");
1386 static void HtpRequestBodySetupBoundary(
HtpTxUserData *htud,
1387 uint8_t *boundary, uint32_t boundary_len)
1389 memset(boundary,
'-', boundary_len);
1394 const uint8_t *chunks_buffer, uint32_t chunks_buffer_len)
1398 uint16_t expected_boundary_len = htud->
boundary_len + 2;
1399 uint16_t expected_boundary_end_len = htud->
boundary_len + 4;
1400 int tx_progress = 0;
1403 printf(
"CHUNK START: \n");
1405 printf(
"CHUNK END: \n");
1408 HtpRequestBodySetupBoundary(htud, boundary, htud->
boundary_len + 4);
1411 const uint8_t *header_start =
Bs2bmSearch(chunks_buffer, chunks_buffer_len,
1412 boundary, expected_boundary_len);
1414 const uint8_t *form_end = NULL;
1416 const uint8_t *header_end = NULL;
1417 if (header_start != NULL) {
1418 header_end =
Bs2bmSearch(header_start, chunks_buffer_len - (header_start - chunks_buffer),
1419 (uint8_t *)
"\r\n\r\n", 4);
1420 form_end =
Bs2bmSearch(header_start, chunks_buffer_len - (header_start - chunks_buffer),
1421 boundary, expected_boundary_end_len);
1424 SCLogDebug(
"header_start %p, header_end %p, form_end %p", header_start,
1425 header_end, form_end);
1432 if (header_start != NULL || (tx_progress > HTP_REQUEST_BODY)) {
1435 const uint8_t *filedata = chunks_buffer;
1436 uint32_t filedata_len = 0;
1439 if (header_start != NULL) {
1440 if (header_start == filedata + 2) {
1442 SCLogDebug(
"last chunk had all data, but not the boundary");
1444 }
else if (header_start > filedata + 2) {
1445 SCLogDebug(
"some data from last file before the boundary");
1447 filedata_len = header_start - filedata - 2;
1452 if (tx_progress > HTP_REQUEST_BODY) {
1453 filedata_len = chunks_buffer_len;
1457 if (filedata_len > chunks_buffer_len) {
1458 HTPSetEvent(hstate, htud, STREAM_TOSERVER,
1463 printf(
"FILEDATA (final chunk) START: \n");
1465 printf(
"FILEDATA (final chunk) END: \n");
1468 if (
HTPFileClose(hstate, htud, filedata, filedata_len,
flags, STREAM_TOSERVER) ==
1478 SCLogDebug(
"not yet at the end of the file");
1480 if (chunks_buffer_len > expected_boundary_end_len) {
1481 const uint8_t *filedata = chunks_buffer;
1482 uint32_t filedata_len = chunks_buffer_len - expected_boundary_len;
1483 for (; filedata_len < chunks_buffer_len; filedata_len++) {
1485 if (chunks_buffer[filedata_len] ==
'\r') {
1486 if (filedata_len + 1 == chunks_buffer_len ||
1487 chunks_buffer[filedata_len + 1] ==
'\n') {
1494 printf(
"FILEDATA (part) START: \n");
1496 printf(
"FILEDATA (part) END: \n");
1501 hstate, htud, filedata, filedata_len, STREAM_TOSERVER);
1504 }
else if (result == -2) {
1512 SCLogDebug(
"chunk too small to already process in part");
1519 while (header_start != NULL && header_end != NULL &&
1520 header_end != form_end &&
1521 header_start < (chunks_buffer + chunks_buffer_len) &&
1522 header_end < (chunks_buffer + chunks_buffer_len) &&
1523 header_start < header_end)
1525 uint8_t *filename = NULL;
1526 uint16_t filename_len = 0;
1527 uint8_t *filetype = NULL;
1528 uint16_t filetype_len = 0;
1530 uint32_t header_len = header_end - header_start;
1532 uint8_t *header = (uint8_t *)header_start;
1535 if (expected_boundary_len == header_len) {
1537 }
else if ((uint32_t)(expected_boundary_len + 2) <= header_len) {
1538 header_len -= (expected_boundary_len + 2);
1539 header = (uint8_t *)header_start + (expected_boundary_len + 2);
1542 HtpRequestBodyMultipartParseHeader(hstate, htud, header, header_len,
1543 &filename, &filename_len, &filetype, &filetype_len);
1545 if (filename != NULL) {
1546 const uint8_t *filedata = NULL;
1547 uint32_t filedata_len = 0;
1558 if (form_end != NULL) {
1561 filedata = header_end + 4;
1562 if (form_end == filedata) {
1563 HTPSetEvent(hstate, htud, STREAM_TOSERVER,
1566 }
else if (form_end < filedata) {
1567 HTPSetEvent(hstate, htud, STREAM_TOSERVER,
1572 filedata_len = form_end - (header_end + 4 + 2);
1573 SCLogDebug(
"filedata_len %"PRIuMAX, (uintmax_t)filedata_len);
1576 uint8_t *header_next =
Bs2bmSearch(filedata, filedata_len,
1577 boundary, expected_boundary_len);
1578 if (header_next != NULL) {
1579 filedata_len -= (form_end - header_next);
1582 if (filedata_len > chunks_buffer_len) {
1583 HTPSetEvent(hstate, htud, STREAM_TOSERVER,
1587 SCLogDebug(
"filedata_len %"PRIuMAX, (uintmax_t)filedata_len);
1589 printf(
"FILEDATA START: \n");
1591 printf(
"FILEDATA END: \n");
1594 result =
HTPFileOpen(hstate, htud, filename, filename_len, filedata, filedata_len,
1598 }
else if (result == -2) {
1601 if (
HTPFileClose(hstate, htud, NULL, 0, 0, STREAM_TOSERVER) == -1) {
1605 FlagDetectStateNewFile(htud, STREAM_TOSERVER);
1610 SCLogDebug(
"chunk doesn't contain form end");
1612 filedata = header_end + 4;
1613 filedata_len = chunks_buffer_len - (filedata - chunks_buffer);
1614 SCLogDebug(
"filedata_len %u (chunks_buffer_len %u)", filedata_len, chunks_buffer_len);
1616 if (filedata_len > chunks_buffer_len) {
1617 HTPSetEvent(hstate, htud, STREAM_TOSERVER,
1623 printf(
"FILEDATA START: \n");
1625 printf(
"FILEDATA END: \n");
1629 uint8_t *header_next =
Bs2bmSearch(filedata, filedata_len,
1630 boundary, expected_boundary_len);
1632 if (header_next == NULL) {
1635 uint32_t
offset = (header_end + 4) - chunks_buffer;
1639 if (filedata_len >= (uint32_t)(expected_boundary_len + 2)) {
1640 filedata_len -= (expected_boundary_len + 2 - 1);
1642 for (
size_t nb = 0; nb < (size_t)expected_boundary_len + 1; nb++) {
1643 if (filedata[filedata_len] ==
'\r') {
1644 if (nb == expected_boundary_len ||
1645 filedata[filedata_len + 1] ==
'\n') {
1651 SCLogDebug(
"opening file with partial data");
1656 result =
HTPFileOpen(hstate, htud, filename, filename_len, filedata,
1657 filedata_len, STREAM_TOSERVER);
1660 }
else if (result == -2) {
1663 FlagDetectStateNewFile(htud, STREAM_TOSERVER);
1667 }
else if (header_next - filedata > 2) {
1668 filedata_len = header_next - filedata - 2;
1671 result =
HTPFileOpen(hstate, htud, filename, filename_len, filedata,
1672 filedata_len, STREAM_TOSERVER);
1675 }
else if (result == -2) {
1678 if (
HTPFileClose(hstate, htud, NULL, 0, 0, STREAM_TOSERVER) == -1) {
1682 FlagDetectStateNewFile(htud, STREAM_TOSERVER);
1690 SCLogDebug(
"header_start %p, header_end %p, form_end %p",
1691 header_start, header_end, form_end);
1694 uint32_t cursizeread = header_end - chunks_buffer;
1696 chunks_buffer_len - (cursizeread + 4),
1697 boundary, expected_boundary_len);
1698 if (header_start != NULL) {
1700 chunks_buffer_len - (cursizeread + 4),
1701 (uint8_t *)
"\r\n\r\n", 4);
1708 if (chunks_buffer_len > expected_boundary_end_len) {
1709 uint32_t move = chunks_buffer_len - expected_boundary_end_len + 1;
1712 SCLogDebug(
"form not ready, file not set, parsing non-file "
1713 "record: moved %u", move);
1726 htp_tx_t *tx, uint8_t *data, uint32_t data_len)
1733 uint8_t *filename = NULL;
1734 size_t filename_len = 0;
1737 if (tx->parsed_uri != NULL && tx->parsed_uri->path != NULL) {
1738 filename = (uint8_t *)bstr_ptr(tx->parsed_uri->path);
1739 filename_len = bstr_len(tx->parsed_uri->path);
1742 if (filename != NULL) {
1748 result =
HTPFileOpen(hstate, htud, filename, (uint16_t)filename_len, data, data_len,
1752 }
else if (result == -2) {
1755 FlagDetectStateNewFile(htud, STREAM_TOSERVER);
1769 }
else if (result == -2) {
1782 htp_tx_t *tx, uint8_t *data, uint32_t data_len)
1795 uint8_t *filename = NULL;
1796 size_t filename_len = 0;
1799 htp_header_t *h = (htp_header_t *)htp_table_get_c(tx->response_headers,
1800 "Content-Disposition");
1801 if (h != NULL && bstr_len(h->value) > 0) {
1803 (void)HTTPParseContentDispositionHeader((uint8_t *)
"filename=", 9,
1804 (uint8_t *) bstr_ptr(h->value), bstr_len(h->value), &filename, &filename_len);
1808 if (filename == NULL) {
1810 if (tx->parsed_uri != NULL && tx->parsed_uri->path != NULL) {
1811 filename = (uint8_t *)bstr_ptr(tx->parsed_uri->path);
1812 filename_len = bstr_len(tx->parsed_uri->path);
1816 if (filename != NULL) {
1818 htp_header_t *h_content_range = htp_table_get_c(tx->response_headers,
"content-range");
1824 if (h_content_range != NULL) {
1826 data_len, tx, h_content_range->value, htud);
1828 result =
HTPFileOpen(hstate, htud, filename, (uint16_t)filename_len, data, data_len,
1834 }
else if (result == -2) {
1837 FlagDetectStateNewFile(htud, STREAM_TOCLIENT);
1850 }
else if (result == -2) {
1868 static int HTPCallbackRequestBodyData(htp_tx_data_t *d)
1879 printf(
"HTPBODY START: \n");
1881 printf(
"HTPBODY END: \n");
1884 HtpState *hstate = htp_connp_get_user_data(d->tx->connp);
1885 if (hstate == NULL) {
1889 SCLogDebug(
"New request body data available at %p -> %p -> %p, bodylen "
1890 "%"PRIu32
"", hstate, d, d->data, (uint32_t)d->len);
1893 if (tx_ud == NULL) {
1901 if (d->tx->request_method_number == HTP_M_POST) {
1903 int r = HtpRequestBodySetupMultipart(d->tx, tx_ud);
1906 }
else if (r == 0) {
1910 }
else if (d->tx->request_method_number == HTP_M_PUT) {
1933 const uint8_t *chunks_buffer = NULL;
1934 uint32_t chunks_buffer_len = 0;
1942 HtpRequestBodyReassemble(tx_ud, &chunks_buffer, &chunks_buffer_len);
1943 if (chunks_buffer == NULL) {
1947 printf(
"REASSCHUNK START: \n");
1949 printf(
"REASSCHUNK END: \n");
1952 HtpRequestBodyHandleMultipart(hstate, tx_ud, d->tx, chunks_buffer, chunks_buffer_len);
1956 HtpRequestBodyHandlePOSTorPUT(hstate, tx_ud, d->tx, (uint8_t *)d->data,
len);
1961 SCLogDebug(
"closing file that was being stored");
1968 if (hstate->
conn != NULL) {
1969 SCLogDebug(
"checking body size %"PRIu64
" against inspect limit %u (cur %"PRIu64
", last %"PRIu64
")",
1983 const uint32_t data_size = (uint32_t)(
2004 static int HTPCallbackResponseBodyData(htp_tx_data_t *d)
2014 HtpState *hstate = htp_connp_get_user_data(d->tx->connp);
2015 if (hstate == NULL) {
2019 SCLogDebug(
"New response body data available at %p -> %p -> %p, bodylen "
2020 "%"PRIu32
"", hstate, d, d->data, (uint32_t)d->len);
2023 if (tx_ud == NULL) {
2049 HtpResponseBodyHandle(hstate, tx_ud, d->tx, (uint8_t *)d->data,
len);
2052 SCLogDebug(
"closing file that was being stored");
2058 if (hstate->
conn != NULL) {
2059 SCLogDebug(
"checking body size %"PRIu64
" against inspect limit %u (cur %"PRIu64
", last %"PRIu64
")",
2072 const uint32_t data_size = (uint32_t)((uint64_t)hstate->
conn->out_data_counter -
2096 SCLogDebug(
"http_state_memcnt %"PRIu64
", http_state_memuse %"PRIu64
"",
2097 htp_state_memcnt, htp_state_memuse);
2117 htp_config_destroy(cfglist.
cfg);
2118 while (nextrec != NULL) {
2120 nextrec = nextrec->
next;
2122 htp_config_destroy(htprec->
cfg);
2128 static int HTPCallbackRequestHasTrailer(htp_tx_t *tx)
2137 static int HTPCallbackResponseHasTrailer(htp_tx_t *tx)
2150 static int HTPCallbackRequestStart(htp_tx_t *tx)
2152 HtpState *hstate = htp_connp_get_user_data(tx->connp);
2153 if (hstate == NULL) {
2157 uint64_t consumed = hstate->
slice->offset + htp_connp_req_data_consumed(hstate->
connp);
2158 SCLogDebug(
"HTTP request start: data offset %" PRIu64
", in_data_counter %" PRIu64, consumed,
2159 (uint64_t)hstate->
conn->in_data_counter);
2176 if (tx_ud == NULL) {
2181 tx_ud->
tx_data.file_tx = STREAM_TOSERVER | STREAM_TOCLIENT;
2182 htp_tx_set_user_data(tx, tx_ud);
2191 static int HTPCallbackResponseStart(htp_tx_t *tx)
2193 HtpState *hstate = htp_connp_get_user_data(tx->connp);
2194 if (hstate == NULL) {
2198 uint64_t consumed = hstate->
slice->offset + htp_connp_res_data_consumed(hstate->
connp);
2199 SCLogDebug(
"HTTP response start: data offset %" PRIu64
", out_data_counter %" PRIu64, consumed,
2200 (uint64_t)hstate->
conn->out_data_counter);
2215 if (tx_ud == NULL) {
2222 htp_tx_set_user_data(tx, tx_ud);
2233 static int HTPCallbackRequestComplete(htp_tx_t *tx)
2241 HtpState *hstate = htp_connp_get_user_data(tx->connp);
2242 if (hstate == NULL) {
2246 const uint64_t abs_right_edge =
2247 hstate->
slice->offset + htp_connp_req_data_consumed(hstate->
connp);
2255 SCLogDebug(
"HTTP request complete: data offset %" PRIu64
", request_size %" PRIu64,
2257 SCLogDebug(
"frame %p/%" PRIi64
" setting len to %" PRIu64, frame, frame->
id,
2259 frame->
len = (int64_t)request_size;
2265 SCLogDebug(
"transaction_cnt %"PRIu64
", list_size %"PRIu64,
2270 HTPErrorCheckTxRequestFlags(hstate, tx);
2275 SCLogDebug(
"closing file that was being stored");
2276 (void)
HTPFileClose(hstate, htud, NULL, 0, 0, STREAM_TOSERVER);
2278 if (abs_right_edge < (uint64_t)UINT32_MAX) {
2280 hstate->
f->
protoctx, STREAM_TOSERVER, (uint32_t)abs_right_edge);
2298 static int HTPCallbackResponseComplete(htp_tx_t *tx)
2302 HtpState *hstate = htp_connp_get_user_data(tx->connp);
2303 if (hstate == NULL) {
2310 const uint64_t abs_right_edge =
2311 hstate->
slice->offset + htp_connp_res_data_consumed(hstate->
connp);
2318 SCLogDebug(
"HTTP response complete: data offset %" PRIu64
", response_size %" PRIu64,
2320 SCLogDebug(
"frame %p/%" PRIi64
" setting len to %" PRIu64, frame, frame->
id,
2322 frame->
len = (int64_t)response_size;
2330 SCLogDebug(
"closing file that was being stored");
2331 (void)
HTPFileClose(hstate, htud, NULL, 0, 0, STREAM_TOCLIENT);
2341 if (tx->request_method_number == HTP_M_CONNECT) {
2344 if ((tx->response_status_number >= 200) &&
2345 (tx->response_status_number < 300) &&
2348 if (tx->request_port_number != -1) {
2349 dp = (uint16_t)tx->request_port_number;
2356 tx->request_progress = HTP_REQUEST_COMPLETE;
2357 tx->response_progress = HTP_RESPONSE_COMPLETE;
2365 static int HTPCallbackRequestLine(htp_tx_t *tx)
2368 bstr *request_uri_normalized;
2369 HtpState *hstate = htp_connp_get_user_data(tx->connp);
2373 if (request_uri_normalized == NULL)
2376 tx_ud = htp_tx_get_user_data(tx);
2378 bstr_free(request_uri_normalized);
2386 HTPErrorCheckTxRequestFlags(hstate, tx);
2391 static int HTPCallbackDoubleDecodeUriPart(htp_tx_t *tx, bstr *part)
2397 size_t prevlen = bstr_len(part);
2398 htp_status_t res = htp_urldecode_inplace(tx->cfg, HTP_DECODER_URLENCODED, part, &
flags);
2400 if (res == HTP_OK && prevlen > bstr_len(part)) {
2404 HtpState *s = htp_connp_get_user_data(tx->connp);
2407 HTPSetEvent(s, htud, STREAM_TOSERVER,
2414 static int HTPCallbackDoubleDecodeQuery(htp_tx_t *tx)
2416 if (tx->parsed_uri == NULL)
2419 return HTPCallbackDoubleDecodeUriPart(tx, tx->parsed_uri->query);
2422 static int HTPCallbackDoubleDecodePath(htp_tx_t *tx)
2424 if (tx->parsed_uri == NULL)
2427 return HTPCallbackDoubleDecodeUriPart(tx, tx->parsed_uri->path);
2430 static int HTPCallbackRequestHeaderData(htp_tx_data_t *tx_data)
2433 if (tx_data->len == 0 || tx_data->tx == NULL)
2437 if (tx_ud == NULL) {
2449 tx_data->data, tx_data->len);
2452 if (tx_data->tx && tx_data->tx->flags) {
2453 HtpState *hstate = htp_connp_get_user_data(tx_data->tx->connp);
2454 HTPErrorCheckTxRequestFlags(hstate, tx_data->tx);
2459 static int HTPCallbackResponseHeaderData(htp_tx_data_t *tx_data)
2462 if (tx_data->len == 0 || tx_data->tx == NULL)
2466 if (tx_ud == NULL) {
2478 tx_data->data, tx_data->len);
2487 static void HTPConfigSetDefaultsPhase1(
HTPCfgRec *cfg_prec)
2504 htp_config_register_request_header_data(cfg_prec->
cfg, HTPCallbackRequestHeaderData);
2505 htp_config_register_request_trailer_data(cfg_prec->
cfg, HTPCallbackRequestHeaderData);
2506 htp_config_register_response_header_data(cfg_prec->
cfg, HTPCallbackResponseHeaderData);
2507 htp_config_register_response_trailer_data(cfg_prec->
cfg, HTPCallbackResponseHeaderData);
2509 htp_config_register_request_trailer(cfg_prec->
cfg, HTPCallbackRequestHasTrailer);
2510 htp_config_register_response_trailer(cfg_prec->
cfg, HTPCallbackResponseHasTrailer);
2512 htp_config_register_request_body_data(cfg_prec->
cfg, HTPCallbackRequestBodyData);
2513 htp_config_register_response_body_data(cfg_prec->
cfg, HTPCallbackResponseBodyData);
2515 htp_config_register_request_start(cfg_prec->
cfg, HTPCallbackRequestStart);
2516 htp_config_register_request_complete(cfg_prec->
cfg, HTPCallbackRequestComplete);
2518 htp_config_register_response_start(cfg_prec->
cfg, HTPCallbackResponseStart);
2519 htp_config_register_response_complete(cfg_prec->
cfg, HTPCallbackResponseComplete);
2521 htp_config_set_parse_request_cookies(cfg_prec->
cfg, 0);
2522 #ifdef HAVE_HTP_CONFIG_SET_ALLOW_SPACE_URI
2523 htp_config_set_allow_space_uri(cfg_prec->
cfg, 1);
2527 htp_config_set_plusspace_decode(cfg_prec->
cfg, HTP_DECODER_URLENCODED, 0);
2529 htp_config_set_request_decompression(cfg_prec->
cfg, 1);
2530 #ifdef HAVE_HTP_CONFIG_SET_LZMA_LAYERS
2534 #ifdef HAVE_HTP_CONFIG_SET_LZMA_MEMLIMIT
2535 htp_config_set_lzma_memlimit(cfg_prec->
cfg,
2538 #ifdef HAVE_HTP_CONFIG_SET_COMPRESSION_BOMB_LIMIT
2539 htp_config_set_compression_bomb_limit(cfg_prec->
cfg,
2542 #ifdef HAVE_HTP_CONFIG_SET_COMPRESSION_TIME_LIMIT
2545 #ifdef HAVE_HTP_CONFIG_SET_MAX_TX
2546 #define HTP_CONFIG_DEFAULT_MAX_TX_LIMIT 512
2547 htp_config_set_max_tx(cfg_prec->
cfg, HTP_CONFIG_DEFAULT_MAX_TX_LIMIT);
2555 htp_config_set_field_limits(cfg_prec->
cfg,
2564 static int RandomGetWrap(
void)
2570 }
while(r >= ULONG_MAX - (ULONG_MAX % RAND_MAX));
2572 return r % RAND_MAX;
2581 static void HTPConfigSetDefaultsPhase2(
const char *name,
HTPCfgRec *cfg_prec)
2587 long int r = RandomGetWrap();
2589 ((
double)r / RAND_MAX - 0.5) * rdrange / 100);
2591 r = RandomGetWrap();
2593 ((
double)r / RAND_MAX - 0.5) * rdrange / 100);
2594 SCLogConfig(
"'%s' server has 'request-body-minimal-inspect-size' set to"
2595 " %u and 'request-body-inspect-window' set to %u after"
2599 r = RandomGetWrap();
2601 ((
double)r / RAND_MAX - 0.5) * rdrange / 100);
2603 r = RandomGetWrap();
2605 ((
double)r / RAND_MAX - 0.5) * rdrange / 100);
2607 SCLogConfig(
"'%s' server has 'response-body-minimal-inspect-size' set to"
2608 " %u and 'response-body-inspect-window' set to %u after"
2613 htp_config_register_request_line(cfg_prec->
cfg, HTPCallbackRequestLine);
2620 if (cfg_prec == NULL || s == NULL || tree == NULL)
2628 if (strcasecmp(
"address", p->
name) == 0) {
2636 if (strchr(pval->
val,
':') != NULL) {
2637 SCLogDebug(
"LIBHTP adding ipv6 server %s at %s: %p",
2641 "add ipv6 server %s, ignoring",
2645 SCLogDebug(
"LIBHTP adding ipv4 server %s at %s: %p",
2649 "to add ipv4 server %s, ignoring",
2655 }
else if (strcasecmp(
"personality", p->
name) == 0) {
2657 int personality = HTPLookupPersonality(p->
val);
2661 if (personality >= 0) {
2664 if (htp_config_set_server_personality(cfg_prec->
cfg, personality) == HTP_ERROR){
2666 "personality \"%s\", ignoring",
2670 HTPLookupPersonalityString(personality));
2676 htp_config_set_convert_lowercase(cfg_prec->
cfg, HTP_DECODER_URL_PATH, 0);
2684 }
else if (strcasecmp(
"request-body-limit", p->
name) == 0 ||
2685 strcasecmp(
"request_body_limit", p->
name) == 0) {
2687 SCLogError(
"Error parsing request-body-limit "
2688 "from conf file - %s. Killing engine",
2693 }
else if (strcasecmp(
"response-body-limit", p->
name) == 0) {
2695 SCLogError(
"Error parsing response-body-limit "
2696 "from conf file - %s. Killing engine",
2701 }
else if (strcasecmp(
"request-body-minimal-inspect-size", p->
name) == 0) {
2703 SCLogError(
"Error parsing request-body-minimal-inspect-size "
2704 "from conf file - %s. Killing engine",
2709 }
else if (strcasecmp(
"request-body-inspect-window", p->
name) == 0) {
2711 SCLogError(
"Error parsing request-body-inspect-window "
2712 "from conf file - %s. Killing engine",
2717 }
else if (strcasecmp(
"double-decode-query", p->
name) == 0) {
2719 htp_config_register_request_line(cfg_prec->
cfg,
2720 HTPCallbackDoubleDecodeQuery);
2723 }
else if (strcasecmp(
"double-decode-path", p->
name) == 0) {
2725 htp_config_register_request_line(cfg_prec->
cfg,
2726 HTPCallbackDoubleDecodePath);
2729 }
else if (strcasecmp(
"response-body-minimal-inspect-size", p->
name) == 0) {
2731 SCLogError(
"Error parsing response-body-minimal-inspect-size "
2732 "from conf file - %s. Killing engine",
2737 }
else if (strcasecmp(
"response-body-inspect-window", p->
name) == 0) {
2739 SCLogError(
"Error parsing response-body-inspect-window "
2740 "from conf file - %s. Killing engine",
2745 }
else if (strcasecmp(
"response-body-decompress-layer-limit", p->
name) == 0) {
2748 SCLogError(
"Error parsing response-body-inspect-window "
2749 "from conf file - %s. Killing engine",
2753 #ifdef HAVE_HTP_CONFIG_SET_RESPONSE_DECOMPRESSION_LAYER_LIMIT
2754 htp_config_set_response_decompression_layer_limit(cfg_prec->
cfg, value);
2756 SCLogWarning(
"can't set response-body-decompress-layer-limit "
2757 "to %u, libhtp version too old",
2760 }
else if (strcasecmp(
"path-convert-backslash-separators", p->
name) == 0) {
2761 htp_config_set_backslash_convert_slashes(cfg_prec->
cfg,
2762 HTP_DECODER_URL_PATH,
2764 }
else if (strcasecmp(
"path-bestfit-replacement-char", p->
name) == 0) {
2765 if (strlen(p->
val) == 1) {
2766 htp_config_set_bestfit_replacement_byte(cfg_prec->
cfg,
2767 HTP_DECODER_URL_PATH,
2771 "for libhtp param path-bestfit-replacement-char");
2773 }
else if (strcasecmp(
"path-convert-lowercase", p->
name) == 0) {
2774 htp_config_set_convert_lowercase(cfg_prec->
cfg,
2775 HTP_DECODER_URL_PATH,
2777 }
else if (strcasecmp(
"path-nul-encoded-terminates", p->
name) == 0) {
2778 htp_config_set_nul_encoded_terminates(cfg_prec->
cfg,
2779 HTP_DECODER_URL_PATH,
2781 }
else if (strcasecmp(
"path-nul-raw-terminates", p->
name) == 0) {
2782 htp_config_set_nul_raw_terminates(cfg_prec->
cfg,
2783 HTP_DECODER_URL_PATH,
2785 }
else if (strcasecmp(
"path-separators-compress", p->
name) == 0) {
2786 htp_config_set_path_separators_compress(cfg_prec->
cfg,
2787 HTP_DECODER_URL_PATH,
2789 }
else if (strcasecmp(
"path-separators-decode", p->
name) == 0) {
2790 htp_config_set_path_separators_decode(cfg_prec->
cfg,
2791 HTP_DECODER_URL_PATH,
2793 }
else if (strcasecmp(
"path-u-encoding-decode", p->
name) == 0) {
2794 htp_config_set_u_encoding_decode(cfg_prec->
cfg,
2795 HTP_DECODER_URL_PATH,
2797 }
else if (strcasecmp(
"path-url-encoding-invalid-handling", p->
name) == 0) {
2798 enum htp_url_encoding_handling_t handling;
2799 if (strcasecmp(p->
val,
"preserve_percent") == 0) {
2800 handling = HTP_URL_DECODE_PRESERVE_PERCENT;
2801 }
else if (strcasecmp(p->
val,
"remove_percent") == 0) {
2802 handling = HTP_URL_DECODE_REMOVE_PERCENT;
2803 }
else if (strcasecmp(p->
val,
"decode_invalid") == 0) {
2804 handling = HTP_URL_DECODE_PROCESS_INVALID;
2807 "for libhtp param path-url-encoding-invalid-handling");
2810 htp_config_set_url_encoding_invalid_handling(cfg_prec->
cfg,
2811 HTP_DECODER_URL_PATH,
2813 }
else if (strcasecmp(
"path-utf8-convert-bestfit", p->
name) == 0) {
2814 htp_config_set_utf8_convert_bestfit(cfg_prec->
cfg,
2815 HTP_DECODER_URL_PATH,
2817 }
else if (strcasecmp(
"uri-include-all", p->
name) == 0) {
2821 }
else if (strcasecmp(
"query-plusspace-decode", p->
name) == 0) {
2822 htp_config_set_plusspace_decode(cfg_prec->
cfg,
2823 HTP_DECODER_URLENCODED,
2825 }
else if (strcasecmp(
"meta-field-limit", p->
name) == 0) {
2829 "from conf file - %s. Killing engine",
2835 "from conf file cannot be 0. Killing engine");
2838 htp_config_set_field_limits(cfg_prec->
cfg,
2841 #ifdef HAVE_HTP_CONFIG_SET_LZMA_MEMLIMIT
2842 }
else if (strcasecmp(
"lzma-memlimit", p->
name) == 0) {
2845 FatalError(
"failed to parse 'lzma-memlimit' "
2846 "from conf file - %s.",
2851 "from conf file cannot be 0.");
2854 SCLogConfig(
"Setting HTTP LZMA memory limit to %"PRIu32
" bytes", limit);
2855 htp_config_set_lzma_memlimit(cfg_prec->
cfg, (
size_t)limit);
2857 #ifdef HAVE_HTP_CONFIG_SET_LZMA_LAYERS
2858 }
else if (strcasecmp(
"lzma-enabled", p->
name) == 0) {
2860 htp_config_set_lzma_layers(cfg_prec->
cfg, 1);
2865 "from conf file - %s.",
2868 SCLogConfig(
"Setting HTTP LZMA decompression layers to %" PRIu32
"", (
int)limit);
2869 htp_config_set_lzma_layers(cfg_prec->
cfg, limit);
2872 #ifdef HAVE_HTP_CONFIG_SET_COMPRESSION_BOMB_LIMIT
2873 }
else if (strcasecmp(
"compression-bomb-limit", p->
name) == 0) {
2876 FatalError(
"failed to parse 'compression-bomb-limit' "
2877 "from conf file - %s.",
2882 "from conf file cannot be 0.");
2885 SCLogConfig(
"Setting HTTP compression bomb limit to %"PRIu32
" bytes", limit);
2886 htp_config_set_compression_bomb_limit(cfg_prec->
cfg, (
size_t)limit);
2888 #ifdef HAVE_HTP_CONFIG_SET_COMPRESSION_TIME_LIMIT
2889 }
else if (strcasecmp(
"decompression-time-limit", p->
name) == 0) {
2893 FatalError(
"failed to parse 'decompression-time-limit' "
2894 "from conf file - %s.",
2897 SCLogConfig(
"Setting HTTP decompression time limit to %" PRIu32
" usec", limit);
2898 htp_config_set_compression_time_limit(cfg_prec->
cfg, (
size_t)limit);
2900 #ifdef HAVE_HTP_CONFIG_SET_MAX_TX
2901 }
else if (strcasecmp(
"max-tx", p->
name) == 0) {
2905 "from conf file - %s.",
2909 SCLogConfig(
"Setting HTTP max-tx limit to %" PRIu32
" bytes", limit);
2910 htp_config_set_max_tx(cfg_prec->
cfg, (
size_t)limit);
2912 }
else if (strcasecmp(
"randomize-inspection-sizes", p->
name) == 0) {
2916 }
else if (strcasecmp(
"randomize-inspection-range", p->
name) == 0) {
2919 (
const char *)p->
val, 0, 100) < 0) {
2921 "-inspection-range setting from conf file - \"%s\"."
2922 " It should be a valid integer less than or equal to 100."
2928 }
else if (strcasecmp(
"http-body-inline", p->
name) == 0) {
2934 if (strcmp(
"auto", p->
val) != 0) {
2943 }
else if (strcasecmp(
"swf-decompression", p->
name) == 0) {
2947 if (strcasecmp(
"enabled", pval->
name) == 0) {
2955 }
else if (strcasecmp(
"type", pval->
name) == 0) {
2956 if (strcasecmp(
"no", pval->
val) == 0) {
2958 }
else if (strcasecmp(
"deflate", pval->
val) == 0) {
2960 }
else if (strcasecmp(
"lzma", pval->
val) == 0) {
2962 }
else if (strcasecmp(
"both", pval->
val) == 0) {
2966 "swf-decompression.type: %s - "
2971 }
else if (strcasecmp(
"compress-depth", pval->
name) == 0) {
2973 SCLogError(
"Error parsing swf-decompression.compression-depth "
2974 "from conf file - %s. Killing engine",
2978 }
else if (strcasecmp(
"decompress-depth", pval->
name) == 0) {
2980 SCLogError(
"Error parsing swf-decompression.decompression-depth "
2981 "from conf file - %s. Killing engine",
2991 "default config: %s",
3003 cfglist.
next = NULL;
3010 if (NULL == cfgtree)
3014 cfglist.
cfg = htp_config_create();
3015 if (NULL == cfglist.
cfg) {
3016 FatalError(
"Failed to create HTP default config");
3019 HTPConfigSetDefaultsPhase1(&cfglist);
3020 if (
ConfGetNode(
"app-layer.protocols.http.libhtp") == NULL) {
3021 HTPConfigParseParameters(&cfglist,
ConfGetNode(
"libhtp.default-config"),
3024 HTPConfigParseParameters(&cfglist,
ConfGetNode(
"app-layer.protocols.http.libhtp.default-config"), cfgtree);
3026 HTPConfigSetDefaultsPhase2(
"default", &cfglist);
3032 if (server_config == NULL) {
3033 server_config =
ConfGetNode(
"libhtp.server-config");
3034 if (server_config == NULL) {
3035 SCLogDebug(
"LIBHTP Configuring %p", server_config);
3039 SCLogDebug(
"LIBHTP Configuring %p", server_config);
3058 cfglist.
next = htprec;
3061 cfglist.
next->
cfg = htp_config_create();
3062 if (NULL == cfglist.
next->
cfg) {
3063 FatalError(
"Failed to create HTP server config");
3066 HTPConfigSetDefaultsPhase1(htprec);
3067 HTPConfigParseParameters(htprec, s, cfgtree);
3068 HTPConfigSetDefaultsPhase2(s->
name, htprec);
3078 SCLogPerf(
"htp memory %"PRIu64
" (%"PRIu64
")", htp_state_memuse, htp_state_memcnt);
3089 static AppLayerGetFileState HTPGetTxFiles(
void *state,
void *txv, uint8_t direction)
3091 AppLayerGetFileState files = { .fc = NULL, .cfg = &
htp_sbcfg };
3092 htp_tx_t *tx = (htp_tx_t *)txv;
3095 if (direction & STREAM_TOCLIENT) {
3104 static int HTPStateGetAlstateProgress(
void *tx, uint8_t direction)
3106 if (direction & STREAM_TOSERVER)
3107 return ((htp_tx_t *)tx)->request_progress;
3109 return ((htp_tx_t *)tx)->response_progress;
3112 static uint64_t HTPStateGetTxCnt(
void *alstate)
3116 if (http_state != NULL && http_state->
conn != NULL) {
3117 const int64_t size = (int64_t)htp_list_size(http_state->
conn->transactions);
3121 return (uint64_t)size + http_state->
tx_freed;
3127 static void *HTPStateGetTx(
void *alstate, uint64_t tx_id)
3131 if (http_state != NULL && http_state->
conn != NULL && tx_id >= http_state->
tx_freed)
3132 return htp_list_get(http_state->
conn->transactions, tx_id - http_state->
tx_freed);
3141 if (http_state != NULL && http_state->
conn != NULL) {
3142 size_t txid = HTPStateGetTxCnt(http_state);
3144 return htp_list_get(http_state->
conn->transactions, txid - http_state->
tx_freed - 1);
3150 static int HTPStateGetEventInfo(
const char *event_name,
3151 int *event_id, AppLayerEventType *event_type)
3154 if (*event_id == -1) {
3156 "http's enum map table.",
3162 *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
3167 static int HTPStateGetEventInfoById(
int event_id,
const char **event_name,
3168 AppLayerEventType *event_type)
3171 if (*event_name == NULL) {
3173 "http's enum map table.",
3179 *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
3186 htp_tx_t *tx = (htp_tx_t *)vtx;
3194 static AppLayerStateData *HTPGetStateData(
void *vstate)
3200 static int HTPRegisterPatternsForProtocolDetection(
void)
3202 const char *methods[] = {
"GET",
"PUT",
"POST",
"HEAD",
"TRACE",
"OPTIONS",
3203 "CONNECT",
"DELETE",
"PATCH",
"PROPFIND",
"PROPPATCH",
"MKCOL",
3204 "COPY",
"MOVE",
"LOCK",
"UNLOCK",
"CHECKOUT",
"UNCHECKOUT",
"CHECKIN",
3205 "UPDATE",
"LABEL",
"REPORT",
"MKWORKSPACE",
"MKACTIVITY",
"MERGE",
3206 "INVALID",
"VERSION-CONTROL",
"BASELINE-CONTROL", NULL};
3207 const char *spacings[] = {
"|20|",
"|09|", NULL };
3208 const char *versions[] = {
"HTTP/0.9",
"HTTP/1.0",
"HTTP/1.1", NULL };
3213 int register_result;
3214 char method_buffer[32] =
"";
3217 for (methods_pos = 0; methods[methods_pos]; methods_pos++) {
3218 for (spacings_pos = 0; spacings[spacings_pos]; spacings_pos++) {
3221 snprintf(method_buffer,
sizeof(method_buffer),
"%s%s", methods[methods_pos], spacings[spacings_pos]);
3228 method_buffer, (uint16_t)strlen(method_buffer) - 3, 0, STREAM_TOSERVER);
3229 if (register_result < 0) {
3236 for (versions_pos = 0; versions[versions_pos]; versions_pos++) {
3238 versions[versions_pos], (uint16_t)strlen(versions[versions_pos]), 0,
3240 if (register_result < 0) {
3256 const char *proto_name =
"http";
3261 if (HTPRegisterPatternsForProtocolDetection() < 0)
3264 SCLogInfo(
"Protocol detection and parser disabled for %s protocol",
3279 ALPROTO_HTTP1, HTP_REQUEST_COMPLETE, HTP_RESPONSE_COMPLETE);
3291 IPPROTO_TCP,
ALPROTO_HTTP1, STREAM_TOSERVER, HTPHandleRequestData);
3293 IPPROTO_TCP,
ALPROTO_HTTP1, STREAM_TOCLIENT, HTPHandleResponseData);
3299 IPPROTO_TCP,
ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_TOCLIENT);
3302 IPPROTO_TCP,
ALPROTO_HTTP1, HTTPGetFrameIdByName, HTTPGetFrameNameById);
3306 SCLogInfo(
"Parser disabled for %s protocol. Protocol detection still on.", proto_name);
3322 cfglist_backup = cfglist;
3329 cfglist = cfglist_backup;
3336 static int HTPParserTest01(
void)
3338 uint8_t httpbuf1[] =
"POST / HTTP/1.0\r\nUser-Agent: Victor/1.0\r\n\r\nPost"
3340 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3343 memset(&ssn, 0,
sizeof(ssn));
3351 f->
proto = IPPROTO_TCP;
3357 for (u = 0; u < httplen1; u++) {
3361 flags = STREAM_TOSERVER|STREAM_START;
3362 else if (u == (httplen1 - 1))
3363 flags = STREAM_TOSERVER|STREAM_EOF;
3365 flags = STREAM_TOSERVER;
3374 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3377 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3380 FAIL_IF(strcmp(bstr_util_strdup_to_c(h->value),
"Victor/1.0"));
3381 FAIL_IF(tx->request_method_number != HTP_M_POST);
3382 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_0);
3391 static int HTPParserTest01b(
void)
3393 uint8_t httpbuf1[] =
"POST / HTTP/1.0\r\nUser-Agent:\r\n Victor/1.0\r\n\r\nPost"
3395 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3398 memset(&ssn, 0,
sizeof(ssn));
3406 f->
proto = IPPROTO_TCP;
3411 uint8_t
flags =STREAM_TOSERVER|STREAM_START|STREAM_EOF;
3418 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3421 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3424 FAIL_IF(strcmp(bstr_util_strdup_to_c(h->value),
"Victor/1.0"));
3425 FAIL_IF(tx->request_method_number != HTP_M_POST);
3426 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_0);
3435 static int HTPParserTest01c(
void)
3437 uint8_t httpbuf1[] =
"POST / HTTP/1.0\r\nUser-Agent:\r\n Victor/1.0\r\n\r\nPost"
3439 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3442 memset(&ssn, 0,
sizeof(ssn));
3450 f->
proto = IPPROTO_TCP;
3456 for (u = 0; u < httplen1; u++) {
3460 flags = STREAM_TOSERVER|STREAM_START;
3461 else if (u == (httplen1 - 1))
3462 flags = STREAM_TOSERVER|STREAM_EOF;
3464 flags = STREAM_TOSERVER;
3473 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3476 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3479 FAIL_IF(strcmp(bstr_util_strdup_to_c(h->value),
"Victor/1.0"));
3480 FAIL_IF(tx->request_method_number != HTP_M_POST);
3481 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_0);
3491 static int HTPParserTest01a(
void)
3495 uint8_t httpbuf1[] =
" POST / HTTP/1.0\r\nUser-Agent: Victor/1.0\r\n\r\nPost"
3497 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3503 memset(&ssn, 0,
sizeof(ssn));
3505 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
3509 f->
proto = IPPROTO_TCP;
3515 for (u = 0; u < httplen1; u++) {
3519 flags = STREAM_TOSERVER|STREAM_START;
3520 else if (u == (httplen1 - 1))
3521 flags = STREAM_TOSERVER|STREAM_EOF;
3523 flags = STREAM_TOSERVER;
3527 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
3534 if (htp_state == NULL) {
3535 printf(
"no http state: ");
3539 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3540 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3541 if (strcmp(bstr_util_strdup_to_c(h->value),
"Victor/1.0")
3542 || tx->request_method_number != HTP_M_POST ||
3543 tx->request_protocol_number != HTP_PROTOCOL_1_0)
3545 printf(
"expected header value: Victor/1.0 and got %s: and expected"
3546 " method: POST and got %s, expected protocol number HTTP/1.0"
3547 " and got: %s \n", bstr_util_strdup_to_c(h->value),
3548 bstr_util_strdup_to_c(tx->request_method),
3549 bstr_util_strdup_to_c(tx->request_protocol));
3562 static int HTPParserTest02(
void)
3566 uint8_t httpbuf1[] =
"POST";
3567 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3572 memset(&ssn, 0,
sizeof(ssn));
3574 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
3578 f->
proto = IPPROTO_TCP;
3584 STREAM_TOSERVER | STREAM_START | STREAM_EOF, httpbuf1, httplen1);
3586 printf(
"toserver chunk 1 returned %" PRId32
", expected 0: ", r);
3591 if (http_state == NULL) {
3592 printf(
"no http state: ");
3596 htp_tx_t *tx = HTPStateGetTx(http_state, 0);
3598 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3602 char *method = bstr_util_strdup_to_c(tx->request_method);
3605 FAIL_IF(strcmp(method,
"POST") != 0);
3619 static int HTPParserTest03(
void)
3623 uint8_t httpbuf1[] =
"HELLO / HTTP/1.0\r\n";
3624 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3630 memset(&ssn, 0,
sizeof(ssn));
3632 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
3636 f->
proto = IPPROTO_TCP;
3642 for (u = 0; u < httplen1; u++) {
3645 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
3646 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
3647 else flags = STREAM_TOSERVER;
3651 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
3657 if (htp_state == NULL) {
3658 printf(
"no http state: ");
3662 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3664 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3665 if (tx->request_method_number != HTP_M_UNKNOWN ||
3666 h != NULL || tx->request_protocol_number != HTP_PROTOCOL_1_0)
3668 printf(
"expected method M_UNKNOWN and got %s: , expected protocol "
3669 "HTTP/1.0 and got %s \n", bstr_util_strdup_to_c(tx->request_method),
3670 bstr_util_strdup_to_c(tx->request_protocol));
3684 static int HTPParserTest04(
void)
3689 uint8_t httpbuf1[] =
"World!\r\n";
3690 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3695 memset(&ssn, 0,
sizeof(ssn));
3697 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
3701 f->
proto = IPPROTO_TCP;
3707 STREAM_TOSERVER | STREAM_START | STREAM_EOF, httpbuf1, httplen1);
3713 if (htp_state == NULL) {
3714 printf(
"no http state: ");
3718 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3719 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3720 if (tx->request_method_number != HTP_M_UNKNOWN ||
3721 h != NULL || tx->request_protocol_number != HTP_PROTOCOL_0_9)
3723 printf(
"expected method M_UNKNOWN and got %s: , expected protocol "
3724 "NULL and got %s \n", bstr_util_strdup_to_c(tx->request_method),
3725 bstr_util_strdup_to_c(tx->request_protocol));
3739 static int HTPParserTest05(
void)
3741 uint8_t httpbuf1[] =
"POST / HTTP/1.0\r\nUser-Agent: Victor/1.0\r\nContent-Length: 17\r\n\r\n";
3742 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3743 uint8_t httpbuf2[] =
"Post D";
3744 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
3745 uint8_t httpbuf3[] =
"ata is c0oL!";
3746 uint32_t httplen3 =
sizeof(httpbuf3) - 1;
3748 uint8_t httpbuf4[] =
"HTTP/1.0 200 OK\r\nServer: VictorServer/1.0\r\n\r\n";
3749 uint32_t httplen4 =
sizeof(httpbuf4) - 1;
3750 uint8_t httpbuf5[] =
"post R";
3751 uint32_t httplen5 =
sizeof(httpbuf5) - 1;
3752 uint8_t httpbuf6[] =
"esults are tha bomb!";
3753 uint32_t httplen6 =
sizeof(httpbuf6) - 1;
3756 memset(&ssn, 0,
sizeof(ssn));
3764 f->
proto = IPPROTO_TCP;
3794 htp_tx_t *tx = HTPStateGetTx(http_state, 0);
3796 FAIL_IF_NOT(tx->request_method_number == HTP_M_POST);
3797 FAIL_IF_NOT(tx->request_protocol_number == HTP_PROTOCOL_1_0);
3799 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3812 static int HTPParserTest06(
void)
3814 uint8_t httpbuf1[] =
"GET /ld/index.php?id=412784631&cid=0064&version=4&"
3815 "name=try HTTP/1.1\r\nAccept: */*\r\nUser-Agent: "
3816 "LD-agent\r\nHost: 209.205.196.16\r\n\r\n";
3817 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3818 uint8_t httpbuf2[] =
"HTTP/1.1 200 OK\r\nDate: Sat, 03 Oct 2009 10:16:02 "
3820 "Server: Apache/1.3.37 (Unix) mod_ssl/2.8.28 "
3821 "OpenSSL/0.9.7a PHP/4.4.7 mod_perl/1.29 "
3822 "FrontPage/5.0.2.2510\r\n"
3823 "X-Powered-By: PHP/4.4.7\r\nTransfer-Encoding: "
3825 "Content-Type: text/html\r\n\r\n"
3827 "W2dyb3VwMV0NCnBob25lMT1wMDB3ODgyMTMxMzAyMTINCmxvZ2lu"
3828 "MT0NCnBhc3N3b3JkMT0NCnBob25lMj1wMDB3ODgyMTMxMzAyMTIN"
3829 "CmxvZ2luMj0NCnBhc3N3b3JkMj0NCnBob25lMz0NCmxvZ2luMz0N"
3830 "CnBhc3N3b3JkMz0NCnBob25lND0NCmxvZ2luND0NCnBhc3N3b3Jk"
3831 "ND0NCnBob25lNT0NCmxvZ2luNT0NCnBhc3N3b3JkNT0NCnBob25l"
3832 "Nj0NCmxvZ2luNj0NCnBhc3N3b3JkNj0NCmNhbGxfdGltZTE9MzIN"
3833 "CmNhbGxfdGltZTI9MjMyDQpkYXlfbGltaXQ9NQ0KbW9udGhfbGlt"
3834 "aXQ9MTUNCltncm91cDJdDQpwaG9uZTE9DQpsb2dpbjE9DQpwYXNz"
3835 "d29yZDE9DQpwaG9uZTI9DQpsb2dpbjI9DQpwYXNzd29yZDI9DQpw"
3836 "aG9uZTM9DQpsb2dpbjM9DQpwYXNzd29yZDM9DQpwaG9uZTQ9DQps"
3837 "b2dpbjQ9DQpwYXNzd29yZDQ9DQpwaG9uZTU9DQpsb2dpbjU9DQpw"
3838 "YXNzd29yZDU9DQpwaG9uZTY9DQpsb2dpbjY9DQpwYXNzd29yZDY9"
3839 "DQpjYWxsX3RpbWUxPQ0KY2FsbF90aW1lMj0NCmRheV9saW1pdD0N"
3840 "Cm1vbnRoX2xpbWl0PQ0KW2dyb3VwM10NCnBob25lMT0NCmxvZ2lu"
3841 "MT0NCnBhc3N3b3JkMT0NCnBob25lMj0NCmxvZ2luMj0NCnBhc3N3"
3842 "b3JkMj0NCnBob25lMz0NCmxvZ2luMz0NCnBhc3N3b3JkMz0NCnBo"
3843 "b25lND0NCmxvZ2luND0NCnBhc3N3b3JkND0NCnBob25lNT0NCmxv"
3844 "Z2luNT0NCnBhc3N3b3JkNT0NCnBob25lNj0NCmxvZ2luNj0NCnBh"
3845 "c3N3b3JkNj0NCmNhbGxfdGltZTE9DQpjYWxsX3RpbWUyPQ0KZGF5"
3846 "X2xpbWl0PQ0KbW9udGhfbGltaXQ9DQpbZ3JvdXA0XQ0KcGhvbmUx"
3847 "PQ0KbG9naW4xPQ0KcGFzc3dvcmQxPQ0KcGhvbmUyPQ0KbG9naW4y"
3848 "PQ0KcGFzc3dvcmQyPQ0KcGhvbmUzPQ0KbG9naW4zPQ0KcGFzc3dv"
3849 "cmQzPQ0KcGhvbmU0PQ0KbG9naW40PQ0KcGFzc3dvcmQ0PQ0KcGhv"
3850 "bmU1PQ0KbG9naW41PQ0KcGFzc3dvcmQ1PQ0KcGhvbmU2PQ0KbG9n"
3851 "aW42PQ0KcGFzc3dvcmQ2PQ0KY2FsbF90aW1lMT0NCmNhbGxfdGlt"
3852 "ZTI9DQpkYXlfbGltaXQ9DQptb250aF9saW1pdD0NCltmaWxlc10N"
3853 "Cmxpbms9aHR0cDovLzIwOS4yMDUuMTk2LjE2L2xkL2dldGJvdC5w"
3854 "aHA=\r\n0\r\n\r\n";
3855 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
3861 memset(&ssn, 0,
sizeof(ssn));
3866 f->
proto = IPPROTO_TCP;
3881 htp_tx_t *tx = HTPStateGetTx(http_state, 0);
3884 FAIL_IF(tx->request_method_number != HTP_M_GET);
3885 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_1);
3887 FAIL_IF(tx->response_status_number != 200);
3888 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_1);
3890 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3901 static int HTPParserTest07(
void)
3905 uint8_t httpbuf1[] =
"GET /awstats.pl?/migratemigrate%20=%20| HTTP/1.0\r\n\r\n";
3906 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3912 memset(&ssn, 0,
sizeof(ssn));
3914 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
3918 f->
proto = IPPROTO_TCP;
3924 for (u = 0; u < httplen1; u++) {
3928 flags = STREAM_TOSERVER|STREAM_START;
3929 else if (u == (httplen1 - 1))
3930 flags = STREAM_TOSERVER|STREAM_EOF;
3932 flags = STREAM_TOSERVER;
3936 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
3943 if (htp_state == NULL) {
3944 printf(
"no http state: ");
3948 uint8_t ref[] =
"/awstats.pl?/migratemigrate = |";
3949 size_t reflen =
sizeof(ref) - 1;
3951 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3957 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
3966 printf(
"normalized uri \"");
3988 static int HTPParserTest08(
void)
3992 uint8_t httpbuf1[] =
"GET /secondhouse/image/js/\%ce\%de\%ce\%fd_RentCity.js?v=2011.05.02 HTTP/1.0\r\n\r\n";
3993 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4015 memset(&ssn, 0,
sizeof(ssn));
4017 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
4021 f->
proto = IPPROTO_TCP;
4027 flags = STREAM_TOSERVER|STREAM_START|STREAM_EOF;
4031 printf(
"toserver chunk returned %" PRId32
", expected"
4038 if (htp_state == NULL) {
4039 printf(
"no http state: ");
4044 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4068 static int HTPParserTest09(
void)
4072 uint8_t httpbuf1[] =
"GET /secondhouse/image/js/\%ce\%de\%ce\%fd_RentCity.js?v=2011.05.02 HTTP/1.0\r\n\r\n";
4073 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4083 personality: Apache_2_2\n\
4096 memset(&ssn, 0,
sizeof(ssn));
4098 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
4102 f->
proto = IPPROTO_TCP;
4108 flags = STREAM_TOSERVER|STREAM_START|STREAM_EOF;
4112 printf(
"toserver chunk returned %" PRId32
", expected"
4118 if (htp_state == NULL) {
4119 printf(
"no http state: ");
4123 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4147 static int HTPParserTest10(
void)
4151 uint8_t httpbuf1[] =
"GET / HTTP/1.0\r\nHost:www.google.com\r\n\r\n";
4152 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4158 memset(&ssn, 0,
sizeof(ssn));
4160 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
4164 f->
proto = IPPROTO_TCP;
4170 for (u = 0; u < httplen1; u++) {
4174 flags = STREAM_TOSERVER|STREAM_START;
4175 else if (u == (httplen1 - 1))
4176 flags = STREAM_TOSERVER|STREAM_EOF;
4178 flags = STREAM_TOSERVER;
4182 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
4189 if (htp_state == NULL) {
4190 printf(
"no http state: ");
4194 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4195 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
4200 char *name = bstr_util_strdup_to_c(h->name);
4205 if (strcmp(name,
"Host") != 0) {
4206 printf(
"header name not \"Host\", instead \"%s\": ", name);
4212 char *value = bstr_util_strdup_to_c(h->value);
4213 if (value == NULL) {
4217 if (strcmp(value,
"www.google.com") != 0) {
4218 printf(
"header value not \"www.google.com\", instead \"%s\": ", value);
4235 static int HTPParserTest11(
void)
4239 uint8_t httpbuf1[] =
"GET /%2500 HTTP/1.0\r\n\r\n";
4240 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4246 memset(&ssn, 0,
sizeof(ssn));
4248 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
4252 f->
proto = IPPROTO_TCP;
4258 for (u = 0; u < httplen1; u++) {
4262 flags = STREAM_TOSERVER|STREAM_START;
4263 else if (u == (httplen1 - 1))
4264 flags = STREAM_TOSERVER|STREAM_EOF;
4266 flags = STREAM_TOSERVER;
4270 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
4277 if (htp_state == NULL) {
4278 printf(
"no http state: ");
4282 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4288 printf(
"normalized uri len should be 2, is %"PRIuMAX,
4298 printf(
"normalized uri \"");
4316 static int HTPParserTest12(
void)
4320 uint8_t httpbuf1[] =
"GET /?a=%2500 HTTP/1.0\r\n\r\n";
4321 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4327 memset(&ssn, 0,
sizeof(ssn));
4329 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
4333 f->
proto = IPPROTO_TCP;
4339 for (u = 0; u < httplen1; u++) {
4343 flags = STREAM_TOSERVER|STREAM_START;
4344 else if (u == (httplen1 - 1))
4345 flags = STREAM_TOSERVER|STREAM_EOF;
4347 flags = STREAM_TOSERVER;
4351 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
4358 if (htp_state == NULL) {
4359 printf(
"no http state: ");
4363 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4369 printf(
"normalized uri len should be 5, is %"PRIuMAX,
4382 printf(
"normalized uri \"");
4400 static int HTPParserTest13(
void)
4404 uint8_t httpbuf1[] =
"GET / HTTP/1.0\r\nHost:www.google.com\rName: Value\r\n\r\n";
4405 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4411 memset(&ssn, 0,
sizeof(ssn));
4413 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
4417 f->
proto = IPPROTO_TCP;
4423 for (u = 0; u < httplen1; u++) {
4427 flags = STREAM_TOSERVER|STREAM_START;
4428 else if (u == (httplen1 - 1))
4429 flags = STREAM_TOSERVER|STREAM_EOF;
4431 flags = STREAM_TOSERVER;
4435 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
4442 if (htp_state == NULL) {
4443 printf(
"no http state: ");
4447 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4448 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
4453 char *name = bstr_util_strdup_to_c(h->name);
4458 if (strcmp(name,
"Host") != 0) {
4459 printf(
"header name not \"Host\", instead \"%s\": ", name);
4465 char *value = bstr_util_strdup_to_c(h->value);
4466 if (value == NULL) {
4470 if (strcmp(value,
"www.google.com\rName: Value") != 0) {
4471 printf(
"header value not \"www.google.com\", instead \"");
4489 static int HTPParserConfigTest01(
void)
4503 address: [192.168.1.0/24, 127.0.0.0/8, \"::1\"]\n\
4504 personality: Tomcat_6_0\n\
4509 - 192.168.10.0/24\n\
4510 personality: IIS_7_0\n\
4519 outputs =
ConfGetNode(
"libhtp.default-config.personality");
4520 if (outputs == NULL) {
4525 if (outputs == NULL) {
4533 if (strcmp(node->
name,
"0") != 0) {
4540 if (strcmp(node->
name,
"apache-tomcat") != 0) {
4548 if (node2 == NULL) {
4551 if (strcmp(node2->
val,
"Tomcat_6_0") != 0) {
4566 if (strcmp(n->
name,
"0") != 0) {
4569 if (strcmp(n->
val,
"192.168.1.0/24") != 0) {
4574 if (strcmp(n->
name,
"1") != 0) {
4577 if (strcmp(n->
val,
"127.0.0.0/8") != 0) {
4582 if (strcmp(n->
name,
"2") != 0) {
4585 if (strcmp(n->
val,
"::1") != 0) {
4596 if (outputs == NULL) {
4605 if (strcmp(node->
name,
"1") != 0) {
4612 if (strcmp(node->
name,
"iis7") != 0) {
4617 if (node2 == NULL) {
4620 if (strcmp(node2->
val,
"IIS_7_0") != 0) {
4637 if (strcmp(n->
name,
"0") != 0) {
4640 if (strcmp(n->
val,
"192.168.0.0/24") != 0) {
4645 if (strcmp(n->
name,
"1") != 0) {
4648 if (strcmp(n->
val,
"192.168.10.0/24") != 0) {
4668 static int HTPParserConfigTest02(
void)
4682 address: [192.168.1.0/24, 127.0.0.0/8, \"::1\"]\n\
4683 personality: Tomcat_6_0\n\
4688 - 192.168.10.0/24\n\
4689 personality: IIS_7_0\n\
4700 if (cfglist.
cfg == NULL) {
4701 printf(
"No default config created.\n");
4705 if (cfgtree == NULL) {
4706 printf(
"No config tree created.\n");
4710 htp_cfg_t *htp = cfglist.
cfg;
4713 void *user_data = NULL;
4715 addr =
"192.168.10.42";
4716 if (inet_pton(AF_INET, addr, buf) == 1) {
4718 if (user_data != NULL) {
4720 htp = htp_cfg_rec->
cfg;
4724 printf(
"Could not get config for: %s\n", addr);
4729 printf(
"Failed to parse address: %s\n", addr);
4735 if (inet_pton(AF_INET6, addr, buf) == 1) {
4737 if (user_data != NULL) {
4739 htp = htp_cfg_rec->
cfg;
4743 printf(
"Could not get config for: %s\n", addr);
4748 printf(
"Failed to parse address: %s\n", addr);
4764 static int HTPParserConfigTest03(
void)
4768 uint8_t httpbuf1[] =
"POST / HTTP/1.0\r\nUser-Agent: Victor/1.0\r\n\r\nPost"
4770 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4787 address: [192.168.1.0/24, 127.0.0.0/8, \"::1\"]\n\
4788 personality: Tomcat_6_0\n\
4793 - 192.168.10.0/24\n\
4794 personality: IIS_7_0\n\
4805 const char *addr =
"192.168.10.42";
4807 memset(&ssn, 0,
sizeof(ssn));
4813 f->
proto = IPPROTO_TCP;
4816 htp_cfg_t *htp = cfglist.
cfg;
4818 void *user_data = NULL;
4820 if (user_data != NULL) {
4822 htp = htp_cfg_rec->
cfg;
4826 printf(
"Could not get config for: %s\n", addr);
4833 for (u = 0; u < httplen1; u++) {
4836 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
4837 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
4838 else flags = STREAM_TOSERVER;
4842 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
4850 if (htp_state == NULL) {
4851 printf(
"no http state: ");
4856 if (HTPStateGetTxCnt(htp_state) != 2) {
4857 printf(
"HTPStateGetTxCnt(htp_state) failure\n");
4861 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4864 if (tx->cfg != htp) {
4865 printf(
"wrong HTP config (%p instead of %p - default=%p): ",
4866 tx->cfg, htp, cfglist.
cfg);
4869 tx = HTPStateGetTx(htp_state, 1);
4872 if (tx->cfg != htp) {
4873 printf(
"wrong HTP config (%p instead of %p - default=%p): ",
4874 tx->cfg, htp, cfglist.
cfg);
4897 static int HTPParserDecodingTest01(
void)
4899 uint8_t httpbuf1[] =
4900 "GET /abc%2fdef HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
4901 "GET /abc/def?ghi%2fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
4902 "GET /abc/def?ghi%252fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
4903 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4914 personality: Apache_2\n\
4922 const char *addr =
"4.3.2.1";
4923 memset(&ssn, 0,
sizeof(ssn));
4928 f->
proto = IPPROTO_TCP;
4933 for (uint32_t u = 0; u < httplen1; u++) {
4935 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
4936 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
4937 else flags = STREAM_TOSERVER;
4946 uint8_t ref1[] =
"/abc%2fdef";
4947 size_t reflen =
sizeof(ref1) - 1;
4949 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4959 uint8_t ref2[] =
"/abc/def?ghi/jkl";
4960 reflen =
sizeof(ref2) - 1;
4962 tx = HTPStateGetTx(htp_state, 1);
4972 uint8_t ref3[] =
"/abc/def?ghi%2fjkl";
4973 reflen =
sizeof(ref3) - 1;
4974 tx = HTPStateGetTx(htp_state, 2);
4995 static int HTPParserDecodingTest01a(
void)
4997 uint8_t httpbuf1[] =
"GET /abc%2fdef HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
4998 "GET /abc/def?ghi%2fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
4999 "GET /abc/def?ghi%252fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5000 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5011 personality: Apache_2\n\
5019 const char *addr =
"4.3.2.1";
5020 memset(&ssn, 0,
sizeof(ssn));
5025 f->
proto = IPPROTO_TCP;
5031 (STREAM_TOSERVER | STREAM_START | STREAM_EOF), httpbuf1, httplen1);
5037 uint8_t ref1[] =
"/abc%2fdef";
5038 size_t reflen =
sizeof(ref1) - 1;
5040 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5050 uint8_t ref2[] =
"/abc/def?ghi/jkl";
5051 reflen =
sizeof(ref2) - 1;
5053 tx = HTPStateGetTx(htp_state, 1);
5063 uint8_t ref3[] =
"/abc/def?ghi%2fjkl";
5064 reflen =
sizeof(ref3) - 1;
5065 tx = HTPStateGetTx(htp_state, 2);
5092 static int HTPParserDecodingTest02(
void)
5096 uint8_t httpbuf1[] =
5097 "GET /abc%2fdef HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
5098 "GET /abc/def?ghi%2fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
5099 "GET /abc/def?ghi%252fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5100 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5113 double-decode-path: no\n\
5114 double-decode-query: no\n\
5122 const char *addr =
"4.3.2.1";
5123 memset(&ssn, 0,
sizeof(ssn));
5129 f->
proto = IPPROTO_TCP;
5135 for (u = 0; u < httplen1; u++) {
5138 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
5139 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
5140 else flags = STREAM_TOSERVER;
5144 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5151 if (htp_state == NULL) {
5152 printf(
"no http state: ");
5156 uint8_t ref1[] =
"/abc/def";
5157 size_t reflen =
sizeof(ref1) - 1;
5159 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5165 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5174 printf(
"normalized uri \"");
5183 uint8_t ref2[] =
"/abc/def?ghi/jkl";
5184 reflen =
sizeof(ref2) - 1;
5186 tx = HTPStateGetTx(htp_state, 1);
5192 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5201 printf(
"normalized uri \"");
5210 uint8_t ref3[] =
"/abc/def?ghi%2fjkl";
5211 reflen =
sizeof(ref3) - 1;
5212 tx = HTPStateGetTx(htp_state, 2);
5218 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX
" (3): ",
5227 printf(
"normalized uri \"");
5256 static int HTPParserDecodingTest03(
void)
5260 uint8_t httpbuf1[] =
5261 "GET /abc%252fdef HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
5262 "GET /abc/def?ghi%252fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5263 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5276 double-decode-path: yes\n\
5277 double-decode-query: yes\n\
5285 const char *addr =
"4.3.2.1";
5286 memset(&ssn, 0,
sizeof(ssn));
5292 f->
proto = IPPROTO_TCP;
5298 for (u = 0; u < httplen1; u++) {
5301 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
5302 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
5303 else flags = STREAM_TOSERVER;
5307 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5314 if (htp_state == NULL) {
5315 printf(
"no http state: ");
5319 uint8_t ref1[] =
"/abc/def";
5320 size_t reflen =
sizeof(ref1) - 1;
5322 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5328 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5337 printf(
"normalized uri \"");
5346 uint8_t ref2[] =
"/abc/def?ghi/jkl";
5347 reflen =
sizeof(ref2) - 1;
5349 tx = HTPStateGetTx(htp_state, 1);
5355 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5364 printf(
"normalized uri \"");
5390 static int HTPParserDecodingTest04(
void)
5394 uint8_t httpbuf1[] =
5395 "GET /abc/def?a=http://www.abc.com/ HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5396 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5409 double-decode-path: yes\n\
5410 double-decode-query: yes\n\
5418 const char *addr =
"4.3.2.1";
5419 memset(&ssn, 0,
sizeof(ssn));
5425 f->
proto = IPPROTO_TCP;
5431 for (u = 0; u < httplen1; u++) {
5434 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
5435 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
5436 else flags = STREAM_TOSERVER;
5440 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5447 if (htp_state == NULL) {
5448 printf(
"no http state: ");
5452 uint8_t ref1[] =
"/abc/def?a=http://www.abc.com/";
5453 size_t reflen =
sizeof(ref1) - 1;
5455 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5461 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5470 printf(
"normalized uri \"");
5496 static int HTPParserDecodingTest05(
void)
5500 uint8_t httpbuf1[] =
5501 "GET /index?id=\\\"<script>alert(document.cookie)</script> HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5502 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5515 double-decode-path: yes\n\
5516 double-decode-query: yes\n\
5524 const char *addr =
"4.3.2.1";
5525 memset(&ssn, 0,
sizeof(ssn));
5531 f->
proto = IPPROTO_TCP;
5537 for (u = 0; u < httplen1; u++) {
5540 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
5541 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
5542 else flags = STREAM_TOSERVER;
5546 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5553 if (htp_state == NULL) {
5554 printf(
"no http state: ");
5558 uint8_t ref1[] =
"/index?id=\\\"<script>alert(document.cookie)</script>";
5559 size_t reflen =
sizeof(ref1) - 1;
5561 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5567 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5576 printf(
"normalized uri \"");
5602 static int HTPParserDecodingTest06(
void)
5606 uint8_t httpbuf1[] =
5607 "GET /put.php?ip=1.2.3.4&port=+6000 HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5608 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5621 double-decode-path: yes\n\
5622 double-decode-query: yes\n\
5630 const char *addr =
"4.3.2.1";
5631 memset(&ssn, 0,
sizeof(ssn));
5637 f->
proto = IPPROTO_TCP;
5643 for (u = 0; u < httplen1; u++) {
5646 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
5647 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
5648 else flags = STREAM_TOSERVER;
5652 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5659 if (htp_state == NULL) {
5660 printf(
"no http state: ");
5664 uint8_t ref1[] =
"/put.php?ip=1.2.3.4&port=+6000";
5665 size_t reflen =
sizeof(ref1) - 1;
5667 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5673 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5682 printf(
"normalized uri \"");
5708 static int HTPParserDecodingTest07(
void)
5712 uint8_t httpbuf1[] =
5713 "GET /put.php?ip=1.2.3.4&port=+6000 HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5714 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5727 double-decode-path: yes\n\
5728 double-decode-query: yes\n\
5729 query-plusspace-decode: yes\n\
5737 const char *addr =
"4.3.2.1";
5738 memset(&ssn, 0,
sizeof(ssn));
5744 f->
proto = IPPROTO_TCP;
5750 for (u = 0; u < httplen1; u++) {
5753 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
5754 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
5755 else flags = STREAM_TOSERVER;
5759 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5766 if (htp_state == NULL) {
5767 printf(
"no http state: ");
5771 uint8_t ref1[] =
"/put.php?ip=1.2.3.4&port= 6000";
5772 size_t reflen =
sizeof(ref1) - 1;
5774 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5780 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5789 printf(
"normalized uri \"");
5815 static int HTPParserDecodingTest08(
void)
5819 uint8_t httpbuf1[] =
5820 "GET http://suricata-ids.org/blah/ HTTP/1.1\r\nHost: suricata-ids.org\r\n\r\n";
5821 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5841 const char *addr =
"4.3.2.1";
5842 memset(&ssn, 0,
sizeof(ssn));
5848 f->
proto = IPPROTO_TCP;
5854 for (u = 0; u < httplen1; u++) {
5857 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
5858 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
5859 else flags = STREAM_TOSERVER;
5863 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5870 if (htp_state == NULL) {
5871 printf(
"no http state: ");
5875 uint8_t ref1[] =
"/blah/";
5876 size_t reflen =
sizeof(ref1) - 1;
5878 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5884 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5893 printf(
"normalized uri \"");
5919 static int HTPParserDecodingTest09(
void)
5923 uint8_t httpbuf1[] =
5924 "GET http://suricata-ids.org/blah/ HTTP/1.1\r\nHost: suricata-ids.org\r\n\r\n";
5925 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5938 uri-include-all: true\n\
5946 const char *addr =
"4.3.2.1";
5947 memset(&ssn, 0,
sizeof(ssn));
5953 f->
proto = IPPROTO_TCP;
5959 for (u = 0; u < httplen1; u++) {
5962 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
5963 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
5964 else flags = STREAM_TOSERVER;
5968 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5975 if (htp_state == NULL) {
5976 printf(
"no http state: ");
5980 uint8_t ref1[] =
"http://suricata-ids.org/blah/";
5981 size_t reflen =
sizeof(ref1) - 1;
5983 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5989 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5998 printf(
"normalized uri \"");
6023 static int HTPBodyReassemblyTest01(
void)
6027 memset(&htud, 0x00,
sizeof(htud));
6029 memset(&hstate, 0x00,
sizeof(hstate));
6031 memset(&flow, 0x00,
sizeof(flow));
6034 memset(&tx, 0,
sizeof(tx));
6039 uint8_t chunk1[] =
"--e5a320f21416a02493a0a6f561b1c494\r\nContent-Disposition: form-data; name=\"uploadfile\"; filename=\"D2GUef.jpg\"\r";
6040 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";
6047 const uint8_t *chunks_buffer = NULL;
6048 uint32_t chunks_buffer_len = 0;
6050 HtpRequestBodyReassemble(&htud, &chunks_buffer, &chunks_buffer_len);
6051 if (chunks_buffer == NULL) {
6055 printf(
"REASSCHUNK START: \n");
6057 printf(
"REASSCHUNK END: \n");
6060 HtpRequestBodyHandleMultipart(&hstate, &htud, &tx, chunks_buffer, chunks_buffer_len);
6075 static int HTPSegvTest01(
void)
6079 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";
6080 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
6088 double-decode-path: no\n\
6089 double-decode-query: no\n\
6090 request-body-limit: 0\n\
6091 response-body-limit: 0\n\
6104 memset(&ssn, 0,
sizeof(ssn));
6106 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
6110 f->
proto = IPPROTO_TCP;
6115 SCLogDebug(
"\n>>>> processing chunk 1 <<<<\n");
6119 printf(
"toserver chunk 1 returned %" PRId32
", expected 0: ", r);
6122 SCLogDebug(
"\n>>>> processing chunk 1 again <<<<\n");
6125 printf(
"toserver chunk 1 returned %" PRId32
", expected 0: ", r);
6130 if (http_state == NULL) {
6131 printf(
"no http state: ");
6136 if (decoder_events != NULL) {
6137 printf(
"app events: ");
6154 static int HTPParserTest14(
void)
6165 double-decode-path: no\n\
6166 double-decode-query: no\n\
6167 request-body-limit: 0\n\
6168 response-body-limit: 0\n\
6173 memset(&ssn, 0,
sizeof(ssn));
6183 memset(httpbuf, 0x00,
len);
6186 strlcpy(httpbuf,
"GET /blah/ HTTP/1.1\r\n"
6187 "Host: myhost.lan\r\n"
6188 "Connection: keep-alive\r\n"
6190 "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"
6191 "Referer: http://blah.lan/\r\n"
6192 "Accept-Encoding: gzip,deflate,sdch\r\nAccept-Language: en-US,en;q=0.8\r\n"
6194 size_t o = strlen(httpbuf);
6195 for ( ; o <
len - 4; o++) {
6198 httpbuf[
len - 4] =
'\r';
6199 httpbuf[
len - 3] =
'\n';
6200 httpbuf[
len - 2] =
'\r';
6201 httpbuf[
len - 1] =
'\n';
6207 f->
proto = IPPROTO_TCP;
6212 for (u = 0; u <
len; u++) {
6215 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
6216 else if (u == (
len - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
6217 else flags = STREAM_TOSERVER;
6225 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
6227 FAIL_IF(tx->request_method_number != HTP_M_GET);
6228 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_1);
6250 static int HTPParserTest15(
void)
6254 char *httpbuf = NULL;
6266 double-decode-path: no\n\
6267 double-decode-query: no\n\
6268 request-body-limit: 0\n\
6269 response-body-limit: 0\n\
6270 meta-field-limit: 20000\n\
6274 memset(&ssn, 0,
sizeof(ssn));
6285 memset(httpbuf, 0x00,
len);
6288 strlcpy(httpbuf,
"GET /blah/ HTTP/1.1\r\n"
6289 "Host: myhost.lan\r\n"
6290 "Connection: keep-alive\r\n"
6292 "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"
6293 "Referer: http://blah.lan/\r\n"
6294 "Accept-Encoding: gzip,deflate,sdch\r\nAccept-Language: en-US,en;q=0.8\r\n"
6296 size_t o = strlen(httpbuf);
6297 for ( ; o <
len - 4; o++) {
6300 httpbuf[
len - 4] =
'\r';
6301 httpbuf[
len - 3] =
'\n';
6302 httpbuf[
len - 2] =
'\r';
6303 httpbuf[
len - 1] =
'\n';
6305 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
6309 f->
proto = IPPROTO_TCP;
6315 for (u = 0; u <
len; u++) {
6318 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
6319 else if (u == (
len - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
6320 else flags = STREAM_TOSERVER;
6324 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
6330 if (htp_state == NULL) {
6331 printf(
"no http state: ");
6335 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
6336 if (tx == NULL || tx->request_method_number != HTP_M_GET || tx->request_protocol_number != HTP_PROTOCOL_1_1)
6338 printf(
"expected method M_GET and got %s: , expected protocol "
6339 "HTTP/1.1 and got %s \n", bstr_util_strdup_to_c(tx->request_method),
6340 bstr_util_strdup_to_c(tx->request_protocol));
6347 if (decoder_events != NULL) {
6348 printf(
"app events: ");
6358 if (httpbuf != NULL)
6368 static int HTPParserTest16(
void)
6377 memset(&ssn, 0,
sizeof(ssn));
6379 uint8_t httpbuf[] =
"GET\f/blah/\fHTTP/1.1\r\n"
6380 "Host: myhost.lan\r\n"
6381 "Connection: keep-alive\r\n"
6383 "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"
6384 "Referer: http://blah.lan/\r\n"
6385 "Accept-Encoding: gzip,deflate,sdch\r\nAccept-Language: en-US,en;q=0.8\r\n"
6386 "Cookie: blah\r\n\r\n";
6387 size_t len =
sizeof(httpbuf) - 1;
6389 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
6393 f->
proto = IPPROTO_TCP;
6398 uint8_t
flags = STREAM_TOSERVER|STREAM_START|STREAM_EOF;
6402 printf(
"toserver chunk 1 returned %" PRId32
", expected 0: ", r);
6407 if (htp_state == NULL) {
6408 printf(
"no http state: ");
6412 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
6413 if (tx == NULL || tx->request_method_number != HTP_M_GET || tx->request_protocol_number != HTP_PROTOCOL_1_1)
6415 printf(
"expected method M_GET and got %s: , expected protocol "
6416 "HTTP/1.1 and got %s \n", tx ? bstr_util_strdup_to_c(tx->request_method) :
"tx null",
6417 tx ? bstr_util_strdup_to_c(tx->request_protocol) :
"tx null");
6421 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
6426 if (decoder_events == NULL) {
6427 printf(
"no app events: ");
6432 printf(
"HTTP_DECODER_EVENT_METHOD_DELIM_NON_COMPLIANT not set: ");
6437 printf(
"HTTP_DECODER_EVENT_URI_DELIM_NON_COMPLIANT not set: ");
6453 static int HTPParserTest20(
void)
6456 uint8_t httpbuf1[] =
"GET /ld/index.php?id=412784631&cid=0064&version=4&"
6457 "name=try HTTP/1.1\r\nAccept: */*\r\nUser-Agent: "
6458 "LD-agent\r\nHost: 209.205.196.16\r\n\r\n";
6459 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
6460 uint8_t httpbuf2[] =
"NOTHTTP\r\nSOMEOTHERDATA";
6461 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
6462 uint8_t httpbuf3[] =
"STILLNOTHTTP\r\nSOMEMOREOTHERDATA";
6463 uint32_t httplen3 =
sizeof(httpbuf3) - 1;
6469 memset(&ssn, 0,
sizeof(ssn));
6471 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
6474 f->
proto = IPPROTO_TCP;
6493 htp_tx_t *tx = HTPStateGetTx(http_state, 0);
6495 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
6498 FAIL_IF(tx->request_method_number != HTP_M_GET);
6499 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_1);
6501 FAIL_IF(tx->response_status_number != 0);
6502 FAIL_IF(tx->response_protocol_number != -1);
6512 static int HTPParserTest21(
void)
6515 uint8_t httpbuf1[] =
"GET /ld/index.php?id=412784631&cid=0064&version=4&"
6516 "name=try HTTP/1.1\r\nAccept: */*\r\nUser-Agent: "
6517 "LD-agent\r\nHost: 209.205.196.16\r\n\r\n";
6518 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
6519 uint8_t httpbuf2[] =
"999 NOTHTTP REALLY\r\nSOMEOTHERDATA\r\n";
6520 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
6521 uint8_t httpbuf3[] =
"STILLNOTHTTP\r\nSOMEMOREOTHERDATA";
6522 uint32_t httplen3 =
sizeof(httpbuf3) - 1;
6528 memset(&ssn, 0,
sizeof(ssn));
6530 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
6533 f->
proto = IPPROTO_TCP;
6552 htp_tx_t *tx = HTPStateGetTx(http_state, 0);
6554 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
6557 FAIL_IF(tx->request_method_number != HTP_M_GET);
6558 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_1);
6560 FAIL_IF(tx->response_status_number != 0);
6561 FAIL_IF(tx->response_protocol_number != -1);
6571 static int HTPParserTest22(
void)
6574 uint8_t httpbuf1[] =
"GET /ld/index.php?id=412784631&cid=0064&version=4&"
6575 "name=try HTTP/1.1\r\nAccept: */*\r\nUser-Agent: "
6576 "LD-agent\r\nHost: 209.205.196.16\r\n\r\n";
6577 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
6578 uint8_t httpbuf2[] =
"\r\n0000=0000000/ASDF3_31.zip, 456723\r\n"
6579 "AAAAAA_0000=0000000/AAAAAAAA.zip,46725\r\n";
6580 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
6586 memset(&ssn, 0,
sizeof(ssn));
6588 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
6591 f->
proto = IPPROTO_TCP;
6606 htp_tx_t *tx = HTPStateGetTx(http_state, 0);
6608 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
6611 FAIL_IF(tx->request_method_number != HTP_M_GET);
6612 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_1);
6614 FAIL_IF(tx->response_status_number != -0);
6615 FAIL_IF(tx->response_protocol_number != -1);
6625 static int HTPParserTest23(
void)
6628 uint8_t httpbuf1[] =
"GET /ld/index.php?id=412784631&cid=0064&version=4&"
6629 "name=try HTTP/1.1\r\nAccept: */*\r\nUser-Agent: "
6630 "LD-agent\r\nHost: 209.205.196.16\r\n\r\n";
6631 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
6632 uint8_t httpbuf2[] =
"HTTP0000=0000000/ASDF3_31.zip, 456723\r\n"
6633 "AAAAAA_0000=0000000/AAAAAAAA.zip,46725\r\n";
6634 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
6640 memset(&ssn, 0,
sizeof(ssn));
6642 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
6645 f->
proto = IPPROTO_TCP;
6660 htp_tx_t *tx = HTPStateGetTx(http_state, 0);
6662 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
6665 FAIL_IF(tx->request_method_number != HTP_M_GET);
6666 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_1);
6668 FAIL_IF(tx->response_status_number != -1);
6669 FAIL_IF(tx->response_protocol_number != -2);
6679 static int HTPParserTest24(
void)
6682 uint8_t httpbuf1[] =
"GET /ld/index.php?id=412784631&cid=0064&version=4&"
6683 "name=try HTTP/1.1\r\nAccept: */*\r\nUser-Agent: "
6684 "LD-agent\r\nHost: 209.205.196.16\r\n\r\n";
6685 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
6686 uint8_t httpbuf2[] =
"HTTP/1.0 0000=0000000/ASDF3_31.zip, 456723\r\n"
6687 "AAAAAA_0000=0000000/AAAAAAAA.zip,46725\r\n";
6688 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
6694 memset(&ssn, 0,
sizeof(ssn));
6696 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
6699 f->
proto = IPPROTO_TCP;
6714 htp_tx_t *tx = HTPStateGetTx(http_state, 0);
6716 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
6719 FAIL_IF(tx->request_method_number != HTP_M_GET);
6720 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_1);
6722 FAIL_IF(tx->response_status_number != -1);
6723 FAIL_IF(tx->response_protocol_number != HTP_PROTOCOL_1_0);
6732 static int HTPParserTest25(
void)
6739 memset(&ssn, 0,
sizeof(ssn));
6744 f->
proto = IPPROTO_TCP;
6747 const char *
str =
"GET / HTTP/1.1\r\nHost: www.google.com\r\nUser-Agent: Suricata/1.0\r\n\r\n";
6749 (uint8_t *)
str, strlen(
str));
6773 str =
"HTTP 1.1 200 OK\r\nServer: Suricata/1.0\r\nContent-Length: 8\r\n\r\nSuricata";
6775 (uint8_t *)
str, strlen(
str));
6809 (uint8_t *)
str, strlen(
str));
6820 (uint8_t *)
str, strlen(
str));
6840 static int HTPParserTest26(
void)
6849 request-body-limit: 1\n\
6850 response-body-limit: 1\n\
6864 uint8_t httpbuf1[] =
"GET /alice.txt HTTP/1.1\r\n\r\n";
6865 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
6866 uint8_t httpbuf2[] =
"HTTP/1.1 200 OK\r\n"
6867 "Content-Type: text/plain\r\n"
6868 "Content-Length: 228\r\n\r\n"
6869 "Alice was beginning to get very tired of sitting by her sister on the bank."
6870 "Alice was beginning to get very tired of sitting by her sister on the bank.";
6871 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
6872 uint8_t httpbuf3[] =
"Alice was beginning to get very tired of sitting by her sister on the bank.\r\n\r\n";
6873 uint32_t httplen3 =
sizeof(httpbuf3) - 1;
6879 memset(&th_v, 0,
sizeof(th_v));
6880 memset(&f, 0,
sizeof(f));
6881 memset(&ssn, 0,
sizeof(ssn));
6888 f.
proto = IPPROTO_TCP;
6909 "(filestore; sid:1; rev:1;)");
6954 AppLayerGetFileState files = HTPGetTxFiles(http_state, tx_ptr, STREAM_TOCLIENT);
6976 static int HTPParserTest27(
void)
6979 memset(&cfg, 0,
sizeof(cfg));
6983 uint32_t
len = 1000;
7008 static void HTPParserRegisterTests(
void)
7030 UtRegisterTest(
"HTPParserDecodingTest01", HTPParserDecodingTest01);
7031 UtRegisterTest(
"HTPParserDecodingTest01a", HTPParserDecodingTest01a);
7032 UtRegisterTest(
"HTPParserDecodingTest02", HTPParserDecodingTest02);
7033 UtRegisterTest(
"HTPParserDecodingTest03", HTPParserDecodingTest03);
7034 UtRegisterTest(
"HTPParserDecodingTest04", HTPParserDecodingTest04);
7035 UtRegisterTest(
"HTPParserDecodingTest05", HTPParserDecodingTest05);
7036 UtRegisterTest(
"HTPParserDecodingTest06", HTPParserDecodingTest06);
7037 UtRegisterTest(
"HTPParserDecodingTest07", HTPParserDecodingTest07);
7038 UtRegisterTest(
"HTPParserDecodingTest08", HTPParserDecodingTest08);
7039 UtRegisterTest(
"HTPParserDecodingTest09", HTPParserDecodingTest09);
7041 UtRegisterTest(
"HTPBodyReassemblyTest01", HTPBodyReassemblyTest01);