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);
2524 htp_config_set_plusspace_decode(cfg_prec->
cfg, HTP_DECODER_URLENCODED, 0);
2526 htp_config_set_request_decompression(cfg_prec->
cfg, 1);
2527 #ifdef HAVE_HTP_CONFIG_SET_LZMA_LAYERS
2531 #ifdef HAVE_HTP_CONFIG_SET_LZMA_MEMLIMIT
2532 htp_config_set_lzma_memlimit(cfg_prec->
cfg,
2535 #ifdef HAVE_HTP_CONFIG_SET_COMPRESSION_BOMB_LIMIT
2536 htp_config_set_compression_bomb_limit(cfg_prec->
cfg,
2539 #ifdef HAVE_HTP_CONFIG_SET_COMPRESSION_TIME_LIMIT
2542 #ifdef HAVE_HTP_CONFIG_SET_MAX_TX
2543 #define HTP_CONFIG_DEFAULT_MAX_TX_LIMIT 512
2544 htp_config_set_max_tx(cfg_prec->
cfg, HTP_CONFIG_DEFAULT_MAX_TX_LIMIT);
2552 htp_config_set_field_limits(cfg_prec->
cfg,
2561 static int RandomGetWrap(
void)
2567 }
while(r >= ULONG_MAX - (ULONG_MAX % RAND_MAX));
2569 return r % RAND_MAX;
2578 static void HTPConfigSetDefaultsPhase2(
const char *name,
HTPCfgRec *cfg_prec)
2584 long int r = RandomGetWrap();
2586 ((
double)r / RAND_MAX - 0.5) * rdrange / 100);
2588 r = RandomGetWrap();
2590 ((
double)r / RAND_MAX - 0.5) * rdrange / 100);
2591 SCLogConfig(
"'%s' server has 'request-body-minimal-inspect-size' set to"
2592 " %u and 'request-body-inspect-window' set to %u after"
2596 r = RandomGetWrap();
2598 ((
double)r / RAND_MAX - 0.5) * rdrange / 100);
2600 r = RandomGetWrap();
2602 ((
double)r / RAND_MAX - 0.5) * rdrange / 100);
2604 SCLogConfig(
"'%s' server has 'response-body-minimal-inspect-size' set to"
2605 " %u and 'response-body-inspect-window' set to %u after"
2610 htp_config_register_request_line(cfg_prec->
cfg, HTPCallbackRequestLine);
2617 if (cfg_prec == NULL || s == NULL || tree == NULL)
2625 if (strcasecmp(
"address", p->
name) == 0) {
2633 if (strchr(pval->
val,
':') != NULL) {
2634 SCLogDebug(
"LIBHTP adding ipv6 server %s at %s: %p",
2638 "add ipv6 server %s, ignoring",
2642 SCLogDebug(
"LIBHTP adding ipv4 server %s at %s: %p",
2646 "to add ipv4 server %s, ignoring",
2652 }
else if (strcasecmp(
"personality", p->
name) == 0) {
2654 int personality = HTPLookupPersonality(p->
val);
2658 if (personality >= 0) {
2661 if (htp_config_set_server_personality(cfg_prec->
cfg, personality) == HTP_ERROR){
2663 "personality \"%s\", ignoring",
2667 HTPLookupPersonalityString(personality));
2673 htp_config_set_convert_lowercase(cfg_prec->
cfg, HTP_DECODER_URL_PATH, 0);
2681 }
else if (strcasecmp(
"request-body-limit", p->
name) == 0 ||
2682 strcasecmp(
"request_body_limit", p->
name) == 0) {
2684 SCLogError(
"Error parsing request-body-limit "
2685 "from conf file - %s. Killing engine",
2690 }
else if (strcasecmp(
"response-body-limit", p->
name) == 0) {
2692 SCLogError(
"Error parsing response-body-limit "
2693 "from conf file - %s. Killing engine",
2698 }
else if (strcasecmp(
"request-body-minimal-inspect-size", p->
name) == 0) {
2700 SCLogError(
"Error parsing request-body-minimal-inspect-size "
2701 "from conf file - %s. Killing engine",
2706 }
else if (strcasecmp(
"request-body-inspect-window", p->
name) == 0) {
2708 SCLogError(
"Error parsing request-body-inspect-window "
2709 "from conf file - %s. Killing engine",
2714 }
else if (strcasecmp(
"double-decode-query", p->
name) == 0) {
2716 htp_config_register_request_line(cfg_prec->
cfg,
2717 HTPCallbackDoubleDecodeQuery);
2720 }
else if (strcasecmp(
"double-decode-path", p->
name) == 0) {
2722 htp_config_register_request_line(cfg_prec->
cfg,
2723 HTPCallbackDoubleDecodePath);
2726 }
else if (strcasecmp(
"response-body-minimal-inspect-size", p->
name) == 0) {
2728 SCLogError(
"Error parsing response-body-minimal-inspect-size "
2729 "from conf file - %s. Killing engine",
2734 }
else if (strcasecmp(
"response-body-inspect-window", p->
name) == 0) {
2736 SCLogError(
"Error parsing response-body-inspect-window "
2737 "from conf file - %s. Killing engine",
2742 }
else if (strcasecmp(
"response-body-decompress-layer-limit", p->
name) == 0) {
2745 SCLogError(
"Error parsing response-body-inspect-window "
2746 "from conf file - %s. Killing engine",
2750 #ifdef HAVE_HTP_CONFIG_SET_RESPONSE_DECOMPRESSION_LAYER_LIMIT
2751 htp_config_set_response_decompression_layer_limit(cfg_prec->
cfg, value);
2753 SCLogWarning(
"can't set response-body-decompress-layer-limit "
2754 "to %u, libhtp version too old",
2757 }
else if (strcasecmp(
"path-convert-backslash-separators", p->
name) == 0) {
2758 htp_config_set_backslash_convert_slashes(cfg_prec->
cfg,
2759 HTP_DECODER_URL_PATH,
2761 }
else if (strcasecmp(
"path-bestfit-replacement-char", p->
name) == 0) {
2762 if (strlen(p->
val) == 1) {
2763 htp_config_set_bestfit_replacement_byte(cfg_prec->
cfg,
2764 HTP_DECODER_URL_PATH,
2768 "for libhtp param path-bestfit-replacement-char");
2770 }
else if (strcasecmp(
"path-convert-lowercase", p->
name) == 0) {
2771 htp_config_set_convert_lowercase(cfg_prec->
cfg,
2772 HTP_DECODER_URL_PATH,
2774 }
else if (strcasecmp(
"path-nul-encoded-terminates", p->
name) == 0) {
2775 htp_config_set_nul_encoded_terminates(cfg_prec->
cfg,
2776 HTP_DECODER_URL_PATH,
2778 }
else if (strcasecmp(
"path-nul-raw-terminates", p->
name) == 0) {
2779 htp_config_set_nul_raw_terminates(cfg_prec->
cfg,
2780 HTP_DECODER_URL_PATH,
2782 }
else if (strcasecmp(
"path-separators-compress", p->
name) == 0) {
2783 htp_config_set_path_separators_compress(cfg_prec->
cfg,
2784 HTP_DECODER_URL_PATH,
2786 }
else if (strcasecmp(
"path-separators-decode", p->
name) == 0) {
2787 htp_config_set_path_separators_decode(cfg_prec->
cfg,
2788 HTP_DECODER_URL_PATH,
2790 }
else if (strcasecmp(
"path-u-encoding-decode", p->
name) == 0) {
2791 htp_config_set_u_encoding_decode(cfg_prec->
cfg,
2792 HTP_DECODER_URL_PATH,
2794 }
else if (strcasecmp(
"path-url-encoding-invalid-handling", p->
name) == 0) {
2795 enum htp_url_encoding_handling_t handling;
2796 if (strcasecmp(p->
val,
"preserve_percent") == 0) {
2797 handling = HTP_URL_DECODE_PRESERVE_PERCENT;
2798 }
else if (strcasecmp(p->
val,
"remove_percent") == 0) {
2799 handling = HTP_URL_DECODE_REMOVE_PERCENT;
2800 }
else if (strcasecmp(p->
val,
"decode_invalid") == 0) {
2801 handling = HTP_URL_DECODE_PROCESS_INVALID;
2804 "for libhtp param path-url-encoding-invalid-handling");
2807 htp_config_set_url_encoding_invalid_handling(cfg_prec->
cfg,
2808 HTP_DECODER_URL_PATH,
2810 }
else if (strcasecmp(
"path-utf8-convert-bestfit", p->
name) == 0) {
2811 htp_config_set_utf8_convert_bestfit(cfg_prec->
cfg,
2812 HTP_DECODER_URL_PATH,
2814 }
else if (strcasecmp(
"uri-include-all", p->
name) == 0) {
2818 }
else if (strcasecmp(
"query-plusspace-decode", p->
name) == 0) {
2819 htp_config_set_plusspace_decode(cfg_prec->
cfg,
2820 HTP_DECODER_URLENCODED,
2822 }
else if (strcasecmp(
"meta-field-limit", p->
name) == 0) {
2826 "from conf file - %s. Killing engine",
2832 "from conf file cannot be 0. Killing engine");
2835 htp_config_set_field_limits(cfg_prec->
cfg,
2838 #ifdef HAVE_HTP_CONFIG_SET_LZMA_MEMLIMIT
2839 }
else if (strcasecmp(
"lzma-memlimit", p->
name) == 0) {
2842 FatalError(
"failed to parse 'lzma-memlimit' "
2843 "from conf file - %s.",
2848 "from conf file cannot be 0.");
2851 SCLogConfig(
"Setting HTTP LZMA memory limit to %"PRIu32
" bytes", limit);
2852 htp_config_set_lzma_memlimit(cfg_prec->
cfg, (
size_t)limit);
2854 #ifdef HAVE_HTP_CONFIG_SET_LZMA_LAYERS
2855 }
else if (strcasecmp(
"lzma-enabled", p->
name) == 0) {
2857 htp_config_set_lzma_layers(cfg_prec->
cfg, 1);
2862 "from conf file - %s.",
2865 SCLogConfig(
"Setting HTTP LZMA decompression layers to %" PRIu32
"", (
int)limit);
2866 htp_config_set_lzma_layers(cfg_prec->
cfg, limit);
2869 #ifdef HAVE_HTP_CONFIG_SET_COMPRESSION_BOMB_LIMIT
2870 }
else if (strcasecmp(
"compression-bomb-limit", p->
name) == 0) {
2873 FatalError(
"failed to parse 'compression-bomb-limit' "
2874 "from conf file - %s.",
2879 "from conf file cannot be 0.");
2882 SCLogConfig(
"Setting HTTP compression bomb limit to %"PRIu32
" bytes", limit);
2883 htp_config_set_compression_bomb_limit(cfg_prec->
cfg, (
size_t)limit);
2885 #ifdef HAVE_HTP_CONFIG_SET_COMPRESSION_TIME_LIMIT
2886 }
else if (strcasecmp(
"decompression-time-limit", p->
name) == 0) {
2890 FatalError(
"failed to parse 'decompression-time-limit' "
2891 "from conf file - %s.",
2894 SCLogConfig(
"Setting HTTP decompression time limit to %" PRIu32
" usec", limit);
2895 htp_config_set_compression_time_limit(cfg_prec->
cfg, (
size_t)limit);
2897 #ifdef HAVE_HTP_CONFIG_SET_MAX_TX
2898 }
else if (strcasecmp(
"max-tx", p->
name) == 0) {
2902 "from conf file - %s.",
2906 SCLogConfig(
"Setting HTTP max-tx limit to %" PRIu32
" bytes", limit);
2907 htp_config_set_max_tx(cfg_prec->
cfg, (
size_t)limit);
2909 }
else if (strcasecmp(
"randomize-inspection-sizes", p->
name) == 0) {
2913 }
else if (strcasecmp(
"randomize-inspection-range", p->
name) == 0) {
2916 (
const char *)p->
val, 0, 100) < 0) {
2918 "-inspection-range setting from conf file - \"%s\"."
2919 " It should be a valid integer less than or equal to 100."
2925 }
else if (strcasecmp(
"http-body-inline", p->
name) == 0) {
2931 if (strcmp(
"auto", p->
val) != 0) {
2940 }
else if (strcasecmp(
"swf-decompression", p->
name) == 0) {
2944 if (strcasecmp(
"enabled", pval->
name) == 0) {
2952 }
else if (strcasecmp(
"type", pval->
name) == 0) {
2953 if (strcasecmp(
"no", pval->
val) == 0) {
2955 }
else if (strcasecmp(
"deflate", pval->
val) == 0) {
2957 }
else if (strcasecmp(
"lzma", pval->
val) == 0) {
2959 }
else if (strcasecmp(
"both", pval->
val) == 0) {
2963 "swf-decompression.type: %s - "
2968 }
else if (strcasecmp(
"compress-depth", pval->
name) == 0) {
2970 SCLogError(
"Error parsing swf-decompression.compression-depth "
2971 "from conf file - %s. Killing engine",
2975 }
else if (strcasecmp(
"decompress-depth", pval->
name) == 0) {
2977 SCLogError(
"Error parsing swf-decompression.decompression-depth "
2978 "from conf file - %s. Killing engine",
2988 "default config: %s",
3000 cfglist.
next = NULL;
3007 if (NULL == cfgtree)
3011 cfglist.
cfg = htp_config_create();
3012 if (NULL == cfglist.
cfg) {
3013 FatalError(
"Failed to create HTP default config");
3016 HTPConfigSetDefaultsPhase1(&cfglist);
3017 if (
ConfGetNode(
"app-layer.protocols.http.libhtp") == NULL) {
3018 HTPConfigParseParameters(&cfglist,
ConfGetNode(
"libhtp.default-config"),
3021 HTPConfigParseParameters(&cfglist,
ConfGetNode(
"app-layer.protocols.http.libhtp.default-config"), cfgtree);
3023 HTPConfigSetDefaultsPhase2(
"default", &cfglist);
3029 if (server_config == NULL) {
3030 server_config =
ConfGetNode(
"libhtp.server-config");
3031 if (server_config == NULL) {
3032 SCLogDebug(
"LIBHTP Configuring %p", server_config);
3036 SCLogDebug(
"LIBHTP Configuring %p", server_config);
3055 cfglist.
next = htprec;
3058 cfglist.
next->
cfg = htp_config_create();
3059 if (NULL == cfglist.
next->
cfg) {
3060 FatalError(
"Failed to create HTP server config");
3063 HTPConfigSetDefaultsPhase1(htprec);
3064 HTPConfigParseParameters(htprec, s, cfgtree);
3065 HTPConfigSetDefaultsPhase2(s->
name, htprec);
3075 SCLogPerf(
"htp memory %"PRIu64
" (%"PRIu64
")", htp_state_memuse, htp_state_memcnt);
3086 static AppLayerGetFileState HTPGetTxFiles(
void *state,
void *txv, uint8_t direction)
3088 AppLayerGetFileState files = { .fc = NULL, .cfg = &
htp_sbcfg };
3089 htp_tx_t *tx = (htp_tx_t *)txv;
3092 if (direction & STREAM_TOCLIENT) {
3101 static int HTPStateGetAlstateProgress(
void *tx, uint8_t direction)
3103 if (direction & STREAM_TOSERVER)
3104 return ((htp_tx_t *)tx)->request_progress;
3106 return ((htp_tx_t *)tx)->response_progress;
3109 static uint64_t HTPStateGetTxCnt(
void *alstate)
3113 if (http_state != NULL && http_state->
conn != NULL) {
3114 const int64_t size = (int64_t)htp_list_size(http_state->
conn->transactions);
3118 return (uint64_t)size + http_state->
tx_freed;
3124 static void *HTPStateGetTx(
void *alstate, uint64_t tx_id)
3128 if (http_state != NULL && http_state->
conn != NULL && tx_id >= http_state->
tx_freed)
3129 return htp_list_get(http_state->
conn->transactions, tx_id - http_state->
tx_freed);
3138 if (http_state != NULL && http_state->
conn != NULL) {
3139 size_t txid = HTPStateGetTxCnt(http_state);
3141 return htp_list_get(http_state->
conn->transactions, txid - http_state->
tx_freed - 1);
3147 static int HTPStateGetEventInfo(
const char *event_name,
3148 int *event_id, AppLayerEventType *event_type)
3151 if (*event_id == -1) {
3153 "http's enum map table.",
3159 *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
3164 static int HTPStateGetEventInfoById(
int event_id,
const char **event_name,
3165 AppLayerEventType *event_type)
3168 if (*event_name == NULL) {
3170 "http's enum map table.",
3176 *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
3183 htp_tx_t *tx = (htp_tx_t *)vtx;
3191 static AppLayerStateData *HTPGetStateData(
void *vstate)
3197 static int HTPRegisterPatternsForProtocolDetection(
void)
3199 const char *methods[] = {
"GET",
"PUT",
"POST",
"HEAD",
"TRACE",
"OPTIONS",
3200 "CONNECT",
"DELETE",
"PATCH",
"PROPFIND",
"PROPPATCH",
"MKCOL",
3201 "COPY",
"MOVE",
"LOCK",
"UNLOCK",
"CHECKOUT",
"UNCHECKOUT",
"CHECKIN",
3202 "UPDATE",
"LABEL",
"REPORT",
"MKWORKSPACE",
"MKACTIVITY",
"MERGE",
3203 "INVALID",
"VERSION-CONTROL",
"BASELINE-CONTROL", NULL};
3204 const char *spacings[] = {
"|20|",
"|09|", NULL };
3205 const char *versions[] = {
"HTTP/0.9",
"HTTP/1.0",
"HTTP/1.1", NULL };
3210 int register_result;
3211 char method_buffer[32] =
"";
3214 for (methods_pos = 0; methods[methods_pos]; methods_pos++) {
3215 for (spacings_pos = 0; spacings[spacings_pos]; spacings_pos++) {
3218 snprintf(method_buffer,
sizeof(method_buffer),
"%s%s", methods[methods_pos], spacings[spacings_pos]);
3225 method_buffer, (uint16_t)strlen(method_buffer) - 3, 0, STREAM_TOSERVER);
3226 if (register_result < 0) {
3233 for (versions_pos = 0; versions[versions_pos]; versions_pos++) {
3235 versions[versions_pos], (uint16_t)strlen(versions[versions_pos]), 0,
3237 if (register_result < 0) {
3253 const char *proto_name =
"http";
3258 if (HTPRegisterPatternsForProtocolDetection() < 0)
3261 SCLogInfo(
"Protocol detection and parser disabled for %s protocol",
3276 ALPROTO_HTTP1, HTP_REQUEST_COMPLETE, HTP_RESPONSE_COMPLETE);
3288 IPPROTO_TCP,
ALPROTO_HTTP1, STREAM_TOSERVER, HTPHandleRequestData);
3290 IPPROTO_TCP,
ALPROTO_HTTP1, STREAM_TOCLIENT, HTPHandleResponseData);
3296 IPPROTO_TCP,
ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_TOCLIENT);
3299 IPPROTO_TCP,
ALPROTO_HTTP1, HTTPGetFrameIdByName, HTTPGetFrameNameById);
3303 SCLogInfo(
"Parser disabled for %s protocol. Protocol detection still on.", proto_name);
3319 cfglist_backup = cfglist;
3326 cfglist = cfglist_backup;
3333 static int HTPParserTest01(
void)
3335 uint8_t httpbuf1[] =
"POST / HTTP/1.0\r\nUser-Agent: Victor/1.0\r\n\r\nPost"
3337 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3340 memset(&ssn, 0,
sizeof(ssn));
3348 f->
proto = IPPROTO_TCP;
3354 for (u = 0; u < httplen1; u++) {
3358 flags = STREAM_TOSERVER|STREAM_START;
3359 else if (u == (httplen1 - 1))
3360 flags = STREAM_TOSERVER|STREAM_EOF;
3362 flags = STREAM_TOSERVER;
3371 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3374 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3377 FAIL_IF(strcmp(bstr_util_strdup_to_c(h->value),
"Victor/1.0"));
3378 FAIL_IF(tx->request_method_number != HTP_M_POST);
3379 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_0);
3388 static int HTPParserTest01b(
void)
3390 uint8_t httpbuf1[] =
"POST / HTTP/1.0\r\nUser-Agent:\r\n Victor/1.0\r\n\r\nPost"
3392 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3395 memset(&ssn, 0,
sizeof(ssn));
3403 f->
proto = IPPROTO_TCP;
3408 uint8_t
flags =STREAM_TOSERVER|STREAM_START|STREAM_EOF;
3415 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3418 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3421 FAIL_IF(strcmp(bstr_util_strdup_to_c(h->value),
"Victor/1.0"));
3422 FAIL_IF(tx->request_method_number != HTP_M_POST);
3423 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_0);
3432 static int HTPParserTest01c(
void)
3434 uint8_t httpbuf1[] =
"POST / HTTP/1.0\r\nUser-Agent:\r\n Victor/1.0\r\n\r\nPost"
3436 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3439 memset(&ssn, 0,
sizeof(ssn));
3447 f->
proto = IPPROTO_TCP;
3453 for (u = 0; u < httplen1; u++) {
3457 flags = STREAM_TOSERVER|STREAM_START;
3458 else if (u == (httplen1 - 1))
3459 flags = STREAM_TOSERVER|STREAM_EOF;
3461 flags = STREAM_TOSERVER;
3470 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3473 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3476 FAIL_IF(strcmp(bstr_util_strdup_to_c(h->value),
"Victor/1.0"));
3477 FAIL_IF(tx->request_method_number != HTP_M_POST);
3478 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_0);
3488 static int HTPParserTest01a(
void)
3492 uint8_t httpbuf1[] =
" POST / HTTP/1.0\r\nUser-Agent: Victor/1.0\r\n\r\nPost"
3494 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3500 memset(&ssn, 0,
sizeof(ssn));
3502 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
3506 f->
proto = IPPROTO_TCP;
3512 for (u = 0; u < httplen1; u++) {
3516 flags = STREAM_TOSERVER|STREAM_START;
3517 else if (u == (httplen1 - 1))
3518 flags = STREAM_TOSERVER|STREAM_EOF;
3520 flags = STREAM_TOSERVER;
3524 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
3531 if (htp_state == NULL) {
3532 printf(
"no http state: ");
3536 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3537 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3538 if (strcmp(bstr_util_strdup_to_c(h->value),
"Victor/1.0")
3539 || tx->request_method_number != HTP_M_POST ||
3540 tx->request_protocol_number != HTP_PROTOCOL_1_0)
3542 printf(
"expected header value: Victor/1.0 and got %s: and expected"
3543 " method: POST and got %s, expected protocol number HTTP/1.0"
3544 " and got: %s \n", bstr_util_strdup_to_c(h->value),
3545 bstr_util_strdup_to_c(tx->request_method),
3546 bstr_util_strdup_to_c(tx->request_protocol));
3559 static int HTPParserTest02(
void)
3563 uint8_t httpbuf1[] =
"POST";
3564 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3569 memset(&ssn, 0,
sizeof(ssn));
3571 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
3575 f->
proto = IPPROTO_TCP;
3581 STREAM_TOSERVER | STREAM_START | STREAM_EOF, httpbuf1, httplen1);
3583 printf(
"toserver chunk 1 returned %" PRId32
", expected 0: ", r);
3588 if (http_state == NULL) {
3589 printf(
"no http state: ");
3593 htp_tx_t *tx = HTPStateGetTx(http_state, 0);
3595 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3599 char *method = bstr_util_strdup_to_c(tx->request_method);
3602 FAIL_IF(strcmp(method,
"POST") != 0);
3616 static int HTPParserTest03(
void)
3620 uint8_t httpbuf1[] =
"HELLO / HTTP/1.0\r\n";
3621 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3627 memset(&ssn, 0,
sizeof(ssn));
3629 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
3633 f->
proto = IPPROTO_TCP;
3639 for (u = 0; u < httplen1; u++) {
3642 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
3643 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
3644 else flags = STREAM_TOSERVER;
3648 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
3654 if (htp_state == NULL) {
3655 printf(
"no http state: ");
3659 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3661 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3662 if (tx->request_method_number != HTP_M_UNKNOWN ||
3663 h != NULL || tx->request_protocol_number != HTP_PROTOCOL_1_0)
3665 printf(
"expected method M_UNKNOWN and got %s: , expected protocol "
3666 "HTTP/1.0 and got %s \n", bstr_util_strdup_to_c(tx->request_method),
3667 bstr_util_strdup_to_c(tx->request_protocol));
3681 static int HTPParserTest04(
void)
3686 uint8_t httpbuf1[] =
"World!\r\n";
3687 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3692 memset(&ssn, 0,
sizeof(ssn));
3694 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
3698 f->
proto = IPPROTO_TCP;
3704 STREAM_TOSERVER | STREAM_START | STREAM_EOF, httpbuf1, httplen1);
3710 if (htp_state == NULL) {
3711 printf(
"no http state: ");
3715 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3716 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3717 if (tx->request_method_number != HTP_M_UNKNOWN ||
3718 h != NULL || tx->request_protocol_number != HTP_PROTOCOL_0_9)
3720 printf(
"expected method M_UNKNOWN and got %s: , expected protocol "
3721 "NULL and got %s \n", bstr_util_strdup_to_c(tx->request_method),
3722 bstr_util_strdup_to_c(tx->request_protocol));
3736 static int HTPParserTest05(
void)
3738 uint8_t httpbuf1[] =
"POST / HTTP/1.0\r\nUser-Agent: Victor/1.0\r\nContent-Length: 17\r\n\r\n";
3739 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3740 uint8_t httpbuf2[] =
"Post D";
3741 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
3742 uint8_t httpbuf3[] =
"ata is c0oL!";
3743 uint32_t httplen3 =
sizeof(httpbuf3) - 1;
3745 uint8_t httpbuf4[] =
"HTTP/1.0 200 OK\r\nServer: VictorServer/1.0\r\n\r\n";
3746 uint32_t httplen4 =
sizeof(httpbuf4) - 1;
3747 uint8_t httpbuf5[] =
"post R";
3748 uint32_t httplen5 =
sizeof(httpbuf5) - 1;
3749 uint8_t httpbuf6[] =
"esults are tha bomb!";
3750 uint32_t httplen6 =
sizeof(httpbuf6) - 1;
3753 memset(&ssn, 0,
sizeof(ssn));
3761 f->
proto = IPPROTO_TCP;
3791 htp_tx_t *tx = HTPStateGetTx(http_state, 0);
3793 FAIL_IF_NOT(tx->request_method_number == HTP_M_POST);
3794 FAIL_IF_NOT(tx->request_protocol_number == HTP_PROTOCOL_1_0);
3796 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3809 static int HTPParserTest06(
void)
3811 uint8_t httpbuf1[] =
"GET /ld/index.php?id=412784631&cid=0064&version=4&"
3812 "name=try HTTP/1.1\r\nAccept: */*\r\nUser-Agent: "
3813 "LD-agent\r\nHost: 209.205.196.16\r\n\r\n";
3814 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3815 uint8_t httpbuf2[] =
"HTTP/1.1 200 OK\r\nDate: Sat, 03 Oct 2009 10:16:02 "
3817 "Server: Apache/1.3.37 (Unix) mod_ssl/2.8.28 "
3818 "OpenSSL/0.9.7a PHP/4.4.7 mod_perl/1.29 "
3819 "FrontPage/5.0.2.2510\r\n"
3820 "X-Powered-By: PHP/4.4.7\r\nTransfer-Encoding: "
3822 "Content-Type: text/html\r\n\r\n"
3824 "W2dyb3VwMV0NCnBob25lMT1wMDB3ODgyMTMxMzAyMTINCmxvZ2lu"
3825 "MT0NCnBhc3N3b3JkMT0NCnBob25lMj1wMDB3ODgyMTMxMzAyMTIN"
3826 "CmxvZ2luMj0NCnBhc3N3b3JkMj0NCnBob25lMz0NCmxvZ2luMz0N"
3827 "CnBhc3N3b3JkMz0NCnBob25lND0NCmxvZ2luND0NCnBhc3N3b3Jk"
3828 "ND0NCnBob25lNT0NCmxvZ2luNT0NCnBhc3N3b3JkNT0NCnBob25l"
3829 "Nj0NCmxvZ2luNj0NCnBhc3N3b3JkNj0NCmNhbGxfdGltZTE9MzIN"
3830 "CmNhbGxfdGltZTI9MjMyDQpkYXlfbGltaXQ9NQ0KbW9udGhfbGlt"
3831 "aXQ9MTUNCltncm91cDJdDQpwaG9uZTE9DQpsb2dpbjE9DQpwYXNz"
3832 "d29yZDE9DQpwaG9uZTI9DQpsb2dpbjI9DQpwYXNzd29yZDI9DQpw"
3833 "aG9uZTM9DQpsb2dpbjM9DQpwYXNzd29yZDM9DQpwaG9uZTQ9DQps"
3834 "b2dpbjQ9DQpwYXNzd29yZDQ9DQpwaG9uZTU9DQpsb2dpbjU9DQpw"
3835 "YXNzd29yZDU9DQpwaG9uZTY9DQpsb2dpbjY9DQpwYXNzd29yZDY9"
3836 "DQpjYWxsX3RpbWUxPQ0KY2FsbF90aW1lMj0NCmRheV9saW1pdD0N"
3837 "Cm1vbnRoX2xpbWl0PQ0KW2dyb3VwM10NCnBob25lMT0NCmxvZ2lu"
3838 "MT0NCnBhc3N3b3JkMT0NCnBob25lMj0NCmxvZ2luMj0NCnBhc3N3"
3839 "b3JkMj0NCnBob25lMz0NCmxvZ2luMz0NCnBhc3N3b3JkMz0NCnBo"
3840 "b25lND0NCmxvZ2luND0NCnBhc3N3b3JkND0NCnBob25lNT0NCmxv"
3841 "Z2luNT0NCnBhc3N3b3JkNT0NCnBob25lNj0NCmxvZ2luNj0NCnBh"
3842 "c3N3b3JkNj0NCmNhbGxfdGltZTE9DQpjYWxsX3RpbWUyPQ0KZGF5"
3843 "X2xpbWl0PQ0KbW9udGhfbGltaXQ9DQpbZ3JvdXA0XQ0KcGhvbmUx"
3844 "PQ0KbG9naW4xPQ0KcGFzc3dvcmQxPQ0KcGhvbmUyPQ0KbG9naW4y"
3845 "PQ0KcGFzc3dvcmQyPQ0KcGhvbmUzPQ0KbG9naW4zPQ0KcGFzc3dv"
3846 "cmQzPQ0KcGhvbmU0PQ0KbG9naW40PQ0KcGFzc3dvcmQ0PQ0KcGhv"
3847 "bmU1PQ0KbG9naW41PQ0KcGFzc3dvcmQ1PQ0KcGhvbmU2PQ0KbG9n"
3848 "aW42PQ0KcGFzc3dvcmQ2PQ0KY2FsbF90aW1lMT0NCmNhbGxfdGlt"
3849 "ZTI9DQpkYXlfbGltaXQ9DQptb250aF9saW1pdD0NCltmaWxlc10N"
3850 "Cmxpbms9aHR0cDovLzIwOS4yMDUuMTk2LjE2L2xkL2dldGJvdC5w"
3851 "aHA=\r\n0\r\n\r\n";
3852 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
3858 memset(&ssn, 0,
sizeof(ssn));
3863 f->
proto = IPPROTO_TCP;
3878 htp_tx_t *tx = HTPStateGetTx(http_state, 0);
3881 FAIL_IF(tx->request_method_number != HTP_M_GET);
3882 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_1);
3884 FAIL_IF(tx->response_status_number != 200);
3885 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_1);
3887 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3898 static int HTPParserTest07(
void)
3902 uint8_t httpbuf1[] =
"GET /awstats.pl?/migratemigrate%20=%20| HTTP/1.0\r\n\r\n";
3903 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3909 memset(&ssn, 0,
sizeof(ssn));
3911 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
3915 f->
proto = IPPROTO_TCP;
3921 for (u = 0; u < httplen1; u++) {
3925 flags = STREAM_TOSERVER|STREAM_START;
3926 else if (u == (httplen1 - 1))
3927 flags = STREAM_TOSERVER|STREAM_EOF;
3929 flags = STREAM_TOSERVER;
3933 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
3940 if (htp_state == NULL) {
3941 printf(
"no http state: ");
3945 uint8_t ref[] =
"/awstats.pl?/migratemigrate = |";
3946 size_t reflen =
sizeof(ref) - 1;
3948 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3954 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
3963 printf(
"normalized uri \"");
3985 static int HTPParserTest08(
void)
3989 uint8_t httpbuf1[] =
"GET /secondhouse/image/js/\%ce\%de\%ce\%fd_RentCity.js?v=2011.05.02 HTTP/1.0\r\n\r\n";
3990 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4012 memset(&ssn, 0,
sizeof(ssn));
4014 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
4018 f->
proto = IPPROTO_TCP;
4024 flags = STREAM_TOSERVER|STREAM_START|STREAM_EOF;
4028 printf(
"toserver chunk returned %" PRId32
", expected"
4035 if (htp_state == NULL) {
4036 printf(
"no http state: ");
4041 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4065 static int HTPParserTest09(
void)
4069 uint8_t httpbuf1[] =
"GET /secondhouse/image/js/\%ce\%de\%ce\%fd_RentCity.js?v=2011.05.02 HTTP/1.0\r\n\r\n";
4070 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4080 personality: Apache_2_2\n\
4093 memset(&ssn, 0,
sizeof(ssn));
4095 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
4099 f->
proto = IPPROTO_TCP;
4105 flags = STREAM_TOSERVER|STREAM_START|STREAM_EOF;
4109 printf(
"toserver chunk returned %" PRId32
", expected"
4115 if (htp_state == NULL) {
4116 printf(
"no http state: ");
4120 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4144 static int HTPParserTest10(
void)
4148 uint8_t httpbuf1[] =
"GET / HTTP/1.0\r\nHost:www.google.com\r\n\r\n";
4149 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4155 memset(&ssn, 0,
sizeof(ssn));
4157 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
4161 f->
proto = IPPROTO_TCP;
4167 for (u = 0; u < httplen1; u++) {
4171 flags = STREAM_TOSERVER|STREAM_START;
4172 else if (u == (httplen1 - 1))
4173 flags = STREAM_TOSERVER|STREAM_EOF;
4175 flags = STREAM_TOSERVER;
4179 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
4186 if (htp_state == NULL) {
4187 printf(
"no http state: ");
4191 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4192 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
4197 char *name = bstr_util_strdup_to_c(h->name);
4202 if (strcmp(name,
"Host") != 0) {
4203 printf(
"header name not \"Host\", instead \"%s\": ", name);
4209 char *value = bstr_util_strdup_to_c(h->value);
4210 if (value == NULL) {
4214 if (strcmp(value,
"www.google.com") != 0) {
4215 printf(
"header value not \"www.google.com\", instead \"%s\": ", value);
4232 static int HTPParserTest11(
void)
4236 uint8_t httpbuf1[] =
"GET /%2500 HTTP/1.0\r\n\r\n";
4237 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4243 memset(&ssn, 0,
sizeof(ssn));
4245 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
4249 f->
proto = IPPROTO_TCP;
4255 for (u = 0; u < httplen1; u++) {
4259 flags = STREAM_TOSERVER|STREAM_START;
4260 else if (u == (httplen1 - 1))
4261 flags = STREAM_TOSERVER|STREAM_EOF;
4263 flags = STREAM_TOSERVER;
4267 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
4274 if (htp_state == NULL) {
4275 printf(
"no http state: ");
4279 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4285 printf(
"normalized uri len should be 2, is %"PRIuMAX,
4295 printf(
"normalized uri \"");
4313 static int HTPParserTest12(
void)
4317 uint8_t httpbuf1[] =
"GET /?a=%2500 HTTP/1.0\r\n\r\n";
4318 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4324 memset(&ssn, 0,
sizeof(ssn));
4326 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
4330 f->
proto = IPPROTO_TCP;
4336 for (u = 0; u < httplen1; u++) {
4340 flags = STREAM_TOSERVER|STREAM_START;
4341 else if (u == (httplen1 - 1))
4342 flags = STREAM_TOSERVER|STREAM_EOF;
4344 flags = STREAM_TOSERVER;
4348 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
4355 if (htp_state == NULL) {
4356 printf(
"no http state: ");
4360 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4366 printf(
"normalized uri len should be 5, is %"PRIuMAX,
4379 printf(
"normalized uri \"");
4397 static int HTPParserTest13(
void)
4401 uint8_t httpbuf1[] =
"GET / HTTP/1.0\r\nHost:www.google.com\rName: Value\r\n\r\n";
4402 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4408 memset(&ssn, 0,
sizeof(ssn));
4410 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
4414 f->
proto = IPPROTO_TCP;
4420 for (u = 0; u < httplen1; u++) {
4424 flags = STREAM_TOSERVER|STREAM_START;
4425 else if (u == (httplen1 - 1))
4426 flags = STREAM_TOSERVER|STREAM_EOF;
4428 flags = STREAM_TOSERVER;
4432 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
4439 if (htp_state == NULL) {
4440 printf(
"no http state: ");
4444 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4445 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
4450 char *name = bstr_util_strdup_to_c(h->name);
4455 if (strcmp(name,
"Host") != 0) {
4456 printf(
"header name not \"Host\", instead \"%s\": ", name);
4462 char *value = bstr_util_strdup_to_c(h->value);
4463 if (value == NULL) {
4467 if (strcmp(value,
"www.google.com\rName: Value") != 0) {
4468 printf(
"header value not \"www.google.com\", instead \"");
4486 static int HTPParserConfigTest01(
void)
4500 address: [192.168.1.0/24, 127.0.0.0/8, \"::1\"]\n\
4501 personality: Tomcat_6_0\n\
4506 - 192.168.10.0/24\n\
4507 personality: IIS_7_0\n\
4516 outputs =
ConfGetNode(
"libhtp.default-config.personality");
4517 if (outputs == NULL) {
4522 if (outputs == NULL) {
4530 if (strcmp(node->
name,
"0") != 0) {
4537 if (strcmp(node->
name,
"apache-tomcat") != 0) {
4545 if (node2 == NULL) {
4548 if (strcmp(node2->
val,
"Tomcat_6_0") != 0) {
4563 if (strcmp(n->
name,
"0") != 0) {
4566 if (strcmp(n->
val,
"192.168.1.0/24") != 0) {
4571 if (strcmp(n->
name,
"1") != 0) {
4574 if (strcmp(n->
val,
"127.0.0.0/8") != 0) {
4579 if (strcmp(n->
name,
"2") != 0) {
4582 if (strcmp(n->
val,
"::1") != 0) {
4593 if (outputs == NULL) {
4602 if (strcmp(node->
name,
"1") != 0) {
4609 if (strcmp(node->
name,
"iis7") != 0) {
4614 if (node2 == NULL) {
4617 if (strcmp(node2->
val,
"IIS_7_0") != 0) {
4634 if (strcmp(n->
name,
"0") != 0) {
4637 if (strcmp(n->
val,
"192.168.0.0/24") != 0) {
4642 if (strcmp(n->
name,
"1") != 0) {
4645 if (strcmp(n->
val,
"192.168.10.0/24") != 0) {
4665 static int HTPParserConfigTest02(
void)
4679 address: [192.168.1.0/24, 127.0.0.0/8, \"::1\"]\n\
4680 personality: Tomcat_6_0\n\
4685 - 192.168.10.0/24\n\
4686 personality: IIS_7_0\n\
4697 if (cfglist.
cfg == NULL) {
4698 printf(
"No default config created.\n");
4702 if (cfgtree == NULL) {
4703 printf(
"No config tree created.\n");
4707 htp_cfg_t *htp = cfglist.
cfg;
4710 void *user_data = NULL;
4712 addr =
"192.168.10.42";
4713 if (inet_pton(AF_INET, addr, buf) == 1) {
4715 if (user_data != NULL) {
4717 htp = htp_cfg_rec->
cfg;
4721 printf(
"Could not get config for: %s\n", addr);
4726 printf(
"Failed to parse address: %s\n", addr);
4732 if (inet_pton(AF_INET6, addr, buf) == 1) {
4734 if (user_data != NULL) {
4736 htp = htp_cfg_rec->
cfg;
4740 printf(
"Could not get config for: %s\n", addr);
4745 printf(
"Failed to parse address: %s\n", addr);
4761 static int HTPParserConfigTest03(
void)
4765 uint8_t httpbuf1[] =
"POST / HTTP/1.0\r\nUser-Agent: Victor/1.0\r\n\r\nPost"
4767 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4784 address: [192.168.1.0/24, 127.0.0.0/8, \"::1\"]\n\
4785 personality: Tomcat_6_0\n\
4790 - 192.168.10.0/24\n\
4791 personality: IIS_7_0\n\
4802 const char *addr =
"192.168.10.42";
4804 memset(&ssn, 0,
sizeof(ssn));
4810 f->
proto = IPPROTO_TCP;
4813 htp_cfg_t *htp = cfglist.
cfg;
4815 void *user_data = NULL;
4817 if (user_data != NULL) {
4819 htp = htp_cfg_rec->
cfg;
4823 printf(
"Could not get config for: %s\n", addr);
4830 for (u = 0; u < httplen1; u++) {
4833 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
4834 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
4835 else flags = STREAM_TOSERVER;
4839 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
4847 if (htp_state == NULL) {
4848 printf(
"no http state: ");
4853 if (HTPStateGetTxCnt(htp_state) != 2) {
4854 printf(
"HTPStateGetTxCnt(htp_state) failure\n");
4858 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4861 if (tx->cfg != htp) {
4862 printf(
"wrong HTP config (%p instead of %p - default=%p): ",
4863 tx->cfg, htp, cfglist.
cfg);
4866 tx = HTPStateGetTx(htp_state, 1);
4869 if (tx->cfg != htp) {
4870 printf(
"wrong HTP config (%p instead of %p - default=%p): ",
4871 tx->cfg, htp, cfglist.
cfg);
4894 static int HTPParserDecodingTest01(
void)
4896 uint8_t httpbuf1[] =
4897 "GET /abc%2fdef HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
4898 "GET /abc/def?ghi%2fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
4899 "GET /abc/def?ghi%252fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
4900 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4911 personality: Apache_2\n\
4919 const char *addr =
"4.3.2.1";
4920 memset(&ssn, 0,
sizeof(ssn));
4925 f->
proto = IPPROTO_TCP;
4930 for (uint32_t u = 0; u < httplen1; u++) {
4932 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
4933 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
4934 else flags = STREAM_TOSERVER;
4943 uint8_t ref1[] =
"/abc%2fdef";
4944 size_t reflen =
sizeof(ref1) - 1;
4946 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4956 uint8_t ref2[] =
"/abc/def?ghi/jkl";
4957 reflen =
sizeof(ref2) - 1;
4959 tx = HTPStateGetTx(htp_state, 1);
4969 uint8_t ref3[] =
"/abc/def?ghi%2fjkl";
4970 reflen =
sizeof(ref3) - 1;
4971 tx = HTPStateGetTx(htp_state, 2);
4992 static int HTPParserDecodingTest01a(
void)
4994 uint8_t httpbuf1[] =
"GET /abc%2fdef HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
4995 "GET /abc/def?ghi%2fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
4996 "GET /abc/def?ghi%252fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
4997 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5008 personality: Apache_2\n\
5016 const char *addr =
"4.3.2.1";
5017 memset(&ssn, 0,
sizeof(ssn));
5022 f->
proto = IPPROTO_TCP;
5028 (STREAM_TOSERVER | STREAM_START | STREAM_EOF), httpbuf1, httplen1);
5034 uint8_t ref1[] =
"/abc%2fdef";
5035 size_t reflen =
sizeof(ref1) - 1;
5037 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5047 uint8_t ref2[] =
"/abc/def?ghi/jkl";
5048 reflen =
sizeof(ref2) - 1;
5050 tx = HTPStateGetTx(htp_state, 1);
5060 uint8_t ref3[] =
"/abc/def?ghi%2fjkl";
5061 reflen =
sizeof(ref3) - 1;
5062 tx = HTPStateGetTx(htp_state, 2);
5089 static int HTPParserDecodingTest02(
void)
5093 uint8_t httpbuf1[] =
5094 "GET /abc%2fdef HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
5095 "GET /abc/def?ghi%2fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
5096 "GET /abc/def?ghi%252fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5097 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5110 double-decode-path: no\n\
5111 double-decode-query: no\n\
5119 const char *addr =
"4.3.2.1";
5120 memset(&ssn, 0,
sizeof(ssn));
5126 f->
proto = IPPROTO_TCP;
5132 for (u = 0; u < httplen1; u++) {
5135 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
5136 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
5137 else flags = STREAM_TOSERVER;
5141 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5148 if (htp_state == NULL) {
5149 printf(
"no http state: ");
5153 uint8_t ref1[] =
"/abc/def";
5154 size_t reflen =
sizeof(ref1) - 1;
5156 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5162 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5171 printf(
"normalized uri \"");
5180 uint8_t ref2[] =
"/abc/def?ghi/jkl";
5181 reflen =
sizeof(ref2) - 1;
5183 tx = HTPStateGetTx(htp_state, 1);
5189 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5198 printf(
"normalized uri \"");
5207 uint8_t ref3[] =
"/abc/def?ghi%2fjkl";
5208 reflen =
sizeof(ref3) - 1;
5209 tx = HTPStateGetTx(htp_state, 2);
5215 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX
" (3): ",
5224 printf(
"normalized uri \"");
5253 static int HTPParserDecodingTest03(
void)
5257 uint8_t httpbuf1[] =
5258 "GET /abc%252fdef HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
5259 "GET /abc/def?ghi%252fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5260 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5273 double-decode-path: yes\n\
5274 double-decode-query: yes\n\
5282 const char *addr =
"4.3.2.1";
5283 memset(&ssn, 0,
sizeof(ssn));
5289 f->
proto = IPPROTO_TCP;
5295 for (u = 0; u < httplen1; u++) {
5298 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
5299 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
5300 else flags = STREAM_TOSERVER;
5304 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5311 if (htp_state == NULL) {
5312 printf(
"no http state: ");
5316 uint8_t ref1[] =
"/abc/def";
5317 size_t reflen =
sizeof(ref1) - 1;
5319 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5325 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5334 printf(
"normalized uri \"");
5343 uint8_t ref2[] =
"/abc/def?ghi/jkl";
5344 reflen =
sizeof(ref2) - 1;
5346 tx = HTPStateGetTx(htp_state, 1);
5352 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5361 printf(
"normalized uri \"");
5387 static int HTPParserDecodingTest04(
void)
5391 uint8_t httpbuf1[] =
5392 "GET /abc/def?a=http://www.abc.com/ HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5393 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5406 double-decode-path: yes\n\
5407 double-decode-query: yes\n\
5415 const char *addr =
"4.3.2.1";
5416 memset(&ssn, 0,
sizeof(ssn));
5422 f->
proto = IPPROTO_TCP;
5428 for (u = 0; u < httplen1; u++) {
5431 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
5432 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
5433 else flags = STREAM_TOSERVER;
5437 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5444 if (htp_state == NULL) {
5445 printf(
"no http state: ");
5449 uint8_t ref1[] =
"/abc/def?a=http://www.abc.com/";
5450 size_t reflen =
sizeof(ref1) - 1;
5452 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5458 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5467 printf(
"normalized uri \"");
5493 static int HTPParserDecodingTest05(
void)
5497 uint8_t httpbuf1[] =
5498 "GET /index?id=\\\"<script>alert(document.cookie)</script> HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5499 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5512 double-decode-path: yes\n\
5513 double-decode-query: yes\n\
5521 const char *addr =
"4.3.2.1";
5522 memset(&ssn, 0,
sizeof(ssn));
5528 f->
proto = IPPROTO_TCP;
5534 for (u = 0; u < httplen1; u++) {
5537 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
5538 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
5539 else flags = STREAM_TOSERVER;
5543 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5550 if (htp_state == NULL) {
5551 printf(
"no http state: ");
5555 uint8_t ref1[] =
"/index?id=\\\"<script>alert(document.cookie)</script>";
5556 size_t reflen =
sizeof(ref1) - 1;
5558 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5564 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5573 printf(
"normalized uri \"");
5599 static int HTPParserDecodingTest06(
void)
5603 uint8_t httpbuf1[] =
5604 "GET /put.php?ip=1.2.3.4&port=+6000 HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5605 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5618 double-decode-path: yes\n\
5619 double-decode-query: yes\n\
5627 const char *addr =
"4.3.2.1";
5628 memset(&ssn, 0,
sizeof(ssn));
5634 f->
proto = IPPROTO_TCP;
5640 for (u = 0; u < httplen1; u++) {
5643 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
5644 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
5645 else flags = STREAM_TOSERVER;
5649 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5656 if (htp_state == NULL) {
5657 printf(
"no http state: ");
5661 uint8_t ref1[] =
"/put.php?ip=1.2.3.4&port=+6000";
5662 size_t reflen =
sizeof(ref1) - 1;
5664 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5670 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5679 printf(
"normalized uri \"");
5705 static int HTPParserDecodingTest07(
void)
5709 uint8_t httpbuf1[] =
5710 "GET /put.php?ip=1.2.3.4&port=+6000 HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5711 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5724 double-decode-path: yes\n\
5725 double-decode-query: yes\n\
5726 query-plusspace-decode: yes\n\
5734 const char *addr =
"4.3.2.1";
5735 memset(&ssn, 0,
sizeof(ssn));
5741 f->
proto = IPPROTO_TCP;
5747 for (u = 0; u < httplen1; u++) {
5750 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
5751 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
5752 else flags = STREAM_TOSERVER;
5756 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5763 if (htp_state == NULL) {
5764 printf(
"no http state: ");
5768 uint8_t ref1[] =
"/put.php?ip=1.2.3.4&port= 6000";
5769 size_t reflen =
sizeof(ref1) - 1;
5771 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5777 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5786 printf(
"normalized uri \"");
5812 static int HTPParserDecodingTest08(
void)
5816 uint8_t httpbuf1[] =
5817 "GET http://suricata-ids.org/blah/ HTTP/1.1\r\nHost: suricata-ids.org\r\n\r\n";
5818 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5838 const char *addr =
"4.3.2.1";
5839 memset(&ssn, 0,
sizeof(ssn));
5845 f->
proto = IPPROTO_TCP;
5851 for (u = 0; u < httplen1; u++) {
5854 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
5855 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
5856 else flags = STREAM_TOSERVER;
5860 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5867 if (htp_state == NULL) {
5868 printf(
"no http state: ");
5872 uint8_t ref1[] =
"/blah/";
5873 size_t reflen =
sizeof(ref1) - 1;
5875 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5881 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5890 printf(
"normalized uri \"");
5916 static int HTPParserDecodingTest09(
void)
5920 uint8_t httpbuf1[] =
5921 "GET http://suricata-ids.org/blah/ HTTP/1.1\r\nHost: suricata-ids.org\r\n\r\n";
5922 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5935 uri-include-all: true\n\
5943 const char *addr =
"4.3.2.1";
5944 memset(&ssn, 0,
sizeof(ssn));
5950 f->
proto = IPPROTO_TCP;
5956 for (u = 0; u < httplen1; u++) {
5959 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
5960 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
5961 else flags = STREAM_TOSERVER;
5965 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5972 if (htp_state == NULL) {
5973 printf(
"no http state: ");
5977 uint8_t ref1[] =
"http://suricata-ids.org/blah/";
5978 size_t reflen =
sizeof(ref1) - 1;
5980 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5986 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5995 printf(
"normalized uri \"");
6020 static int HTPBodyReassemblyTest01(
void)
6024 memset(&htud, 0x00,
sizeof(htud));
6026 memset(&hstate, 0x00,
sizeof(hstate));
6028 memset(&flow, 0x00,
sizeof(flow));
6031 memset(&tx, 0,
sizeof(tx));
6036 uint8_t chunk1[] =
"--e5a320f21416a02493a0a6f561b1c494\r\nContent-Disposition: form-data; name=\"uploadfile\"; filename=\"D2GUef.jpg\"\r";
6037 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";
6044 const uint8_t *chunks_buffer = NULL;
6045 uint32_t chunks_buffer_len = 0;
6047 HtpRequestBodyReassemble(&htud, &chunks_buffer, &chunks_buffer_len);
6048 if (chunks_buffer == NULL) {
6052 printf(
"REASSCHUNK START: \n");
6054 printf(
"REASSCHUNK END: \n");
6057 HtpRequestBodyHandleMultipart(&hstate, &htud, &tx, chunks_buffer, chunks_buffer_len);
6072 static int HTPSegvTest01(
void)
6076 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";
6077 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
6085 double-decode-path: no\n\
6086 double-decode-query: no\n\
6087 request-body-limit: 0\n\
6088 response-body-limit: 0\n\
6101 memset(&ssn, 0,
sizeof(ssn));
6103 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
6107 f->
proto = IPPROTO_TCP;
6112 SCLogDebug(
"\n>>>> processing chunk 1 <<<<\n");
6116 printf(
"toserver chunk 1 returned %" PRId32
", expected 0: ", r);
6119 SCLogDebug(
"\n>>>> processing chunk 1 again <<<<\n");
6122 printf(
"toserver chunk 1 returned %" PRId32
", expected 0: ", r);
6127 if (http_state == NULL) {
6128 printf(
"no http state: ");
6133 if (decoder_events != NULL) {
6134 printf(
"app events: ");
6151 static int HTPParserTest14(
void)
6162 double-decode-path: no\n\
6163 double-decode-query: no\n\
6164 request-body-limit: 0\n\
6165 response-body-limit: 0\n\
6170 memset(&ssn, 0,
sizeof(ssn));
6180 memset(httpbuf, 0x00,
len);
6183 strlcpy(httpbuf,
"GET /blah/ HTTP/1.1\r\n"
6184 "Host: myhost.lan\r\n"
6185 "Connection: keep-alive\r\n"
6187 "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"
6188 "Referer: http://blah.lan/\r\n"
6189 "Accept-Encoding: gzip,deflate,sdch\r\nAccept-Language: en-US,en;q=0.8\r\n"
6191 size_t o = strlen(httpbuf);
6192 for ( ; o <
len - 4; o++) {
6195 httpbuf[
len - 4] =
'\r';
6196 httpbuf[
len - 3] =
'\n';
6197 httpbuf[
len - 2] =
'\r';
6198 httpbuf[
len - 1] =
'\n';
6204 f->
proto = IPPROTO_TCP;
6209 for (u = 0; u <
len; u++) {
6212 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
6213 else if (u == (
len - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
6214 else flags = STREAM_TOSERVER;
6222 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
6224 FAIL_IF(tx->request_method_number != HTP_M_GET);
6225 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_1);
6247 static int HTPParserTest15(
void)
6251 char *httpbuf = NULL;
6263 double-decode-path: no\n\
6264 double-decode-query: no\n\
6265 request-body-limit: 0\n\
6266 response-body-limit: 0\n\
6267 meta-field-limit: 20000\n\
6271 memset(&ssn, 0,
sizeof(ssn));
6282 memset(httpbuf, 0x00,
len);
6285 strlcpy(httpbuf,
"GET /blah/ HTTP/1.1\r\n"
6286 "Host: myhost.lan\r\n"
6287 "Connection: keep-alive\r\n"
6289 "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"
6290 "Referer: http://blah.lan/\r\n"
6291 "Accept-Encoding: gzip,deflate,sdch\r\nAccept-Language: en-US,en;q=0.8\r\n"
6293 size_t o = strlen(httpbuf);
6294 for ( ; o <
len - 4; o++) {
6297 httpbuf[
len - 4] =
'\r';
6298 httpbuf[
len - 3] =
'\n';
6299 httpbuf[
len - 2] =
'\r';
6300 httpbuf[
len - 1] =
'\n';
6302 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
6306 f->
proto = IPPROTO_TCP;
6312 for (u = 0; u <
len; u++) {
6315 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
6316 else if (u == (
len - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
6317 else flags = STREAM_TOSERVER;
6321 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
6327 if (htp_state == NULL) {
6328 printf(
"no http state: ");
6332 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
6333 if (tx == NULL || tx->request_method_number != HTP_M_GET || tx->request_protocol_number != HTP_PROTOCOL_1_1)
6335 printf(
"expected method M_GET and got %s: , expected protocol "
6336 "HTTP/1.1 and got %s \n", bstr_util_strdup_to_c(tx->request_method),
6337 bstr_util_strdup_to_c(tx->request_protocol));
6344 if (decoder_events != NULL) {
6345 printf(
"app events: ");
6355 if (httpbuf != NULL)
6365 static int HTPParserTest16(
void)
6374 memset(&ssn, 0,
sizeof(ssn));
6376 uint8_t httpbuf[] =
"GET\f/blah/\fHTTP/1.1\r\n"
6377 "Host: myhost.lan\r\n"
6378 "Connection: keep-alive\r\n"
6380 "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"
6381 "Referer: http://blah.lan/\r\n"
6382 "Accept-Encoding: gzip,deflate,sdch\r\nAccept-Language: en-US,en;q=0.8\r\n"
6383 "Cookie: blah\r\n\r\n";
6384 size_t len =
sizeof(httpbuf) - 1;
6386 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
6390 f->
proto = IPPROTO_TCP;
6395 uint8_t
flags = STREAM_TOSERVER|STREAM_START|STREAM_EOF;
6399 printf(
"toserver chunk 1 returned %" PRId32
", expected 0: ", r);
6404 if (htp_state == NULL) {
6405 printf(
"no http state: ");
6409 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
6410 if (tx == NULL || tx->request_method_number != HTP_M_GET || tx->request_protocol_number != HTP_PROTOCOL_1_1)
6412 printf(
"expected method M_GET and got %s: , expected protocol "
6413 "HTTP/1.1 and got %s \n", tx ? bstr_util_strdup_to_c(tx->request_method) :
"tx null",
6414 tx ? bstr_util_strdup_to_c(tx->request_protocol) :
"tx null");
6418 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
6423 if (decoder_events == NULL) {
6424 printf(
"no app events: ");
6429 printf(
"HTTP_DECODER_EVENT_METHOD_DELIM_NON_COMPLIANT not set: ");
6434 printf(
"HTTP_DECODER_EVENT_URI_DELIM_NON_COMPLIANT not set: ");
6450 static int HTPParserTest20(
void)
6453 uint8_t httpbuf1[] =
"GET /ld/index.php?id=412784631&cid=0064&version=4&"
6454 "name=try HTTP/1.1\r\nAccept: */*\r\nUser-Agent: "
6455 "LD-agent\r\nHost: 209.205.196.16\r\n\r\n";
6456 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
6457 uint8_t httpbuf2[] =
"NOTHTTP\r\nSOMEOTHERDATA";
6458 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
6459 uint8_t httpbuf3[] =
"STILLNOTHTTP\r\nSOMEMOREOTHERDATA";
6460 uint32_t httplen3 =
sizeof(httpbuf3) - 1;
6466 memset(&ssn, 0,
sizeof(ssn));
6468 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
6471 f->
proto = IPPROTO_TCP;
6490 htp_tx_t *tx = HTPStateGetTx(http_state, 0);
6492 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
6495 FAIL_IF(tx->request_method_number != HTP_M_GET);
6496 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_1);
6498 FAIL_IF(tx->response_status_number != 0);
6499 FAIL_IF(tx->response_protocol_number != -1);
6509 static int HTPParserTest21(
void)
6512 uint8_t httpbuf1[] =
"GET /ld/index.php?id=412784631&cid=0064&version=4&"
6513 "name=try HTTP/1.1\r\nAccept: */*\r\nUser-Agent: "
6514 "LD-agent\r\nHost: 209.205.196.16\r\n\r\n";
6515 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
6516 uint8_t httpbuf2[] =
"999 NOTHTTP REALLY\r\nSOMEOTHERDATA\r\n";
6517 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
6518 uint8_t httpbuf3[] =
"STILLNOTHTTP\r\nSOMEMOREOTHERDATA";
6519 uint32_t httplen3 =
sizeof(httpbuf3) - 1;
6525 memset(&ssn, 0,
sizeof(ssn));
6527 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
6530 f->
proto = IPPROTO_TCP;
6549 htp_tx_t *tx = HTPStateGetTx(http_state, 0);
6551 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
6554 FAIL_IF(tx->request_method_number != HTP_M_GET);
6555 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_1);
6557 FAIL_IF(tx->response_status_number != 0);
6558 FAIL_IF(tx->response_protocol_number != -1);
6568 static int HTPParserTest22(
void)
6571 uint8_t httpbuf1[] =
"GET /ld/index.php?id=412784631&cid=0064&version=4&"
6572 "name=try HTTP/1.1\r\nAccept: */*\r\nUser-Agent: "
6573 "LD-agent\r\nHost: 209.205.196.16\r\n\r\n";
6574 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
6575 uint8_t httpbuf2[] =
"\r\n0000=0000000/ASDF3_31.zip, 456723\r\n"
6576 "AAAAAA_0000=0000000/AAAAAAAA.zip,46725\r\n";
6577 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
6583 memset(&ssn, 0,
sizeof(ssn));
6585 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
6588 f->
proto = IPPROTO_TCP;
6603 htp_tx_t *tx = HTPStateGetTx(http_state, 0);
6605 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
6608 FAIL_IF(tx->request_method_number != HTP_M_GET);
6609 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_1);
6611 FAIL_IF(tx->response_status_number != -0);
6612 FAIL_IF(tx->response_protocol_number != -1);
6622 static int HTPParserTest23(
void)
6625 uint8_t httpbuf1[] =
"GET /ld/index.php?id=412784631&cid=0064&version=4&"
6626 "name=try HTTP/1.1\r\nAccept: */*\r\nUser-Agent: "
6627 "LD-agent\r\nHost: 209.205.196.16\r\n\r\n";
6628 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
6629 uint8_t httpbuf2[] =
"HTTP0000=0000000/ASDF3_31.zip, 456723\r\n"
6630 "AAAAAA_0000=0000000/AAAAAAAA.zip,46725\r\n";
6631 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
6637 memset(&ssn, 0,
sizeof(ssn));
6639 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
6642 f->
proto = IPPROTO_TCP;
6657 htp_tx_t *tx = HTPStateGetTx(http_state, 0);
6659 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
6662 FAIL_IF(tx->request_method_number != HTP_M_GET);
6663 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_1);
6665 FAIL_IF(tx->response_status_number != -1);
6666 FAIL_IF(tx->response_protocol_number != -2);
6676 static int HTPParserTest24(
void)
6679 uint8_t httpbuf1[] =
"GET /ld/index.php?id=412784631&cid=0064&version=4&"
6680 "name=try HTTP/1.1\r\nAccept: */*\r\nUser-Agent: "
6681 "LD-agent\r\nHost: 209.205.196.16\r\n\r\n";
6682 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
6683 uint8_t httpbuf2[] =
"HTTP/1.0 0000=0000000/ASDF3_31.zip, 456723\r\n"
6684 "AAAAAA_0000=0000000/AAAAAAAA.zip,46725\r\n";
6685 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
6691 memset(&ssn, 0,
sizeof(ssn));
6693 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
6696 f->
proto = IPPROTO_TCP;
6711 htp_tx_t *tx = HTPStateGetTx(http_state, 0);
6713 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
6716 FAIL_IF(tx->request_method_number != HTP_M_GET);
6717 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_1);
6719 FAIL_IF(tx->response_status_number != -1);
6720 FAIL_IF(tx->response_protocol_number != HTP_PROTOCOL_1_0);
6729 static int HTPParserTest25(
void)
6736 memset(&ssn, 0,
sizeof(ssn));
6741 f->
proto = IPPROTO_TCP;
6744 const char *
str =
"GET / HTTP/1.1\r\nHost: www.google.com\r\nUser-Agent: Suricata/1.0\r\n\r\n";
6746 (uint8_t *)
str, strlen(
str));
6770 str =
"HTTP 1.1 200 OK\r\nServer: Suricata/1.0\r\nContent-Length: 8\r\n\r\nSuricata";
6772 (uint8_t *)
str, strlen(
str));
6806 (uint8_t *)
str, strlen(
str));
6817 (uint8_t *)
str, strlen(
str));
6837 static int HTPParserTest26(
void)
6846 request-body-limit: 1\n\
6847 response-body-limit: 1\n\
6861 uint8_t httpbuf1[] =
"GET /alice.txt HTTP/1.1\r\n\r\n";
6862 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
6863 uint8_t httpbuf2[] =
"HTTP/1.1 200 OK\r\n"
6864 "Content-Type: text/plain\r\n"
6865 "Content-Length: 228\r\n\r\n"
6866 "Alice was beginning to get very tired of sitting by her sister on the bank."
6867 "Alice was beginning to get very tired of sitting by her sister on the bank.";
6868 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
6869 uint8_t httpbuf3[] =
"Alice was beginning to get very tired of sitting by her sister on the bank.\r\n\r\n";
6870 uint32_t httplen3 =
sizeof(httpbuf3) - 1;
6876 memset(&th_v, 0,
sizeof(th_v));
6877 memset(&f, 0,
sizeof(f));
6878 memset(&ssn, 0,
sizeof(ssn));
6885 f.
proto = IPPROTO_TCP;
6906 "(filestore; sid:1; rev:1;)");
6951 AppLayerGetFileState files = HTPGetTxFiles(http_state, tx_ptr, STREAM_TOCLIENT);
6973 static int HTPParserTest27(
void)
6976 memset(&cfg, 0,
sizeof(cfg));
6980 uint32_t
len = 1000;
7005 static void HTPParserRegisterTests(
void)
7027 UtRegisterTest(
"HTPParserDecodingTest01", HTPParserDecodingTest01);
7028 UtRegisterTest(
"HTPParserDecodingTest01a", HTPParserDecodingTest01a);
7029 UtRegisterTest(
"HTPParserDecodingTest02", HTPParserDecodingTest02);
7030 UtRegisterTest(
"HTPParserDecodingTest03", HTPParserDecodingTest03);
7031 UtRegisterTest(
"HTPParserDecodingTest04", HTPParserDecodingTest04);
7032 UtRegisterTest(
"HTPParserDecodingTest05", HTPParserDecodingTest05);
7033 UtRegisterTest(
"HTPParserDecodingTest06", HTPParserDecodingTest06);
7034 UtRegisterTest(
"HTPParserDecodingTest07", HTPParserDecodingTest07);
7035 UtRegisterTest(
"HTPParserDecodingTest08", HTPParserDecodingTest08);
7036 UtRegisterTest(
"HTPParserDecodingTest09", HTPParserDecodingTest09);
7038 UtRegisterTest(
"HTPBodyReassemblyTest01", HTPBodyReassemblyTest01);