99 #define HTP_MAX_MESSAGES 512
105 static uint64_t htp_state_memuse = 0;
106 static uint64_t htp_state_memcnt = 0;
116 {
"INVALID_TRANSFER_ENCODING_VALUE_IN_REQUEST",
118 {
"INVALID_TRANSFER_ENCODING_VALUE_IN_RESPONSE",
120 {
"INVALID_CONTENT_LENGTH_FIELD_IN_REQUEST",
122 {
"INVALID_CONTENT_LENGTH_FIELD_IN_RESPONSE",
124 {
"DUPLICATE_CONTENT_LENGTH_FIELD_IN_REQUEST",
126 {
"DUPLICATE_CONTENT_LENGTH_FIELD_IN_RESPONSE",
129 {
"UNABLE_TO_MATCH_RESPONSE_TO_REQUEST",
144 {
"REQUEST_SERVER_PORT_TCP_PORT_MISMATCH",
158 {
"RESPONSE_ABNORMAL_TRANSFER_ENCODING",
202 static int HTTPGetFrameIdByName(
const char *frame_name)
211 static const char *HTTPGetFrameNameById(
const uint8_t frame_id)
217 static void *HTPStateGetTx(
void *alstate, uint64_t tx_id);
218 static int HTPStateGetAlstateProgress(
void *tx, uint8_t direction);
219 static uint64_t HTPStateGetTxCnt(
void *alstate);
221 static void HTPParserRegisterTests(
void);
224 static inline uint64_t HtpGetActiveRequestTxID(
HtpState *s)
226 uint64_t
id = HTPStateGetTxCnt(s);
231 static inline uint64_t HtpGetActiveResponseTxID(
HtpState *s)
244 static const char *HTPLookupPersonalityString(
int p)
246 #define CASE_HTP_PERSONALITY_STRING(p) \
247 case HTP_SERVER_ ## p: return #p
250 CASE_HTP_PERSONALITY_STRING(MINIMAL);
251 CASE_HTP_PERSONALITY_STRING(GENERIC);
252 CASE_HTP_PERSONALITY_STRING(IDS);
253 CASE_HTP_PERSONALITY_STRING(IIS_4_0);
254 CASE_HTP_PERSONALITY_STRING(IIS_5_0);
255 CASE_HTP_PERSONALITY_STRING(IIS_5_1);
256 CASE_HTP_PERSONALITY_STRING(IIS_6_0);
257 CASE_HTP_PERSONALITY_STRING(IIS_7_0);
258 CASE_HTP_PERSONALITY_STRING(IIS_7_5);
259 CASE_HTP_PERSONALITY_STRING(APACHE_2);
273 static int HTPLookupPersonality(
const char *
str)
275 #define IF_HTP_PERSONALITY_NUM(p) \
276 if (strcasecmp(#p, str) == 0) return HTP_SERVER_ ## p
288 if (strcasecmp(
"TOMCAT_6_0",
str) == 0) {
290 "longer supported by libhtp.",
293 }
else if ((strcasecmp(
"APACHE",
str) == 0) ||
294 (strcasecmp(
"APACHE_2_2",
str) == 0))
297 "longer supported by libhtp, failing back to "
298 "Apache2 personality.",
300 return HTP_SERVER_APACHE_2;
307 const uint8_t dir,
const uint8_t e)
317 const uint64_t tx_id = (dir == STREAM_TOSERVER) ?
318 HtpGetActiveRequestTxID(s) : HtpGetActiveResponseTxID(s);
320 htp_tx_t *tx = HTPStateGetTx(s, tx_id);
321 if (tx == NULL && tx_id > 0)
322 tx = HTPStateGetTx(s, tx_id - 1);
337 static void *HTPStateAlloc(
void *orig_state,
AppProto proto_orig)
351 htp_state_memuse +=
sizeof(
HtpState);
352 SCLogDebug(
"htp memory %"PRIu64
" (%"PRIu64
")", htp_state_memuse, htp_state_memcnt);
372 if (htud->
tx_data.de_state != NULL) {
398 if (s->
connp != NULL) {
402 uint64_t total_txs = HTPStateGetTxCnt(state);
404 if (s->
conn != NULL) {
405 for (tx_id = s->
tx_freed; tx_id < total_txs; tx_id++) {
406 htp_tx_t *tx = HTPStateGetTx(s, tx_id);
409 HtpTxUserDataFree(s, htud);
410 htp_tx_set_user_data(tx, NULL);
414 htp_connp_destroy_all(s->
connp);
422 htp_state_memuse -=
sizeof(
HtpState);
423 SCLogDebug(
"htp memory %"PRIu64
" (%"PRIu64
")", htp_state_memuse, htp_state_memcnt);
436 static void HTPStateTransactionFree(
void *state, uint64_t
id)
444 htp_tx_t *tx = HTPStateGetTx(s,
id);
448 HtpTxUserDataFree(s, htud);
449 htp_tx_set_user_data(tx, NULL);
456 tx->request_progress == HTP_REQUEST_COMPLETE &&
457 tx->response_progress == HTP_RESPONSE_COMPLETE)))
459 tx->request_progress = HTP_REQUEST_COMPLETE;
460 tx->response_progress = HTP_RESPONSE_COMPLETE;
500 static void AppLayerHtpNeedMultipartHeader(
void)
518 AppLayerHtpNeedMultipartHeader();
526 static void AppLayerHtpSetStreamDepthFlag(
void *tx,
const uint8_t
flags)
531 if (
flags & STREAM_TOCLIENT) {
541 SCLogDebug(
"cfg->body_limit %u stream_depth %u body->content_len_so_far %" PRIu64,
558 static uint32_t AppLayerHtpComputeChunkLength(uint64_t content_len_so_far, uint32_t body_limit,
559 uint32_t stream_depth, uint8_t
flags, uint32_t data_len)
561 uint32_t chunk_len = 0;
563 (content_len_so_far < (uint64_t)body_limit) &&
564 (content_len_so_far + (uint64_t)data_len) > body_limit)
566 chunk_len = body_limit - content_len_so_far;
568 (content_len_so_far < (uint64_t)stream_depth) &&
569 (content_len_so_far + (uint64_t)data_len) > stream_depth)
571 chunk_len = stream_depth - content_len_so_far;
574 return (chunk_len == 0 ? data_len : chunk_len);
621 {
"Request line: URI contains non-compliant delimiter",
623 {
"Request line: non-compliant delimiter between Method and URI",
632 {
"Transfer-encoding has abnormal chunked value",
634 {
"Chunked transfer-encoding on HTTP/0.9 or HTTP/1.0",
637 {
"Invalid response line: invalid response status",
643 {
"Ambiguous response C-L value",
649 #define HTP_ERROR_MAX (sizeof(htp_errors) / sizeof(htp_errors[0]))
650 #define HTP_WARNING_MAX (sizeof(htp_warnings) / sizeof(htp_warnings[0]))
661 static uint8_t HTPHandleWarningGetId(
const char *
msg)
685 static uint8_t HTPHandleErrorGetId(
const char *
msg)
709 static void HTPHandleError(
HtpState *s,
const uint8_t dir)
711 if (s == NULL || s->
conn == NULL ||
712 s->
conn->messages == NULL) {
716 size_t size = htp_list_size(s->
conn->messages);
731 htp_log_t *log = htp_list_get(s->
conn->messages,
msg);
736 htp_tx_t *tx = log->tx;
742 uint8_t
id = HTPHandleErrorGetId(log->msg);
744 id = HTPHandleWarningGetId(log->msg);
750 HTPSetEvent(s, htud, dir,
id);
757 static inline void HTPErrorCheckTxRequestFlags(
HtpState *s, htp_tx_t *tx)
760 BUG_ON(s == NULL || tx == NULL);
762 if (tx->flags & ( HTP_REQUEST_INVALID_T_E|HTP_REQUEST_INVALID_C_L|
763 HTP_HOST_MISSING|HTP_HOST_AMBIGUOUS|HTP_HOSTU_INVALID|
770 if (tx->flags & HTP_REQUEST_INVALID_T_E)
771 HTPSetEvent(s, htud, STREAM_TOSERVER,
773 if (tx->flags & HTP_REQUEST_INVALID_C_L)
774 HTPSetEvent(s, htud, STREAM_TOSERVER,
776 if (tx->flags & HTP_HOST_MISSING)
777 HTPSetEvent(s, htud, STREAM_TOSERVER,
779 if (tx->flags & HTP_HOST_AMBIGUOUS)
780 HTPSetEvent(s, htud, STREAM_TOSERVER,
782 if (tx->flags & HTP_HOSTU_INVALID)
783 HTPSetEvent(s, htud, STREAM_TOSERVER,
785 if (tx->flags & HTP_HOSTH_INVALID)
786 HTPSetEvent(s, htud, STREAM_TOSERVER,
789 if (tx->request_auth_type == HTP_AUTH_UNRECOGNIZED) {
793 HTPSetEvent(s, htud, STREAM_TOSERVER,
796 if (tx->is_protocol_0_9 && tx->request_method_number == HTP_M_UNKNOWN &&
797 (tx->request_protocol_number == HTP_PROTOCOL_INVALID ||
798 tx->request_protocol_number == HTP_PROTOCOL_UNKNOWN)) {
802 HTPSetEvent(s, htud, STREAM_TOSERVER,
813 htp_cfg_t *htp = cfglist.
cfg;
814 void *user_data = NULL;
829 if (user_data != NULL) {
830 htp_cfg_rec = user_data;
831 htp = htp_cfg_rec->
cfg;
834 SCLogDebug(
"Using default HTP config: %p", htp);
838 #ifdef DEBUG_VALIDATION
845 hstate->
connp = htp_connp_create(htp);
846 if (hstate->
connp == NULL) {
850 hstate->
conn = htp_connp_get_connection(hstate->
connp);
852 htp_connp_set_user_data(hstate->
connp, (
void *)hstate);
853 hstate->
cfg = htp_cfg_rec;
858 htp_connp_open(hstate->
connp, NULL, f->
sp, NULL, f->
dp, &
tv);
880 StreamSlice stream_slice,
void *local_data)
890 if (NULL == hstate->
conn) {
891 if (Setup(f, hstate) != 0) {
896 hstate->
slice = &stream_slice;
898 const uint8_t *input = StreamSliceGetData(&stream_slice);
899 uint32_t input_len = StreamSliceGetDataLen(&stream_slice);
904 const int r = htp_connp_req_data(hstate->
connp, &
ts, input, input_len);
906 case HTP_STREAM_ERROR:
912 HTPHandleError(hstate, STREAM_TOSERVER);
919 htp_connp_req_close(hstate->
connp, &
ts);
921 SCLogDebug(
"stream eof encountered, closing htp handle for ts");
925 hstate->
slice = NULL;
947 StreamSlice stream_slice,
void *local_data)
953 const uint8_t *input = StreamSliceGetData(&stream_slice);
954 uint32_t input_len = StreamSliceGetDataLen(&stream_slice);
960 if (NULL == hstate->
conn) {
961 if (Setup(f, hstate) != 0) {
966 hstate->
slice = &stream_slice;
972 const int r = htp_connp_res_data(hstate->
connp, &
ts, input, input_len);
974 case HTP_STREAM_ERROR:
977 case HTP_STREAM_TUNNEL:
978 tx = htp_connp_get_out_tx(hstate->
connp);
979 if (tx != NULL && tx->response_status_number == 101) {
981 (htp_header_t *)htp_table_get_c(tx->response_headers,
"Upgrade");
982 if (h == NULL || bstr_cmp_c(h->value,
"h2c") != 0) {
990 if (tx->request_port_number != -1) {
991 dp = (uint16_t)tx->request_port_number;
993 consumed = htp_connp_res_data_consumed(hstate->
connp);
994 hstate->
slice = NULL;
996 HTPSetEvent(hstate, NULL, STREAM_TOCLIENT,
1001 if (consumed > 0 && consumed < input_len) {
1010 HTPHandleError(hstate, STREAM_TOCLIENT);
1017 htp_connp_close(hstate->
connp, &
ts);
1022 hstate->
slice = NULL;
1033 static int HTTPParseContentDispositionHeader(uint8_t *name,
size_t name_len,
1034 uint8_t *data,
size_t len, uint8_t **retptr,
size_t *retlen)
1037 printf(
"DATA START: \n");
1039 printf(
"DATA END: \n");
1044 for (x = 0; x <
len; x++) {
1045 if (!(isspace(data[x])))
1052 uint8_t *line = data+x;
1053 size_t line_len =
len-x;
1056 printf(
"LINE START: \n");
1058 printf(
"LINE END: \n");
1060 for (x = 0 ; x < line_len; x++) {
1062 if (line[x - 1] !=
'\\' && line[x] ==
'\"') {
1066 if (((line[x - 1] !=
'\\' && line[x] ==
';') || ((x + 1) == line_len)) && (quote == 0 || quote % 2 == 0)) {
1067 uint8_t *token = line +
offset;
1068 size_t token_len = x -
offset;
1070 if ((x + 1) == line_len) {
1081 printf(
"TOKEN START: \n");
1083 printf(
"TOKEN END: \n");
1085 if (token_len > name_len) {
1086 if (name == NULL || SCMemcmpLowercase(name, token, name_len) == 0) {
1087 uint8_t *value = token + name_len;
1088 size_t value_len = token_len - name_len;
1090 if (value[0] ==
'\"') {
1094 if (value[value_len-1] ==
'\"') {
1098 printf(
"VALUE START: \n");
1100 printf(
"VALUE END: \n");
1103 *retlen = value_len;
1117 static int HTTPParseContentTypeHeader(uint8_t *name,
size_t name_len,
1118 uint8_t *data,
size_t len, uint8_t **retptr,
size_t *retlen)
1122 printf(
"DATA START: \n");
1124 printf(
"DATA END: \n");
1129 for (x = 0; x <
len; x++) {
1130 if (!(isspace(data[x])))
1138 uint8_t *line = data+x;
1139 size_t line_len =
len-x;
1142 printf(
"LINE START: \n");
1144 printf(
"LINE END: \n");
1146 for (x = 0 ; x < line_len; x++) {
1148 if (line[x - 1] !=
'\\' && line[x] ==
'\"') {
1152 if (((line[x - 1] !=
'\\' && line[x] ==
';') || ((x + 1) == line_len)) && (quote == 0 || quote % 2 == 0)) {
1153 uint8_t *token = line +
offset;
1154 size_t token_len = x -
offset;
1156 if ((x + 1) == line_len) {
1167 printf(
"TOKEN START: \n");
1169 printf(
"TOKEN END: \n");
1171 if (token_len > name_len) {
1172 if (name == NULL || SCMemcmpLowercase(name, token, name_len) == 0) {
1173 uint8_t *value = token + name_len;
1174 size_t value_len = token_len - name_len;
1176 if (value[0] ==
'\"') {
1180 if (value[value_len-1] ==
'\"') {
1184 printf(
"VALUE START: \n");
1186 printf(
"VALUE END: \n");
1189 *retlen = value_len;
1213 static int HtpRequestBodySetupMultipart(htp_tx_t *tx,
HtpTxUserData *htud)
1215 htp_header_t *h = (htp_header_t *)htp_table_get_c(tx->request_headers,
1217 if (h != NULL && bstr_len(h->value) > 0) {
1218 uint8_t *boundary = NULL;
1219 size_t boundary_len = 0;
1221 int r = HTTPParseContentTypeHeader((uint8_t *)
"boundary=", 9,
1222 (uint8_t *) bstr_ptr(h->value), bstr_len(h->value),
1223 &boundary, &boundary_len);
1226 printf(
"BOUNDARY START: \n");
1228 printf(
"BOUNDARY END: \n");
1236 memcpy(htud->
boundary, boundary, boundary_len);
1250 #define C_D_HDR "content-disposition:"
1251 #define C_D_HDR_LEN 20
1252 #define C_T_HDR "content-type:"
1253 #define C_T_HDR_LEN 13
1255 static void HtpRequestBodyMultipartParseHeader(
HtpState *hstate,
1257 uint8_t *header, uint32_t header_len,
1258 uint8_t **filename, uint16_t *filename_len,
1259 uint8_t **filetype, uint16_t *filetype_len)
1267 printf(
"HEADER START: \n");
1269 printf(
"HEADER END: \n");
1272 while (header_len > 0) {
1273 uint8_t *next_line =
Bs2bmSearch(header, header_len, (uint8_t *)
"\r\n", 2);
1274 uint8_t *line = header;
1277 if (next_line == NULL) {
1278 line_len = header_len;
1280 line_len = next_line - header;
1282 uint8_t *sc = (uint8_t *)memchr(line,
':', line_len);
1284 HTPSetEvent(hstate, htud, STREAM_TOSERVER,
1288 }
else if (line_len > 0 && sc == &line[line_len - 1]) {
1289 HTPSetEvent(hstate, htud, STREAM_TOSERVER,
1293 printf(
"LINE START: \n");
1295 printf(
"LINE END: \n");
1303 (void)HTTPParseContentDispositionHeader((uint8_t *)
"filename=", 9,
1304 value, value_len, &fn, &fn_len);
1311 (void)HTTPParseContentTypeHeader(NULL, 0,
1312 value, value_len, &ft, &ft_len);
1316 if (next_line == NULL) {
1320 header_len -= ((next_line + 2) - header);
1321 header = next_line + 2;
1324 if (fn_len > USHRT_MAX)
1326 if (ft_len > USHRT_MAX)
1330 *filename_len = (uint16_t)fn_len;
1332 *filetype_len = (uint16_t)ft_len;
1343 const uint8_t **chunks_buffer, uint32_t *chunks_buffer_len)
1346 chunks_buffer, chunks_buffer_len,
1350 static void FlagDetectStateNewFile(
HtpTxUserData *tx,
int dir)
1353 if (tx && tx->
tx_data.de_state) {
1354 if (dir == STREAM_TOSERVER) {
1355 SCLogDebug(
"DETECT_ENGINE_STATE_FLAG_FILE_NEW set");
1357 }
else if (STREAM_TOCLIENT) {
1358 SCLogDebug(
"DETECT_ENGINE_STATE_FLAG_FILE_NEW set");
1367 static void HtpRequestBodySetupBoundary(
HtpTxUserData *htud,
1368 uint8_t *boundary, uint32_t boundary_len)
1370 memset(boundary,
'-', boundary_len);
1375 const uint8_t *chunks_buffer, uint32_t chunks_buffer_len)
1379 uint16_t expected_boundary_len = htud->
boundary_len + 2;
1380 uint16_t expected_boundary_end_len = htud->
boundary_len + 4;
1381 int tx_progress = 0;
1384 printf(
"CHUNK START: \n");
1386 printf(
"CHUNK END: \n");
1389 HtpRequestBodySetupBoundary(htud, boundary, htud->
boundary_len + 4);
1392 const uint8_t *header_start =
Bs2bmSearch(chunks_buffer, chunks_buffer_len,
1393 boundary, expected_boundary_len);
1395 const uint8_t *form_end = NULL;
1397 const uint8_t *header_end = NULL;
1398 if (header_start != NULL) {
1399 header_end =
Bs2bmSearch(header_start, chunks_buffer_len - (header_start - chunks_buffer),
1400 (uint8_t *)
"\r\n\r\n", 4);
1401 form_end =
Bs2bmSearch(header_start, chunks_buffer_len - (header_start - chunks_buffer),
1402 boundary, expected_boundary_end_len);
1405 SCLogDebug(
"header_start %p, header_end %p, form_end %p", header_start,
1406 header_end, form_end);
1413 if (header_start != NULL || (tx_progress > HTP_REQUEST_BODY)) {
1416 const uint8_t *filedata = chunks_buffer;
1417 uint32_t filedata_len = 0;
1420 if (header_start != NULL) {
1421 if (header_start == filedata + 2) {
1423 SCLogDebug(
"last chunk had all data, but not the boundary");
1425 }
else if (header_start > filedata + 2) {
1426 SCLogDebug(
"some data from last file before the boundary");
1428 filedata_len = header_start - filedata - 2;
1433 if (tx_progress > HTP_REQUEST_BODY) {
1434 filedata_len = chunks_buffer_len;
1438 if (filedata_len > chunks_buffer_len) {
1439 HTPSetEvent(hstate, htud, STREAM_TOSERVER,
1444 printf(
"FILEDATA (final chunk) START: \n");
1446 printf(
"FILEDATA (final chunk) END: \n");
1449 if (
HTPFileClose(hstate, htud, filedata, filedata_len,
flags, STREAM_TOSERVER) ==
1459 SCLogDebug(
"not yet at the end of the file");
1461 if (chunks_buffer_len > expected_boundary_end_len) {
1462 const uint8_t *filedata = chunks_buffer;
1463 uint32_t filedata_len = chunks_buffer_len - expected_boundary_len;
1464 for (; filedata_len < chunks_buffer_len; filedata_len++) {
1466 if (chunks_buffer[filedata_len] ==
'\r') {
1467 if (filedata_len + 1 == chunks_buffer_len ||
1468 chunks_buffer[filedata_len + 1] ==
'\n') {
1475 printf(
"FILEDATA (part) START: \n");
1477 printf(
"FILEDATA (part) END: \n");
1482 hstate, htud, filedata, filedata_len, STREAM_TOSERVER);
1485 }
else if (result == -2) {
1493 SCLogDebug(
"chunk too small to already process in part");
1500 while (header_start != NULL && header_end != NULL &&
1501 header_end != form_end &&
1502 header_start < (chunks_buffer + chunks_buffer_len) &&
1503 header_end < (chunks_buffer + chunks_buffer_len) &&
1504 header_start < header_end)
1506 uint8_t *filename = NULL;
1507 uint16_t filename_len = 0;
1508 uint8_t *filetype = NULL;
1509 uint16_t filetype_len = 0;
1511 uint32_t header_len = header_end - header_start;
1513 uint8_t *header = (uint8_t *)header_start;
1516 if (expected_boundary_len == header_len) {
1518 }
else if ((uint32_t)(expected_boundary_len + 2) <= header_len) {
1519 header_len -= (expected_boundary_len + 2);
1520 header = (uint8_t *)header_start + (expected_boundary_len + 2);
1523 HtpRequestBodyMultipartParseHeader(hstate, htud, header, header_len,
1524 &filename, &filename_len, &filetype, &filetype_len);
1526 if (filename != NULL) {
1527 const uint8_t *filedata = NULL;
1528 uint32_t filedata_len = 0;
1539 if (form_end != NULL) {
1542 filedata = header_end + 4;
1543 if (form_end == filedata) {
1544 HTPSetEvent(hstate, htud, STREAM_TOSERVER,
1547 }
else if (form_end < filedata) {
1548 HTPSetEvent(hstate, htud, STREAM_TOSERVER,
1553 filedata_len = form_end - (header_end + 4 + 2);
1554 SCLogDebug(
"filedata_len %"PRIuMAX, (uintmax_t)filedata_len);
1557 uint8_t *header_next =
Bs2bmSearch(filedata, filedata_len,
1558 boundary, expected_boundary_len);
1559 if (header_next != NULL) {
1560 filedata_len -= (form_end - header_next);
1563 if (filedata_len > chunks_buffer_len) {
1564 HTPSetEvent(hstate, htud, STREAM_TOSERVER,
1568 SCLogDebug(
"filedata_len %"PRIuMAX, (uintmax_t)filedata_len);
1570 printf(
"FILEDATA START: \n");
1572 printf(
"FILEDATA END: \n");
1575 result =
HTPFileOpen(hstate, htud, filename, filename_len, filedata, filedata_len,
1579 }
else if (result == -2) {
1582 if (
HTPFileClose(hstate, htud, NULL, 0, 0, STREAM_TOSERVER) == -1) {
1586 FlagDetectStateNewFile(htud, STREAM_TOSERVER);
1591 SCLogDebug(
"chunk doesn't contain form end");
1593 filedata = header_end + 4;
1594 filedata_len = chunks_buffer_len - (filedata - chunks_buffer);
1595 SCLogDebug(
"filedata_len %u (chunks_buffer_len %u)", filedata_len, chunks_buffer_len);
1597 if (filedata_len > chunks_buffer_len) {
1598 HTPSetEvent(hstate, htud, STREAM_TOSERVER,
1604 printf(
"FILEDATA START: \n");
1606 printf(
"FILEDATA END: \n");
1610 uint8_t *header_next =
Bs2bmSearch(filedata, filedata_len,
1611 boundary, expected_boundary_len);
1613 if (header_next == NULL) {
1616 uint32_t
offset = (header_end + 4) - chunks_buffer;
1620 if (filedata_len >= (uint32_t)(expected_boundary_len + 2)) {
1621 filedata_len -= (expected_boundary_len + 2 - 1);
1623 for (
size_t nb = 0; nb < (size_t)expected_boundary_len + 1; nb++) {
1624 if (filedata[filedata_len] ==
'\r') {
1625 if (nb == expected_boundary_len ||
1626 filedata[filedata_len + 1] ==
'\n') {
1632 SCLogDebug(
"opening file with partial data");
1637 result =
HTPFileOpen(hstate, htud, filename, filename_len, filedata,
1638 filedata_len, STREAM_TOSERVER);
1641 }
else if (result == -2) {
1644 FlagDetectStateNewFile(htud, STREAM_TOSERVER);
1648 }
else if (header_next - filedata > 2) {
1649 filedata_len = header_next - filedata - 2;
1652 result =
HTPFileOpen(hstate, htud, filename, filename_len, filedata,
1653 filedata_len, STREAM_TOSERVER);
1656 }
else if (result == -2) {
1659 if (
HTPFileClose(hstate, htud, NULL, 0, 0, STREAM_TOSERVER) == -1) {
1663 FlagDetectStateNewFile(htud, STREAM_TOSERVER);
1671 SCLogDebug(
"header_start %p, header_end %p, form_end %p",
1672 header_start, header_end, form_end);
1675 uint32_t cursizeread = header_end - chunks_buffer;
1677 chunks_buffer_len - (cursizeread + 4),
1678 boundary, expected_boundary_len);
1679 if (header_start != NULL) {
1681 chunks_buffer_len - (cursizeread + 4),
1682 (uint8_t *)
"\r\n\r\n", 4);
1689 if (chunks_buffer_len > expected_boundary_end_len) {
1690 uint32_t move = chunks_buffer_len - expected_boundary_end_len + 1;
1693 SCLogDebug(
"form not ready, file not set, parsing non-file "
1694 "record: moved %u", move);
1707 htp_tx_t *tx, uint8_t *data, uint32_t data_len)
1714 uint8_t *filename = NULL;
1715 size_t filename_len = 0;
1718 if (tx->parsed_uri != NULL && tx->parsed_uri->path != NULL) {
1719 filename = (uint8_t *)bstr_ptr(tx->parsed_uri->path);
1720 filename_len = bstr_len(tx->parsed_uri->path);
1723 if (filename != NULL) {
1729 result =
HTPFileOpen(hstate, htud, filename, (uint16_t)filename_len, data, data_len,
1733 }
else if (result == -2) {
1736 FlagDetectStateNewFile(htud, STREAM_TOSERVER);
1750 }
else if (result == -2) {
1763 htp_tx_t *tx, uint8_t *data, uint32_t data_len)
1776 uint8_t *filename = NULL;
1777 size_t filename_len = 0;
1780 htp_header_t *h = (htp_header_t *)htp_table_get_c(tx->response_headers,
1781 "Content-Disposition");
1782 if (h != NULL && bstr_len(h->value) > 0) {
1784 (void)HTTPParseContentDispositionHeader((uint8_t *)
"filename=", 9,
1785 (uint8_t *) bstr_ptr(h->value), bstr_len(h->value), &filename, &filename_len);
1789 if (filename == NULL) {
1791 if (tx->parsed_uri != NULL && tx->parsed_uri->path != NULL) {
1792 filename = (uint8_t *)bstr_ptr(tx->parsed_uri->path);
1793 filename_len = bstr_len(tx->parsed_uri->path);
1797 if (filename != NULL) {
1799 htp_header_t *h_content_range = htp_table_get_c(tx->response_headers,
"content-range");
1805 if (h_content_range != NULL) {
1807 data_len, tx, h_content_range->value, htud);
1809 result =
HTPFileOpen(hstate, htud, filename, (uint16_t)filename_len, data, data_len,
1815 }
else if (result == -2) {
1818 FlagDetectStateNewFile(htud, STREAM_TOCLIENT);
1831 }
else if (result == -2) {
1849 static int HTPCallbackRequestBodyData(htp_tx_data_t *d)
1860 printf(
"HTPBODY START: \n");
1862 printf(
"HTPBODY END: \n");
1865 HtpState *hstate = htp_connp_get_user_data(d->tx->connp);
1866 if (hstate == NULL) {
1870 SCLogDebug(
"New request body data available at %p -> %p -> %p, bodylen "
1871 "%"PRIu32
"", hstate, d, d->data, (uint32_t)d->len);
1874 if (tx_ud == NULL) {
1882 if (d->tx->request_method_number == HTP_M_POST) {
1884 int r = HtpRequestBodySetupMultipart(d->tx, tx_ud);
1887 }
else if (r == 0) {
1891 }
else if (d->tx->request_method_number == HTP_M_PUT) {
1914 const uint8_t *chunks_buffer = NULL;
1915 uint32_t chunks_buffer_len = 0;
1923 HtpRequestBodyReassemble(tx_ud, &chunks_buffer, &chunks_buffer_len);
1924 if (chunks_buffer == NULL) {
1928 printf(
"REASSCHUNK START: \n");
1930 printf(
"REASSCHUNK END: \n");
1933 HtpRequestBodyHandleMultipart(hstate, tx_ud, d->tx, chunks_buffer, chunks_buffer_len);
1937 HtpRequestBodyHandlePOSTorPUT(hstate, tx_ud, d->tx, (uint8_t *)d->data,
len);
1942 SCLogDebug(
"closing file that was being stored");
1949 if (hstate->
conn != NULL) {
1950 SCLogDebug(
"checking body size %"PRIu64
" against inspect limit %u (cur %"PRIu64
", last %"PRIu64
")",
1964 const uint32_t data_size = (uint32_t)(
1985 static int HTPCallbackResponseBodyData(htp_tx_data_t *d)
1995 HtpState *hstate = htp_connp_get_user_data(d->tx->connp);
1996 if (hstate == NULL) {
2000 SCLogDebug(
"New response body data available at %p -> %p -> %p, bodylen "
2001 "%"PRIu32
"", hstate, d, d->data, (uint32_t)d->len);
2004 if (tx_ud == NULL) {
2030 HtpResponseBodyHandle(hstate, tx_ud, d->tx, (uint8_t *)d->data,
len);
2033 SCLogDebug(
"closing file that was being stored");
2039 if (hstate->
conn != NULL) {
2040 SCLogDebug(
"checking body size %"PRIu64
" against inspect limit %u (cur %"PRIu64
", last %"PRIu64
")",
2053 const uint32_t data_size = (uint32_t)((uint64_t)hstate->
conn->out_data_counter -
2077 SCLogDebug(
"http_state_memcnt %"PRIu64
", http_state_memuse %"PRIu64
"",
2078 htp_state_memcnt, htp_state_memuse);
2098 htp_config_destroy(cfglist.
cfg);
2099 while (nextrec != NULL) {
2101 nextrec = nextrec->
next;
2103 htp_config_destroy(htprec->
cfg);
2109 static int HTPCallbackRequestHasTrailer(htp_tx_t *tx)
2118 static int HTPCallbackResponseHasTrailer(htp_tx_t *tx)
2131 static int HTPCallbackRequestStart(htp_tx_t *tx)
2133 HtpState *hstate = htp_connp_get_user_data(tx->connp);
2134 if (hstate == NULL) {
2138 uint64_t consumed = hstate->
slice->offset + htp_connp_req_data_consumed(hstate->
connp);
2139 SCLogDebug(
"HTTP request start: data offset %" PRIu64
", in_data_counter %" PRIu64, consumed,
2140 (uint64_t)hstate->
conn->in_data_counter);
2157 if (tx_ud == NULL) {
2162 tx_ud->
tx_data.file_tx = STREAM_TOSERVER | STREAM_TOCLIENT;
2163 htp_tx_set_user_data(tx, tx_ud);
2172 static int HTPCallbackResponseStart(htp_tx_t *tx)
2174 HtpState *hstate = htp_connp_get_user_data(tx->connp);
2175 if (hstate == NULL) {
2179 uint64_t consumed = hstate->
slice->offset + htp_connp_res_data_consumed(hstate->
connp);
2180 SCLogDebug(
"HTTP response start: data offset %" PRIu64
", out_data_counter %" PRIu64, consumed,
2181 (uint64_t)hstate->
conn->out_data_counter);
2196 if (tx_ud == NULL) {
2203 htp_tx_set_user_data(tx, tx_ud);
2214 static int HTPCallbackRequestComplete(htp_tx_t *tx)
2222 HtpState *hstate = htp_connp_get_user_data(tx->connp);
2223 if (hstate == NULL) {
2227 const uint64_t abs_right_edge =
2228 hstate->
slice->offset + htp_connp_req_data_consumed(hstate->
connp);
2236 SCLogDebug(
"HTTP request complete: data offset %" PRIu64
", request_size %" PRIu64,
2238 SCLogDebug(
"frame %p/%" PRIi64
" setting len to %" PRIu64, frame, frame->
id,
2240 frame->
len = (int64_t)request_size;
2246 SCLogDebug(
"transaction_cnt %"PRIu64
", list_size %"PRIu64,
2251 HTPErrorCheckTxRequestFlags(hstate, tx);
2256 SCLogDebug(
"closing file that was being stored");
2257 (void)
HTPFileClose(hstate, htud, NULL, 0, 0, STREAM_TOSERVER);
2259 if (abs_right_edge < (uint64_t)UINT32_MAX) {
2261 hstate->
f->
protoctx, STREAM_TOSERVER, (uint32_t)abs_right_edge);
2279 static int HTPCallbackResponseComplete(htp_tx_t *tx)
2283 HtpState *hstate = htp_connp_get_user_data(tx->connp);
2284 if (hstate == NULL) {
2291 const uint64_t abs_right_edge =
2292 hstate->
slice->offset + htp_connp_res_data_consumed(hstate->
connp);
2299 SCLogDebug(
"HTTP response complete: data offset %" PRIu64
", response_size %" PRIu64,
2301 SCLogDebug(
"frame %p/%" PRIi64
" setting len to %" PRIu64, frame, frame->
id,
2303 frame->
len = (int64_t)response_size;
2311 SCLogDebug(
"closing file that was being stored");
2312 (void)
HTPFileClose(hstate, htud, NULL, 0, 0, STREAM_TOCLIENT);
2322 if (tx->request_method_number == HTP_M_CONNECT) {
2325 if ((tx->response_status_number >= 200) &&
2326 (tx->response_status_number < 300) &&
2329 if (tx->request_port_number != -1) {
2330 dp = (uint16_t)tx->request_port_number;
2337 tx->request_progress = HTP_REQUEST_COMPLETE;
2338 tx->response_progress = HTP_RESPONSE_COMPLETE;
2346 static int HTPCallbackRequestLine(htp_tx_t *tx)
2349 bstr *request_uri_normalized;
2350 HtpState *hstate = htp_connp_get_user_data(tx->connp);
2354 if (request_uri_normalized == NULL)
2357 tx_ud = htp_tx_get_user_data(tx);
2359 bstr_free(request_uri_normalized);
2367 HTPErrorCheckTxRequestFlags(hstate, tx);
2372 static int HTPCallbackDoubleDecodeUriPart(htp_tx_t *tx, bstr *part)
2378 size_t prevlen = bstr_len(part);
2379 htp_status_t res = htp_urldecode_inplace(tx->cfg, HTP_DECODER_URLENCODED, part, &
flags);
2381 if (res == HTP_OK && prevlen > bstr_len(part)) {
2385 HtpState *s = htp_connp_get_user_data(tx->connp);
2388 HTPSetEvent(s, htud, STREAM_TOSERVER,
2395 static int HTPCallbackDoubleDecodeQuery(htp_tx_t *tx)
2397 if (tx->parsed_uri == NULL)
2400 return HTPCallbackDoubleDecodeUriPart(tx, tx->parsed_uri->query);
2403 static int HTPCallbackDoubleDecodePath(htp_tx_t *tx)
2405 if (tx->parsed_uri == NULL)
2408 return HTPCallbackDoubleDecodeUriPart(tx, tx->parsed_uri->path);
2411 static int HTPCallbackRequestHeaderData(htp_tx_data_t *tx_data)
2414 if (tx_data->len == 0 || tx_data->tx == NULL)
2418 if (tx_ud == NULL) {
2430 tx_data->data, tx_data->len);
2433 if (tx_data->tx && tx_data->tx->flags) {
2434 HtpState *hstate = htp_connp_get_user_data(tx_data->tx->connp);
2435 HTPErrorCheckTxRequestFlags(hstate, tx_data->tx);
2440 static int HTPCallbackResponseHeaderData(htp_tx_data_t *tx_data)
2443 if (tx_data->len == 0 || tx_data->tx == NULL)
2447 if (tx_ud == NULL) {
2459 tx_data->data, tx_data->len);
2468 static void HTPConfigSetDefaultsPhase1(
HTPCfgRec *cfg_prec)
2485 htp_config_register_request_header_data(cfg_prec->
cfg, HTPCallbackRequestHeaderData);
2486 htp_config_register_request_trailer_data(cfg_prec->
cfg, HTPCallbackRequestHeaderData);
2487 htp_config_register_response_header_data(cfg_prec->
cfg, HTPCallbackResponseHeaderData);
2488 htp_config_register_response_trailer_data(cfg_prec->
cfg, HTPCallbackResponseHeaderData);
2490 htp_config_register_request_trailer(cfg_prec->
cfg, HTPCallbackRequestHasTrailer);
2491 htp_config_register_response_trailer(cfg_prec->
cfg, HTPCallbackResponseHasTrailer);
2493 htp_config_register_request_body_data(cfg_prec->
cfg, HTPCallbackRequestBodyData);
2494 htp_config_register_response_body_data(cfg_prec->
cfg, HTPCallbackResponseBodyData);
2496 htp_config_register_request_start(cfg_prec->
cfg, HTPCallbackRequestStart);
2497 htp_config_register_request_complete(cfg_prec->
cfg, HTPCallbackRequestComplete);
2499 htp_config_register_response_start(cfg_prec->
cfg, HTPCallbackResponseStart);
2500 htp_config_register_response_complete(cfg_prec->
cfg, HTPCallbackResponseComplete);
2502 htp_config_set_parse_request_cookies(cfg_prec->
cfg, 0);
2505 htp_config_set_plusspace_decode(cfg_prec->
cfg, HTP_DECODER_URLENCODED, 0);
2507 htp_config_set_request_decompression(cfg_prec->
cfg, 1);
2508 #ifdef HAVE_HTP_CONFIG_SET_LZMA_LAYERS
2512 #ifdef HAVE_HTP_CONFIG_SET_LZMA_MEMLIMIT
2513 htp_config_set_lzma_memlimit(cfg_prec->
cfg,
2516 #ifdef HAVE_HTP_CONFIG_SET_COMPRESSION_BOMB_LIMIT
2517 htp_config_set_compression_bomb_limit(cfg_prec->
cfg,
2520 #ifdef HAVE_HTP_CONFIG_SET_COMPRESSION_TIME_LIMIT
2523 #ifdef HAVE_HTP_CONFIG_SET_MAX_TX
2524 #define HTP_CONFIG_DEFAULT_MAX_TX_LIMIT 512
2525 htp_config_set_max_tx(cfg_prec->
cfg, HTP_CONFIG_DEFAULT_MAX_TX_LIMIT);
2533 htp_config_set_field_limits(cfg_prec->
cfg,
2542 static int RandomGetWrap(
void)
2548 }
while(r >= ULONG_MAX - (ULONG_MAX % RAND_MAX));
2550 return r % RAND_MAX;
2559 static void HTPConfigSetDefaultsPhase2(
const char *name,
HTPCfgRec *cfg_prec)
2565 long int r = RandomGetWrap();
2567 ((
double)r / RAND_MAX - 0.5) * rdrange / 100);
2569 r = RandomGetWrap();
2571 ((
double)r / RAND_MAX - 0.5) * rdrange / 100);
2572 SCLogConfig(
"'%s' server has 'request-body-minimal-inspect-size' set to"
2573 " %u and 'request-body-inspect-window' set to %u after"
2577 r = RandomGetWrap();
2579 ((
double)r / RAND_MAX - 0.5) * rdrange / 100);
2581 r = RandomGetWrap();
2583 ((
double)r / RAND_MAX - 0.5) * rdrange / 100);
2585 SCLogConfig(
"'%s' server has 'response-body-minimal-inspect-size' set to"
2586 " %u and 'response-body-inspect-window' set to %u after"
2591 htp_config_register_request_line(cfg_prec->
cfg, HTPCallbackRequestLine);
2598 if (cfg_prec == NULL || s == NULL || tree == NULL)
2606 if (strcasecmp(
"address", p->
name) == 0) {
2614 if (strchr(pval->
val,
':') != NULL) {
2615 SCLogDebug(
"LIBHTP adding ipv6 server %s at %s: %p",
2619 "add ipv6 server %s, ignoring",
2623 SCLogDebug(
"LIBHTP adding ipv4 server %s at %s: %p",
2627 "to add ipv4 server %s, ignoring",
2633 }
else if (strcasecmp(
"personality", p->
name) == 0) {
2635 int personality = HTPLookupPersonality(p->
val);
2639 if (personality >= 0) {
2642 if (htp_config_set_server_personality(cfg_prec->
cfg, personality) == HTP_ERROR){
2644 "personality \"%s\", ignoring",
2648 HTPLookupPersonalityString(personality));
2654 htp_config_set_convert_lowercase(cfg_prec->
cfg, HTP_DECODER_URL_PATH, 0);
2662 }
else if (strcasecmp(
"request-body-limit", p->
name) == 0 ||
2663 strcasecmp(
"request_body_limit", p->
name) == 0) {
2665 SCLogError(
"Error parsing request-body-limit "
2666 "from conf file - %s. Killing engine",
2671 }
else if (strcasecmp(
"response-body-limit", p->
name) == 0) {
2673 SCLogError(
"Error parsing response-body-limit "
2674 "from conf file - %s. Killing engine",
2679 }
else if (strcasecmp(
"request-body-minimal-inspect-size", p->
name) == 0) {
2681 SCLogError(
"Error parsing request-body-minimal-inspect-size "
2682 "from conf file - %s. Killing engine",
2687 }
else if (strcasecmp(
"request-body-inspect-window", p->
name) == 0) {
2689 SCLogError(
"Error parsing request-body-inspect-window "
2690 "from conf file - %s. Killing engine",
2695 }
else if (strcasecmp(
"double-decode-query", p->
name) == 0) {
2697 htp_config_register_request_line(cfg_prec->
cfg,
2698 HTPCallbackDoubleDecodeQuery);
2701 }
else if (strcasecmp(
"double-decode-path", p->
name) == 0) {
2703 htp_config_register_request_line(cfg_prec->
cfg,
2704 HTPCallbackDoubleDecodePath);
2707 }
else if (strcasecmp(
"response-body-minimal-inspect-size", p->
name) == 0) {
2709 SCLogError(
"Error parsing response-body-minimal-inspect-size "
2710 "from conf file - %s. Killing engine",
2715 }
else if (strcasecmp(
"response-body-inspect-window", p->
name) == 0) {
2717 SCLogError(
"Error parsing response-body-inspect-window "
2718 "from conf file - %s. Killing engine",
2723 }
else if (strcasecmp(
"response-body-decompress-layer-limit", p->
name) == 0) {
2726 SCLogError(
"Error parsing response-body-inspect-window "
2727 "from conf file - %s. Killing engine",
2731 #ifdef HAVE_HTP_CONFIG_SET_RESPONSE_DECOMPRESSION_LAYER_LIMIT
2732 htp_config_set_response_decompression_layer_limit(cfg_prec->
cfg, value);
2734 SCLogWarning(
"can't set response-body-decompress-layer-limit "
2735 "to %u, libhtp version too old",
2738 }
else if (strcasecmp(
"path-convert-backslash-separators", p->
name) == 0) {
2739 htp_config_set_backslash_convert_slashes(cfg_prec->
cfg,
2740 HTP_DECODER_URL_PATH,
2742 }
else if (strcasecmp(
"path-bestfit-replacement-char", p->
name) == 0) {
2743 if (strlen(p->
val) == 1) {
2744 htp_config_set_bestfit_replacement_byte(cfg_prec->
cfg,
2745 HTP_DECODER_URL_PATH,
2749 "for libhtp param path-bestfit-replacement-char");
2751 }
else if (strcasecmp(
"path-convert-lowercase", p->
name) == 0) {
2752 htp_config_set_convert_lowercase(cfg_prec->
cfg,
2753 HTP_DECODER_URL_PATH,
2755 }
else if (strcasecmp(
"path-nul-encoded-terminates", p->
name) == 0) {
2756 htp_config_set_nul_encoded_terminates(cfg_prec->
cfg,
2757 HTP_DECODER_URL_PATH,
2759 }
else if (strcasecmp(
"path-nul-raw-terminates", p->
name) == 0) {
2760 htp_config_set_nul_raw_terminates(cfg_prec->
cfg,
2761 HTP_DECODER_URL_PATH,
2763 }
else if (strcasecmp(
"path-separators-compress", p->
name) == 0) {
2764 htp_config_set_path_separators_compress(cfg_prec->
cfg,
2765 HTP_DECODER_URL_PATH,
2767 }
else if (strcasecmp(
"path-separators-decode", p->
name) == 0) {
2768 htp_config_set_path_separators_decode(cfg_prec->
cfg,
2769 HTP_DECODER_URL_PATH,
2771 }
else if (strcasecmp(
"path-u-encoding-decode", p->
name) == 0) {
2772 htp_config_set_u_encoding_decode(cfg_prec->
cfg,
2773 HTP_DECODER_URL_PATH,
2775 }
else if (strcasecmp(
"path-url-encoding-invalid-handling", p->
name) == 0) {
2776 enum htp_url_encoding_handling_t handling;
2777 if (strcasecmp(p->
val,
"preserve_percent") == 0) {
2778 handling = HTP_URL_DECODE_PRESERVE_PERCENT;
2779 }
else if (strcasecmp(p->
val,
"remove_percent") == 0) {
2780 handling = HTP_URL_DECODE_REMOVE_PERCENT;
2781 }
else if (strcasecmp(p->
val,
"decode_invalid") == 0) {
2782 handling = HTP_URL_DECODE_PROCESS_INVALID;
2785 "for libhtp param path-url-encoding-invalid-handling");
2788 htp_config_set_url_encoding_invalid_handling(cfg_prec->
cfg,
2789 HTP_DECODER_URL_PATH,
2791 }
else if (strcasecmp(
"path-utf8-convert-bestfit", p->
name) == 0) {
2792 htp_config_set_utf8_convert_bestfit(cfg_prec->
cfg,
2793 HTP_DECODER_URL_PATH,
2795 }
else if (strcasecmp(
"uri-include-all", p->
name) == 0) {
2799 }
else if (strcasecmp(
"query-plusspace-decode", p->
name) == 0) {
2800 htp_config_set_plusspace_decode(cfg_prec->
cfg,
2801 HTP_DECODER_URLENCODED,
2803 }
else if (strcasecmp(
"meta-field-limit", p->
name) == 0) {
2807 "from conf file - %s. Killing engine",
2813 "from conf file cannot be 0. Killing engine");
2816 htp_config_set_field_limits(cfg_prec->
cfg,
2819 #ifdef HAVE_HTP_CONFIG_SET_LZMA_MEMLIMIT
2820 }
else if (strcasecmp(
"lzma-memlimit", p->
name) == 0) {
2823 FatalError(
"failed to parse 'lzma-memlimit' "
2824 "from conf file - %s.",
2829 "from conf file cannot be 0.");
2832 SCLogConfig(
"Setting HTTP LZMA memory limit to %"PRIu32
" bytes", limit);
2833 htp_config_set_lzma_memlimit(cfg_prec->
cfg, (
size_t)limit);
2835 #ifdef HAVE_HTP_CONFIG_SET_LZMA_LAYERS
2836 }
else if (strcasecmp(
"lzma-enabled", p->
name) == 0) {
2838 htp_config_set_lzma_layers(cfg_prec->
cfg, 1);
2843 "from conf file - %s.",
2846 SCLogConfig(
"Setting HTTP LZMA decompression layers to %" PRIu32
"", (
int)limit);
2847 htp_config_set_lzma_layers(cfg_prec->
cfg, limit);
2850 #ifdef HAVE_HTP_CONFIG_SET_COMPRESSION_BOMB_LIMIT
2851 }
else if (strcasecmp(
"compression-bomb-limit", p->
name) == 0) {
2854 FatalError(
"failed to parse 'compression-bomb-limit' "
2855 "from conf file - %s.",
2860 "from conf file cannot be 0.");
2863 SCLogConfig(
"Setting HTTP compression bomb limit to %"PRIu32
" bytes", limit);
2864 htp_config_set_compression_bomb_limit(cfg_prec->
cfg, (
size_t)limit);
2866 #ifdef HAVE_HTP_CONFIG_SET_COMPRESSION_TIME_LIMIT
2867 }
else if (strcasecmp(
"decompression-time-limit", p->
name) == 0) {
2871 FatalError(
"failed to parse 'decompression-time-limit' "
2872 "from conf file - %s.",
2875 SCLogConfig(
"Setting HTTP decompression time limit to %" PRIu32
" usec", limit);
2876 htp_config_set_compression_time_limit(cfg_prec->
cfg, (
size_t)limit);
2878 #ifdef HAVE_HTP_CONFIG_SET_MAX_TX
2879 }
else if (strcasecmp(
"max-tx", p->
name) == 0) {
2883 "from conf file - %s.",
2887 SCLogConfig(
"Setting HTTP max-tx limit to %" PRIu32
" bytes", limit);
2888 htp_config_set_max_tx(cfg_prec->
cfg, (
size_t)limit);
2890 }
else if (strcasecmp(
"randomize-inspection-sizes", p->
name) == 0) {
2894 }
else if (strcasecmp(
"randomize-inspection-range", p->
name) == 0) {
2897 (
const char *)p->
val, 0, 100) < 0) {
2899 "-inspection-range setting from conf file - \"%s\"."
2900 " It should be a valid integer less than or equal to 100."
2906 }
else if (strcasecmp(
"http-body-inline", p->
name) == 0) {
2912 if (strcmp(
"auto", p->
val) != 0) {
2921 }
else if (strcasecmp(
"swf-decompression", p->
name) == 0) {
2925 if (strcasecmp(
"enabled", pval->
name) == 0) {
2933 }
else if (strcasecmp(
"type", pval->
name) == 0) {
2934 if (strcasecmp(
"no", pval->
val) == 0) {
2936 }
else if (strcasecmp(
"deflate", pval->
val) == 0) {
2938 }
else if (strcasecmp(
"lzma", pval->
val) == 0) {
2940 }
else if (strcasecmp(
"both", pval->
val) == 0) {
2944 "swf-decompression.type: %s - "
2949 }
else if (strcasecmp(
"compress-depth", pval->
name) == 0) {
2951 SCLogError(
"Error parsing swf-decompression.compression-depth "
2952 "from conf file - %s. Killing engine",
2956 }
else if (strcasecmp(
"decompress-depth", pval->
name) == 0) {
2958 SCLogError(
"Error parsing swf-decompression.decompression-depth "
2959 "from conf file - %s. Killing engine",
2969 "default config: %s",
2981 cfglist.
next = NULL;
2988 if (NULL == cfgtree)
2992 cfglist.
cfg = htp_config_create();
2993 if (NULL == cfglist.
cfg) {
2994 FatalError(
"Failed to create HTP default config");
2997 HTPConfigSetDefaultsPhase1(&cfglist);
2998 if (
ConfGetNode(
"app-layer.protocols.http.libhtp") == NULL) {
2999 HTPConfigParseParameters(&cfglist,
ConfGetNode(
"libhtp.default-config"),
3002 HTPConfigParseParameters(&cfglist,
ConfGetNode(
"app-layer.protocols.http.libhtp.default-config"), cfgtree);
3004 HTPConfigSetDefaultsPhase2(
"default", &cfglist);
3010 if (server_config == NULL) {
3011 server_config =
ConfGetNode(
"libhtp.server-config");
3012 if (server_config == NULL) {
3013 SCLogDebug(
"LIBHTP Configuring %p", server_config);
3017 SCLogDebug(
"LIBHTP Configuring %p", server_config);
3036 cfglist.
next = htprec;
3039 cfglist.
next->
cfg = htp_config_create();
3040 if (NULL == cfglist.
next->
cfg) {
3041 FatalError(
"Failed to create HTP server config");
3044 HTPConfigSetDefaultsPhase1(htprec);
3045 HTPConfigParseParameters(htprec, s, cfgtree);
3046 HTPConfigSetDefaultsPhase2(s->
name, htprec);
3056 SCLogPerf(
"htp memory %"PRIu64
" (%"PRIu64
")", htp_state_memuse, htp_state_memcnt);
3067 static AppLayerGetFileState HTPGetTxFiles(
void *state,
void *txv, uint8_t direction)
3069 AppLayerGetFileState files = { .fc = NULL, .cfg = &
htp_sbcfg };
3070 htp_tx_t *tx = (htp_tx_t *)txv;
3073 if (direction & STREAM_TOCLIENT) {
3082 static int HTPStateGetAlstateProgress(
void *tx, uint8_t direction)
3084 if (direction & STREAM_TOSERVER)
3085 return ((htp_tx_t *)tx)->request_progress;
3087 return ((htp_tx_t *)tx)->response_progress;
3090 static uint64_t HTPStateGetTxCnt(
void *alstate)
3094 if (http_state != NULL && http_state->
conn != NULL) {
3095 const int64_t size = (int64_t)htp_list_size(http_state->
conn->transactions);
3099 return (uint64_t)size + http_state->
tx_freed;
3105 static void *HTPStateGetTx(
void *alstate, uint64_t tx_id)
3109 if (http_state != NULL && http_state->
conn != NULL && tx_id >= http_state->
tx_freed)
3110 return htp_list_get(http_state->
conn->transactions, tx_id - http_state->
tx_freed);
3119 if (http_state != NULL && http_state->
conn != NULL) {
3120 size_t txid = HTPStateGetTxCnt(http_state);
3122 return htp_list_get(http_state->
conn->transactions, txid - http_state->
tx_freed - 1);
3128 static int HTPStateGetEventInfo(
const char *event_name,
3129 int *event_id, AppLayerEventType *event_type)
3132 if (*event_id == -1) {
3134 "http's enum map table.",
3140 *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
3145 static int HTPStateGetEventInfoById(
int event_id,
const char **event_name,
3146 AppLayerEventType *event_type)
3149 if (*event_name == NULL) {
3151 "http's enum map table.",
3157 *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
3164 htp_tx_t *tx = (htp_tx_t *)vtx;
3172 static AppLayerStateData *HTPGetStateData(
void *vstate)
3178 static int HTPRegisterPatternsForProtocolDetection(
void)
3180 const char *methods[] = {
"GET",
"PUT",
"POST",
"HEAD",
"TRACE",
"OPTIONS",
3181 "CONNECT",
"DELETE",
"PATCH",
"PROPFIND",
"PROPPATCH",
"MKCOL",
3182 "COPY",
"MOVE",
"LOCK",
"UNLOCK",
"CHECKOUT",
"UNCHECKOUT",
"CHECKIN",
3183 "UPDATE",
"LABEL",
"REPORT",
"MKWORKSPACE",
"MKACTIVITY",
"MERGE",
3184 "INVALID",
"VERSION-CONTROL",
"BASELINE-CONTROL", NULL};
3185 const char *spacings[] = {
"|20|",
"|09|", NULL };
3186 const char *versions[] = {
"HTTP/0.9",
"HTTP/1.0",
"HTTP/1.1", NULL };
3191 int register_result;
3192 char method_buffer[32] =
"";
3195 for (methods_pos = 0; methods[methods_pos]; methods_pos++) {
3196 for (spacings_pos = 0; spacings[spacings_pos]; spacings_pos++) {
3199 snprintf(method_buffer,
sizeof(method_buffer),
"%s%s", methods[methods_pos], spacings[spacings_pos]);
3206 method_buffer, (uint16_t)strlen(method_buffer) - 3, 0, STREAM_TOSERVER);
3207 if (register_result < 0) {
3214 for (versions_pos = 0; versions[versions_pos]; versions_pos++) {
3216 versions[versions_pos], (uint16_t)strlen(versions[versions_pos]), 0,
3218 if (register_result < 0) {
3234 const char *proto_name =
"http";
3239 if (HTPRegisterPatternsForProtocolDetection() < 0)
3242 SCLogInfo(
"Protocol detection and parser disabled for %s protocol",
3257 ALPROTO_HTTP1, HTP_REQUEST_COMPLETE, HTP_RESPONSE_COMPLETE);
3269 IPPROTO_TCP,
ALPROTO_HTTP1, STREAM_TOSERVER, HTPHandleRequestData);
3271 IPPROTO_TCP,
ALPROTO_HTTP1, STREAM_TOCLIENT, HTPHandleResponseData);
3277 IPPROTO_TCP,
ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_TOCLIENT);
3280 IPPROTO_TCP,
ALPROTO_HTTP1, HTTPGetFrameIdByName, HTTPGetFrameNameById);
3284 SCLogInfo(
"Parsed disabled for %s protocol. Protocol detection"
3285 "still on.", proto_name);
3301 cfglist_backup = cfglist;
3308 cfglist = cfglist_backup;
3315 static int HTPParserTest01(
void)
3317 uint8_t httpbuf1[] =
"POST / HTTP/1.0\r\nUser-Agent: Victor/1.0\r\n\r\nPost"
3319 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3322 memset(&ssn, 0,
sizeof(ssn));
3330 f->
proto = IPPROTO_TCP;
3336 for (u = 0; u < httplen1; u++) {
3340 flags = STREAM_TOSERVER|STREAM_START;
3341 else if (u == (httplen1 - 1))
3342 flags = STREAM_TOSERVER|STREAM_EOF;
3344 flags = STREAM_TOSERVER;
3353 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3356 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3359 FAIL_IF(strcmp(bstr_util_strdup_to_c(h->value),
"Victor/1.0"));
3360 FAIL_IF(tx->request_method_number != HTP_M_POST);
3361 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_0);
3370 static int HTPParserTest01b(
void)
3372 uint8_t httpbuf1[] =
"POST / HTTP/1.0\r\nUser-Agent:\r\n Victor/1.0\r\n\r\nPost"
3374 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3377 memset(&ssn, 0,
sizeof(ssn));
3385 f->
proto = IPPROTO_TCP;
3390 uint8_t
flags =STREAM_TOSERVER|STREAM_START|STREAM_EOF;
3397 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3400 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3403 FAIL_IF(strcmp(bstr_util_strdup_to_c(h->value),
"Victor/1.0"));
3404 FAIL_IF(tx->request_method_number != HTP_M_POST);
3405 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_0);
3414 static int HTPParserTest01c(
void)
3416 uint8_t httpbuf1[] =
"POST / HTTP/1.0\r\nUser-Agent:\r\n Victor/1.0\r\n\r\nPost"
3418 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3421 memset(&ssn, 0,
sizeof(ssn));
3429 f->
proto = IPPROTO_TCP;
3435 for (u = 0; u < httplen1; u++) {
3439 flags = STREAM_TOSERVER|STREAM_START;
3440 else if (u == (httplen1 - 1))
3441 flags = STREAM_TOSERVER|STREAM_EOF;
3443 flags = STREAM_TOSERVER;
3452 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3455 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3458 FAIL_IF(strcmp(bstr_util_strdup_to_c(h->value),
"Victor/1.0"));
3459 FAIL_IF(tx->request_method_number != HTP_M_POST);
3460 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_0);
3470 static int HTPParserTest01a(
void)
3474 uint8_t httpbuf1[] =
" POST / HTTP/1.0\r\nUser-Agent: Victor/1.0\r\n\r\nPost"
3476 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3482 memset(&ssn, 0,
sizeof(ssn));
3484 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
3488 f->
proto = IPPROTO_TCP;
3494 for (u = 0; u < httplen1; u++) {
3498 flags = STREAM_TOSERVER|STREAM_START;
3499 else if (u == (httplen1 - 1))
3500 flags = STREAM_TOSERVER|STREAM_EOF;
3502 flags = STREAM_TOSERVER;
3506 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
3513 if (htp_state == NULL) {
3514 printf(
"no http state: ");
3518 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3519 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3520 if (strcmp(bstr_util_strdup_to_c(h->value),
"Victor/1.0")
3521 || tx->request_method_number != HTP_M_POST ||
3522 tx->request_protocol_number != HTP_PROTOCOL_1_0)
3524 printf(
"expected header value: Victor/1.0 and got %s: and expected"
3525 " method: POST and got %s, expected protocol number HTTP/1.0"
3526 " and got: %s \n", bstr_util_strdup_to_c(h->value),
3527 bstr_util_strdup_to_c(tx->request_method),
3528 bstr_util_strdup_to_c(tx->request_protocol));
3541 static int HTPParserTest02(
void)
3545 uint8_t httpbuf1[] =
"POST";
3546 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3551 memset(&ssn, 0,
sizeof(ssn));
3553 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
3557 f->
proto = IPPROTO_TCP;
3563 STREAM_TOSERVER | STREAM_START | STREAM_EOF, httpbuf1, httplen1);
3565 printf(
"toserver chunk 1 returned %" PRId32
", expected 0: ", r);
3570 if (http_state == NULL) {
3571 printf(
"no http state: ");
3575 htp_tx_t *tx = HTPStateGetTx(http_state, 0);
3577 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3581 char *method = bstr_util_strdup_to_c(tx->request_method);
3584 FAIL_IF(strcmp(method,
"POST") != 0);
3598 static int HTPParserTest03(
void)
3602 uint8_t httpbuf1[] =
"HELLO / HTTP/1.0\r\n";
3603 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3609 memset(&ssn, 0,
sizeof(ssn));
3611 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
3615 f->
proto = IPPROTO_TCP;
3621 for (u = 0; u < httplen1; u++) {
3624 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
3625 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
3626 else flags = STREAM_TOSERVER;
3630 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
3636 if (htp_state == NULL) {
3637 printf(
"no http state: ");
3641 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3643 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3644 if (tx->request_method_number != HTP_M_UNKNOWN ||
3645 h != NULL || tx->request_protocol_number != HTP_PROTOCOL_1_0)
3647 printf(
"expected method M_UNKNOWN and got %s: , expected protocol "
3648 "HTTP/1.0 and got %s \n", bstr_util_strdup_to_c(tx->request_method),
3649 bstr_util_strdup_to_c(tx->request_protocol));
3663 static int HTPParserTest04(
void)
3668 uint8_t httpbuf1[] =
"World!\r\n";
3669 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3674 memset(&ssn, 0,
sizeof(ssn));
3676 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
3680 f->
proto = IPPROTO_TCP;
3686 STREAM_TOSERVER | STREAM_START | STREAM_EOF, httpbuf1, httplen1);
3692 if (htp_state == NULL) {
3693 printf(
"no http state: ");
3697 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3698 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3699 if (tx->request_method_number != HTP_M_UNKNOWN ||
3700 h != NULL || tx->request_protocol_number != HTP_PROTOCOL_0_9)
3702 printf(
"expected method M_UNKNOWN and got %s: , expected protocol "
3703 "NULL and got %s \n", bstr_util_strdup_to_c(tx->request_method),
3704 bstr_util_strdup_to_c(tx->request_protocol));
3718 static int HTPParserTest05(
void)
3720 uint8_t httpbuf1[] =
"POST / HTTP/1.0\r\nUser-Agent: Victor/1.0\r\nContent-Length: 17\r\n\r\n";
3721 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3722 uint8_t httpbuf2[] =
"Post D";
3723 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
3724 uint8_t httpbuf3[] =
"ata is c0oL!";
3725 uint32_t httplen3 =
sizeof(httpbuf3) - 1;
3727 uint8_t httpbuf4[] =
"HTTP/1.0 200 OK\r\nServer: VictorServer/1.0\r\n\r\n";
3728 uint32_t httplen4 =
sizeof(httpbuf4) - 1;
3729 uint8_t httpbuf5[] =
"post R";
3730 uint32_t httplen5 =
sizeof(httpbuf5) - 1;
3731 uint8_t httpbuf6[] =
"esults are tha bomb!";
3732 uint32_t httplen6 =
sizeof(httpbuf6) - 1;
3735 memset(&ssn, 0,
sizeof(ssn));
3743 f->
proto = IPPROTO_TCP;
3773 htp_tx_t *tx = HTPStateGetTx(http_state, 0);
3775 FAIL_IF_NOT(tx->request_method_number == HTP_M_POST);
3776 FAIL_IF_NOT(tx->request_protocol_number == HTP_PROTOCOL_1_0);
3778 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3791 static int HTPParserTest06(
void)
3793 uint8_t httpbuf1[] =
"GET /ld/index.php?id=412784631&cid=0064&version=4&"
3794 "name=try HTTP/1.1\r\nAccept: */*\r\nUser-Agent: "
3795 "LD-agent\r\nHost: 209.205.196.16\r\n\r\n";
3796 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3797 uint8_t httpbuf2[] =
"HTTP/1.1 200 OK\r\nDate: Sat, 03 Oct 2009 10:16:02 "
3799 "Server: Apache/1.3.37 (Unix) mod_ssl/2.8.28 "
3800 "OpenSSL/0.9.7a PHP/4.4.7 mod_perl/1.29 "
3801 "FrontPage/5.0.2.2510\r\n"
3802 "X-Powered-By: PHP/4.4.7\r\nTransfer-Encoding: "
3804 "Content-Type: text/html\r\n\r\n"
3806 "W2dyb3VwMV0NCnBob25lMT1wMDB3ODgyMTMxMzAyMTINCmxvZ2lu"
3807 "MT0NCnBhc3N3b3JkMT0NCnBob25lMj1wMDB3ODgyMTMxMzAyMTIN"
3808 "CmxvZ2luMj0NCnBhc3N3b3JkMj0NCnBob25lMz0NCmxvZ2luMz0N"
3809 "CnBhc3N3b3JkMz0NCnBob25lND0NCmxvZ2luND0NCnBhc3N3b3Jk"
3810 "ND0NCnBob25lNT0NCmxvZ2luNT0NCnBhc3N3b3JkNT0NCnBob25l"
3811 "Nj0NCmxvZ2luNj0NCnBhc3N3b3JkNj0NCmNhbGxfdGltZTE9MzIN"
3812 "CmNhbGxfdGltZTI9MjMyDQpkYXlfbGltaXQ9NQ0KbW9udGhfbGlt"
3813 "aXQ9MTUNCltncm91cDJdDQpwaG9uZTE9DQpsb2dpbjE9DQpwYXNz"
3814 "d29yZDE9DQpwaG9uZTI9DQpsb2dpbjI9DQpwYXNzd29yZDI9DQpw"
3815 "aG9uZTM9DQpsb2dpbjM9DQpwYXNzd29yZDM9DQpwaG9uZTQ9DQps"
3816 "b2dpbjQ9DQpwYXNzd29yZDQ9DQpwaG9uZTU9DQpsb2dpbjU9DQpw"
3817 "YXNzd29yZDU9DQpwaG9uZTY9DQpsb2dpbjY9DQpwYXNzd29yZDY9"
3818 "DQpjYWxsX3RpbWUxPQ0KY2FsbF90aW1lMj0NCmRheV9saW1pdD0N"
3819 "Cm1vbnRoX2xpbWl0PQ0KW2dyb3VwM10NCnBob25lMT0NCmxvZ2lu"
3820 "MT0NCnBhc3N3b3JkMT0NCnBob25lMj0NCmxvZ2luMj0NCnBhc3N3"
3821 "b3JkMj0NCnBob25lMz0NCmxvZ2luMz0NCnBhc3N3b3JkMz0NCnBo"
3822 "b25lND0NCmxvZ2luND0NCnBhc3N3b3JkND0NCnBob25lNT0NCmxv"
3823 "Z2luNT0NCnBhc3N3b3JkNT0NCnBob25lNj0NCmxvZ2luNj0NCnBh"
3824 "c3N3b3JkNj0NCmNhbGxfdGltZTE9DQpjYWxsX3RpbWUyPQ0KZGF5"
3825 "X2xpbWl0PQ0KbW9udGhfbGltaXQ9DQpbZ3JvdXA0XQ0KcGhvbmUx"
3826 "PQ0KbG9naW4xPQ0KcGFzc3dvcmQxPQ0KcGhvbmUyPQ0KbG9naW4y"
3827 "PQ0KcGFzc3dvcmQyPQ0KcGhvbmUzPQ0KbG9naW4zPQ0KcGFzc3dv"
3828 "cmQzPQ0KcGhvbmU0PQ0KbG9naW40PQ0KcGFzc3dvcmQ0PQ0KcGhv"
3829 "bmU1PQ0KbG9naW41PQ0KcGFzc3dvcmQ1PQ0KcGhvbmU2PQ0KbG9n"
3830 "aW42PQ0KcGFzc3dvcmQ2PQ0KY2FsbF90aW1lMT0NCmNhbGxfdGlt"
3831 "ZTI9DQpkYXlfbGltaXQ9DQptb250aF9saW1pdD0NCltmaWxlc10N"
3832 "Cmxpbms9aHR0cDovLzIwOS4yMDUuMTk2LjE2L2xkL2dldGJvdC5w"
3833 "aHA=\r\n0\r\n\r\n";
3834 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
3840 memset(&ssn, 0,
sizeof(ssn));
3845 f->
proto = IPPROTO_TCP;
3860 htp_tx_t *tx = HTPStateGetTx(http_state, 0);
3863 FAIL_IF(tx->request_method_number != HTP_M_GET);
3864 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_1);
3866 FAIL_IF(tx->response_status_number != 200);
3867 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_1);
3869 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3880 static int HTPParserTest07(
void)
3884 uint8_t httpbuf1[] =
"GET /awstats.pl?/migratemigrate%20=%20| HTTP/1.0\r\n\r\n";
3885 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3891 memset(&ssn, 0,
sizeof(ssn));
3893 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
3897 f->
proto = IPPROTO_TCP;
3903 for (u = 0; u < httplen1; u++) {
3907 flags = STREAM_TOSERVER|STREAM_START;
3908 else if (u == (httplen1 - 1))
3909 flags = STREAM_TOSERVER|STREAM_EOF;
3911 flags = STREAM_TOSERVER;
3915 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
3922 if (htp_state == NULL) {
3923 printf(
"no http state: ");
3927 uint8_t ref[] =
"/awstats.pl?/migratemigrate = |";
3928 size_t reflen =
sizeof(ref) - 1;
3930 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3936 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
3945 printf(
"normalized uri \"");
3967 static int HTPParserTest08(
void)
3971 uint8_t httpbuf1[] =
"GET /secondhouse/image/js/\%ce\%de\%ce\%fd_RentCity.js?v=2011.05.02 HTTP/1.0\r\n\r\n";
3972 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3994 memset(&ssn, 0,
sizeof(ssn));
3996 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
4000 f->
proto = IPPROTO_TCP;
4006 flags = STREAM_TOSERVER|STREAM_START|STREAM_EOF;
4010 printf(
"toserver chunk returned %" PRId32
", expected"
4017 if (htp_state == NULL) {
4018 printf(
"no http state: ");
4023 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4048 static int HTPParserTest09(
void)
4052 uint8_t httpbuf1[] =
"GET /secondhouse/image/js/\%ce\%de\%ce\%fd_RentCity.js?v=2011.05.02 HTTP/1.0\r\n\r\n";
4053 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4063 personality: Apache_2_2\n\
4076 memset(&ssn, 0,
sizeof(ssn));
4078 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
4082 f->
proto = IPPROTO_TCP;
4088 flags = STREAM_TOSERVER|STREAM_START|STREAM_EOF;
4092 printf(
"toserver chunk returned %" PRId32
", expected"
4098 if (htp_state == NULL) {
4099 printf(
"no http state: ");
4103 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4128 static int HTPParserTest10(
void)
4132 uint8_t httpbuf1[] =
"GET / HTTP/1.0\r\nHost:www.google.com\r\n\r\n";
4133 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4139 memset(&ssn, 0,
sizeof(ssn));
4141 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
4145 f->
proto = IPPROTO_TCP;
4151 for (u = 0; u < httplen1; u++) {
4155 flags = STREAM_TOSERVER|STREAM_START;
4156 else if (u == (httplen1 - 1))
4157 flags = STREAM_TOSERVER|STREAM_EOF;
4159 flags = STREAM_TOSERVER;
4163 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
4170 if (htp_state == NULL) {
4171 printf(
"no http state: ");
4175 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4176 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
4181 char *name = bstr_util_strdup_to_c(h->name);
4186 if (strcmp(name,
"Host") != 0) {
4187 printf(
"header name not \"Host\", instead \"%s\": ", name);
4193 char *value = bstr_util_strdup_to_c(h->value);
4194 if (value == NULL) {
4198 if (strcmp(value,
"www.google.com") != 0) {
4199 printf(
"header value not \"www.google.com\", instead \"%s\": ", value);
4216 static int HTPParserTest11(
void)
4220 uint8_t httpbuf1[] =
"GET /%2500 HTTP/1.0\r\n\r\n";
4221 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4227 memset(&ssn, 0,
sizeof(ssn));
4229 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
4233 f->
proto = IPPROTO_TCP;
4239 for (u = 0; u < httplen1; u++) {
4243 flags = STREAM_TOSERVER|STREAM_START;
4244 else if (u == (httplen1 - 1))
4245 flags = STREAM_TOSERVER|STREAM_EOF;
4247 flags = STREAM_TOSERVER;
4251 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
4258 if (htp_state == NULL) {
4259 printf(
"no http state: ");
4263 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4269 printf(
"normalized uri len should be 2, is %"PRIuMAX,
4279 printf(
"normalized uri \"");
4297 static int HTPParserTest12(
void)
4301 uint8_t httpbuf1[] =
"GET /?a=%2500 HTTP/1.0\r\n\r\n";
4302 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4308 memset(&ssn, 0,
sizeof(ssn));
4310 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
4314 f->
proto = IPPROTO_TCP;
4320 for (u = 0; u < httplen1; u++) {
4324 flags = STREAM_TOSERVER|STREAM_START;
4325 else if (u == (httplen1 - 1))
4326 flags = STREAM_TOSERVER|STREAM_EOF;
4328 flags = STREAM_TOSERVER;
4332 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
4339 if (htp_state == NULL) {
4340 printf(
"no http state: ");
4344 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4350 printf(
"normalized uri len should be 5, is %"PRIuMAX,
4363 printf(
"normalized uri \"");
4381 static int HTPParserTest13(
void)
4385 uint8_t httpbuf1[] =
"GET / HTTP/1.0\r\nHost:www.google.com\rName: Value\r\n\r\n";
4386 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4392 memset(&ssn, 0,
sizeof(ssn));
4394 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
4398 f->
proto = IPPROTO_TCP;
4404 for (u = 0; u < httplen1; u++) {
4408 flags = STREAM_TOSERVER|STREAM_START;
4409 else if (u == (httplen1 - 1))
4410 flags = STREAM_TOSERVER|STREAM_EOF;
4412 flags = STREAM_TOSERVER;
4416 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
4423 if (htp_state == NULL) {
4424 printf(
"no http state: ");
4428 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4429 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
4434 char *name = bstr_util_strdup_to_c(h->name);
4439 if (strcmp(name,
"Host") != 0) {
4440 printf(
"header name not \"Host\", instead \"%s\": ", name);
4446 char *value = bstr_util_strdup_to_c(h->value);
4447 if (value == NULL) {
4451 if (strcmp(value,
"www.google.com\rName: Value") != 0) {
4452 printf(
"header value not \"www.google.com\", instead \"");
4470 static int HTPParserConfigTest01(
void)
4484 address: [192.168.1.0/24, 127.0.0.0/8, \"::1\"]\n\
4485 personality: Tomcat_6_0\n\
4490 - 192.168.10.0/24\n\
4491 personality: IIS_7_0\n\
4500 outputs =
ConfGetNode(
"libhtp.default-config.personality");
4501 if (outputs == NULL) {
4506 if (outputs == NULL) {
4514 if (strcmp(node->
name,
"0") != 0) {
4521 if (strcmp(node->
name,
"apache-tomcat") != 0) {
4529 if (node2 == NULL) {
4532 if (strcmp(node2->
val,
"Tomcat_6_0") != 0) {
4547 if (strcmp(n->
name,
"0") != 0) {
4550 if (strcmp(n->
val,
"192.168.1.0/24") != 0) {
4555 if (strcmp(n->
name,
"1") != 0) {
4558 if (strcmp(n->
val,
"127.0.0.0/8") != 0) {
4563 if (strcmp(n->
name,
"2") != 0) {
4566 if (strcmp(n->
val,
"::1") != 0) {
4577 if (outputs == NULL) {
4586 if (strcmp(node->
name,
"1") != 0) {
4593 if (strcmp(node->
name,
"iis7") != 0) {
4598 if (node2 == NULL) {
4601 if (strcmp(node2->
val,
"IIS_7_0") != 0) {
4618 if (strcmp(n->
name,
"0") != 0) {
4621 if (strcmp(n->
val,
"192.168.0.0/24") != 0) {
4626 if (strcmp(n->
name,
"1") != 0) {
4629 if (strcmp(n->
val,
"192.168.10.0/24") != 0) {
4649 static int HTPParserConfigTest02(
void)
4663 address: [192.168.1.0/24, 127.0.0.0/8, \"::1\"]\n\
4664 personality: Tomcat_6_0\n\
4669 - 192.168.10.0/24\n\
4670 personality: IIS_7_0\n\
4681 if (cfglist.
cfg == NULL) {
4682 printf(
"No default config created.\n");
4686 if (cfgtree == NULL) {
4687 printf(
"No config tree created.\n");
4691 htp_cfg_t *htp = cfglist.
cfg;
4694 void *user_data = NULL;
4696 addr =
"192.168.10.42";
4697 if (inet_pton(AF_INET, addr, buf) == 1) {
4699 if (user_data != NULL) {
4701 htp = htp_cfg_rec->
cfg;
4705 printf(
"Could not get config for: %s\n", addr);
4710 printf(
"Failed to parse address: %s\n", addr);
4716 if (inet_pton(AF_INET6, 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);
4745 static int HTPParserConfigTest03(
void)
4749 uint8_t httpbuf1[] =
"POST / HTTP/1.0\r\nUser-Agent: Victor/1.0\r\n\r\nPost"
4751 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4768 address: [192.168.1.0/24, 127.0.0.0/8, \"::1\"]\n\
4769 personality: Tomcat_6_0\n\
4774 - 192.168.10.0/24\n\
4775 personality: IIS_7_0\n\
4786 const char *addr =
"192.168.10.42";
4788 memset(&ssn, 0,
sizeof(ssn));
4794 f->
proto = IPPROTO_TCP;
4797 htp_cfg_t *htp = cfglist.
cfg;
4799 void *user_data = NULL;
4801 if (user_data != NULL) {
4803 htp = htp_cfg_rec->
cfg;
4807 printf(
"Could not get config for: %s\n", addr);
4814 for (u = 0; u < httplen1; u++) {
4817 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
4818 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
4819 else flags = STREAM_TOSERVER;
4823 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
4831 if (htp_state == NULL) {
4832 printf(
"no http state: ");
4837 if (HTPStateGetTxCnt(htp_state) != 2) {
4838 printf(
"HTPStateGetTxCnt(htp_state) failure\n");
4842 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4845 if (tx->cfg != htp) {
4846 printf(
"wrong HTP config (%p instead of %p - default=%p): ",
4847 tx->cfg, htp, cfglist.
cfg);
4850 tx = HTPStateGetTx(htp_state, 1);
4853 if (tx->cfg != htp) {
4854 printf(
"wrong HTP config (%p instead of %p - default=%p): ",
4855 tx->cfg, htp, cfglist.
cfg);
4874 static int HTPParserConfigTest04(
void)
4885 path-control-char-handling: status_400\n\
4886 path-convert-utf8: yes\n\
4887 path-invalid-encoding-handling: remove_percent\n\
4892 personality: Tomcat_6_0\n\
4893 path-invalid-utf8-handling: none\n\
4894 path-nul-encoded-handling: status_404\n\
4895 path-nul-raw-handling: status_400\n\
4898 personality: IIS_7_0\n\
4899 path-replacement-char: o\n\
4900 path-unicode-mapping: status_400\n\
4912 if (cfg_rec->
cfg->path_control_char_handling != STATUS_400 ||
4913 cfg_rec->
cfg->path_convert_utf8 != 1 ||
4914 cfg_rec->
cfg->path_invalid_encoding_handling != URL_DECODER_REMOVE_PERCENT) {
4915 printf(
"failed 1\n");
4919 cfg_rec = cfg_rec->
next;
4920 if (cfg_rec->
cfg->bestfit_replacement_char !=
'o' ||
4921 cfg_rec->
cfg->path_unicode_mapping != STATUS_400) {
4922 printf(
"failed 2\n");
4926 cfg_rec = cfg_rec->
next;
4927 if (cfg_rec->
cfg->path_invalid_utf8_handling != NONE ||
4928 cfg_rec->
cfg->path_nul_encoded_handling != STATUS_404 ||
4929 cfg_rec->
cfg->path_nul_raw_handling != STATUS_400) {
4930 printf(
"failed 3\n");
4952 static int HTPParserDecodingTest01(
void)
4954 uint8_t httpbuf1[] =
4955 "GET /abc%2fdef HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
4956 "GET /abc/def?ghi%2fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
4957 "GET /abc/def?ghi%252fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
4958 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4969 personality: Apache_2\n\
4977 const char *addr =
"4.3.2.1";
4978 memset(&ssn, 0,
sizeof(ssn));
4983 f->
proto = IPPROTO_TCP;
4988 for (uint32_t u = 0; u < httplen1; u++) {
4990 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
4991 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
4992 else flags = STREAM_TOSERVER;
5001 uint8_t ref1[] =
"/abc%2fdef";
5002 size_t reflen =
sizeof(ref1) - 1;
5004 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5014 uint8_t ref2[] =
"/abc/def?ghi/jkl";
5015 reflen =
sizeof(ref2) - 1;
5017 tx = HTPStateGetTx(htp_state, 1);
5027 uint8_t ref3[] =
"/abc/def?ghi%2fjkl";
5028 reflen =
sizeof(ref3) - 1;
5029 tx = HTPStateGetTx(htp_state, 2);
5050 static int HTPParserDecodingTest01a(
void)
5052 uint8_t httpbuf1[] =
"GET /abc%2fdef HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
5053 "GET /abc/def?ghi%2fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
5054 "GET /abc/def?ghi%252fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5055 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5066 personality: Apache_2\n\
5074 const char *addr =
"4.3.2.1";
5075 memset(&ssn, 0,
sizeof(ssn));
5080 f->
proto = IPPROTO_TCP;
5086 (STREAM_TOSERVER | STREAM_START | STREAM_EOF), httpbuf1, httplen1);
5092 uint8_t ref1[] =
"/abc%2fdef";
5093 size_t reflen =
sizeof(ref1) - 1;
5095 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5105 uint8_t ref2[] =
"/abc/def?ghi/jkl";
5106 reflen =
sizeof(ref2) - 1;
5108 tx = HTPStateGetTx(htp_state, 1);
5118 uint8_t ref3[] =
"/abc/def?ghi%2fjkl";
5119 reflen =
sizeof(ref3) - 1;
5120 tx = HTPStateGetTx(htp_state, 2);
5147 static int HTPParserDecodingTest02(
void)
5151 uint8_t httpbuf1[] =
5152 "GET /abc%2fdef HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
5153 "GET /abc/def?ghi%2fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
5154 "GET /abc/def?ghi%252fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5155 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5168 double-decode-path: no\n\
5169 double-decode-query: no\n\
5177 const char *addr =
"4.3.2.1";
5178 memset(&ssn, 0,
sizeof(ssn));
5184 f->
proto = IPPROTO_TCP;
5190 for (u = 0; u < httplen1; u++) {
5193 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
5194 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
5195 else flags = STREAM_TOSERVER;
5199 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5206 if (htp_state == NULL) {
5207 printf(
"no http state: ");
5211 uint8_t ref1[] =
"/abc/def";
5212 size_t reflen =
sizeof(ref1) - 1;
5214 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5220 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5229 printf(
"normalized uri \"");
5238 uint8_t ref2[] =
"/abc/def?ghi/jkl";
5239 reflen =
sizeof(ref2) - 1;
5241 tx = HTPStateGetTx(htp_state, 1);
5247 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5256 printf(
"normalized uri \"");
5265 uint8_t ref3[] =
"/abc/def?ghi%2fjkl";
5266 reflen =
sizeof(ref3) - 1;
5267 tx = HTPStateGetTx(htp_state, 2);
5273 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX
" (3): ",
5282 printf(
"normalized uri \"");
5311 static int HTPParserDecodingTest03(
void)
5315 uint8_t httpbuf1[] =
5316 "GET /abc%252fdef HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
5317 "GET /abc/def?ghi%252fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5318 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5331 double-decode-path: yes\n\
5332 double-decode-query: yes\n\
5340 const char *addr =
"4.3.2.1";
5341 memset(&ssn, 0,
sizeof(ssn));
5347 f->
proto = IPPROTO_TCP;
5353 for (u = 0; u < httplen1; u++) {
5356 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
5357 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
5358 else flags = STREAM_TOSERVER;
5362 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5369 if (htp_state == NULL) {
5370 printf(
"no http state: ");
5374 uint8_t ref1[] =
"/abc/def";
5375 size_t reflen =
sizeof(ref1) - 1;
5377 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5383 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5392 printf(
"normalized uri \"");
5401 uint8_t ref2[] =
"/abc/def?ghi/jkl";
5402 reflen =
sizeof(ref2) - 1;
5404 tx = HTPStateGetTx(htp_state, 1);
5410 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5419 printf(
"normalized uri \"");
5445 static int HTPParserDecodingTest04(
void)
5449 uint8_t httpbuf1[] =
5450 "GET /abc/def?a=http://www.abc.com/ HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5451 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5464 double-decode-path: yes\n\
5465 double-decode-query: yes\n\
5473 const char *addr =
"4.3.2.1";
5474 memset(&ssn, 0,
sizeof(ssn));
5480 f->
proto = IPPROTO_TCP;
5486 for (u = 0; u < httplen1; u++) {
5489 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
5490 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
5491 else flags = STREAM_TOSERVER;
5495 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5502 if (htp_state == NULL) {
5503 printf(
"no http state: ");
5507 uint8_t ref1[] =
"/abc/def?a=http://www.abc.com/";
5508 size_t reflen =
sizeof(ref1) - 1;
5510 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5516 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5525 printf(
"normalized uri \"");
5551 static int HTPParserDecodingTest05(
void)
5555 uint8_t httpbuf1[] =
5556 "GET /index?id=\\\"<script>alert(document.cookie)</script> HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5557 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5570 double-decode-path: yes\n\
5571 double-decode-query: yes\n\
5579 const char *addr =
"4.3.2.1";
5580 memset(&ssn, 0,
sizeof(ssn));
5586 f->
proto = IPPROTO_TCP;
5592 for (u = 0; u < httplen1; u++) {
5595 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
5596 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
5597 else flags = STREAM_TOSERVER;
5601 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5608 if (htp_state == NULL) {
5609 printf(
"no http state: ");
5613 uint8_t ref1[] =
"/index?id=\\\"<script>alert(document.cookie)</script>";
5614 size_t reflen =
sizeof(ref1) - 1;
5616 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5622 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5631 printf(
"normalized uri \"");
5657 static int HTPParserDecodingTest06(
void)
5661 uint8_t httpbuf1[] =
5662 "GET /put.php?ip=1.2.3.4&port=+6000 HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5663 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5676 double-decode-path: yes\n\
5677 double-decode-query: yes\n\
5685 const char *addr =
"4.3.2.1";
5686 memset(&ssn, 0,
sizeof(ssn));
5692 f->
proto = IPPROTO_TCP;
5698 for (u = 0; u < httplen1; u++) {
5701 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
5702 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
5703 else flags = STREAM_TOSERVER;
5707 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5714 if (htp_state == NULL) {
5715 printf(
"no http state: ");
5719 uint8_t ref1[] =
"/put.php?ip=1.2.3.4&port=+6000";
5720 size_t reflen =
sizeof(ref1) - 1;
5722 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5728 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5737 printf(
"normalized uri \"");
5763 static int HTPParserDecodingTest07(
void)
5767 uint8_t httpbuf1[] =
5768 "GET /put.php?ip=1.2.3.4&port=+6000 HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5769 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5782 double-decode-path: yes\n\
5783 double-decode-query: yes\n\
5784 query-plusspace-decode: yes\n\
5792 const char *addr =
"4.3.2.1";
5793 memset(&ssn, 0,
sizeof(ssn));
5799 f->
proto = IPPROTO_TCP;
5805 for (u = 0; u < httplen1; u++) {
5808 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
5809 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
5810 else flags = STREAM_TOSERVER;
5814 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5821 if (htp_state == NULL) {
5822 printf(
"no http state: ");
5826 uint8_t ref1[] =
"/put.php?ip=1.2.3.4&port= 6000";
5827 size_t reflen =
sizeof(ref1) - 1;
5829 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5835 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5844 printf(
"normalized uri \"");
5870 static int HTPParserDecodingTest08(
void)
5874 uint8_t httpbuf1[] =
5875 "GET http://suricata-ids.org/blah/ HTTP/1.1\r\nHost: suricata-ids.org\r\n\r\n";
5876 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5896 const char *addr =
"4.3.2.1";
5897 memset(&ssn, 0,
sizeof(ssn));
5903 f->
proto = IPPROTO_TCP;
5909 for (u = 0; u < httplen1; u++) {
5912 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
5913 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
5914 else flags = STREAM_TOSERVER;
5918 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5925 if (htp_state == NULL) {
5926 printf(
"no http state: ");
5930 uint8_t ref1[] =
"/blah/";
5931 size_t reflen =
sizeof(ref1) - 1;
5933 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5939 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5948 printf(
"normalized uri \"");
5974 static int HTPParserDecodingTest09(
void)
5978 uint8_t httpbuf1[] =
5979 "GET http://suricata-ids.org/blah/ HTTP/1.1\r\nHost: suricata-ids.org\r\n\r\n";
5980 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5993 uri-include-all: true\n\
6001 const char *addr =
"4.3.2.1";
6002 memset(&ssn, 0,
sizeof(ssn));
6008 f->
proto = IPPROTO_TCP;
6014 for (u = 0; u < httplen1; u++) {
6017 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
6018 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
6019 else flags = STREAM_TOSERVER;
6023 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
6030 if (htp_state == NULL) {
6031 printf(
"no http state: ");
6035 uint8_t ref1[] =
"http://suricata-ids.org/blah/";
6036 size_t reflen =
sizeof(ref1) - 1;
6038 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
6044 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
6053 printf(
"normalized uri \"");
6078 static int HTPBodyReassemblyTest01(
void)
6082 memset(&htud, 0x00,
sizeof(htud));
6084 memset(&hstate, 0x00,
sizeof(hstate));
6086 memset(&flow, 0x00,
sizeof(flow));
6089 memset(&tx, 0,
sizeof(tx));
6094 uint8_t chunk1[] =
"--e5a320f21416a02493a0a6f561b1c494\r\nContent-Disposition: form-data; name=\"uploadfile\"; filename=\"D2GUef.jpg\"\r";
6095 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";
6102 const uint8_t *chunks_buffer = NULL;
6103 uint32_t chunks_buffer_len = 0;
6105 HtpRequestBodyReassemble(&htud, &chunks_buffer, &chunks_buffer_len);
6106 if (chunks_buffer == NULL) {
6110 printf(
"REASSCHUNK START: \n");
6112 printf(
"REASSCHUNK END: \n");
6115 HtpRequestBodyHandleMultipart(&hstate, &htud, &tx, chunks_buffer, chunks_buffer_len);
6130 static int HTPSegvTest01(
void)
6134 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";
6135 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
6143 double-decode-path: no\n\
6144 double-decode-query: no\n\
6145 request-body-limit: 0\n\
6146 response-body-limit: 0\n\
6159 memset(&ssn, 0,
sizeof(ssn));
6161 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
6165 f->
proto = IPPROTO_TCP;
6170 SCLogDebug(
"\n>>>> processing chunk 1 <<<<\n");
6174 printf(
"toserver chunk 1 returned %" PRId32
", expected 0: ", r);
6177 SCLogDebug(
"\n>>>> processing chunk 1 again <<<<\n");
6180 printf(
"toserver chunk 1 returned %" PRId32
", expected 0: ", r);
6185 if (http_state == NULL) {
6186 printf(
"no http state: ");
6191 if (decoder_events != NULL) {
6192 printf(
"app events: ");
6209 static int HTPParserTest14(
void)
6220 double-decode-path: no\n\
6221 double-decode-query: no\n\
6222 request-body-limit: 0\n\
6223 response-body-limit: 0\n\
6228 memset(&ssn, 0,
sizeof(ssn));
6238 memset(httpbuf, 0x00,
len);
6241 strlcpy(httpbuf,
"GET /blah/ HTTP/1.1\r\n"
6242 "Host: myhost.lan\r\n"
6243 "Connection: keep-alive\r\n"
6245 "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"
6246 "Referer: http://blah.lan/\r\n"
6247 "Accept-Encoding: gzip,deflate,sdch\r\nAccept-Language: en-US,en;q=0.8\r\n"
6249 size_t o = strlen(httpbuf);
6250 for ( ; o <
len - 4; o++) {
6253 httpbuf[
len - 4] =
'\r';
6254 httpbuf[
len - 3] =
'\n';
6255 httpbuf[
len - 2] =
'\r';
6256 httpbuf[
len - 1] =
'\n';
6262 f->
proto = IPPROTO_TCP;
6267 for (u = 0; u <
len; u++) {
6270 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
6271 else if (u == (
len - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
6272 else flags = STREAM_TOSERVER;
6280 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
6282 FAIL_IF(tx->request_method_number != HTP_M_GET);
6283 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_1);
6305 static int HTPParserTest15(
void)
6309 char *httpbuf = NULL;
6321 double-decode-path: no\n\
6322 double-decode-query: no\n\
6323 request-body-limit: 0\n\
6324 response-body-limit: 0\n\
6325 meta-field-limit: 20000\n\
6329 memset(&ssn, 0,
sizeof(ssn));
6340 memset(httpbuf, 0x00,
len);
6343 strlcpy(httpbuf,
"GET /blah/ HTTP/1.1\r\n"
6344 "Host: myhost.lan\r\n"
6345 "Connection: keep-alive\r\n"
6347 "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"
6348 "Referer: http://blah.lan/\r\n"
6349 "Accept-Encoding: gzip,deflate,sdch\r\nAccept-Language: en-US,en;q=0.8\r\n"
6351 size_t o = strlen(httpbuf);
6352 for ( ; o <
len - 4; o++) {
6355 httpbuf[
len - 4] =
'\r';
6356 httpbuf[
len - 3] =
'\n';
6357 httpbuf[
len - 2] =
'\r';
6358 httpbuf[
len - 1] =
'\n';
6360 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
6364 f->
proto = IPPROTO_TCP;
6370 for (u = 0; u <
len; u++) {
6373 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
6374 else if (u == (
len - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
6375 else flags = STREAM_TOSERVER;
6379 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
6385 if (htp_state == NULL) {
6386 printf(
"no http state: ");
6390 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
6391 if (tx == NULL || tx->request_method_number != HTP_M_GET || tx->request_protocol_number != HTP_PROTOCOL_1_1)
6393 printf(
"expected method M_GET and got %s: , expected protocol "
6394 "HTTP/1.1 and got %s \n", bstr_util_strdup_to_c(tx->request_method),
6395 bstr_util_strdup_to_c(tx->request_protocol));
6402 if (decoder_events != NULL) {
6403 printf(
"app events: ");
6413 if (httpbuf != NULL)
6423 static int HTPParserTest16(
void)
6432 memset(&ssn, 0,
sizeof(ssn));
6434 uint8_t httpbuf[] =
"GET\f/blah/\fHTTP/1.1\r\n"
6435 "Host: myhost.lan\r\n"
6436 "Connection: keep-alive\r\n"
6438 "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"
6439 "Referer: http://blah.lan/\r\n"
6440 "Accept-Encoding: gzip,deflate,sdch\r\nAccept-Language: en-US,en;q=0.8\r\n"
6441 "Cookie: blah\r\n\r\n";
6442 size_t len =
sizeof(httpbuf) - 1;
6444 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
6448 f->
proto = IPPROTO_TCP;
6453 uint8_t
flags = STREAM_TOSERVER|STREAM_START|STREAM_EOF;
6457 printf(
"toserver chunk 1 returned %" PRId32
", expected 0: ", r);
6462 if (htp_state == NULL) {
6463 printf(
"no http state: ");
6467 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
6468 if (tx == NULL || tx->request_method_number != HTP_M_GET || tx->request_protocol_number != HTP_PROTOCOL_1_1)
6470 printf(
"expected method M_GET and got %s: , expected protocol "
6471 "HTTP/1.1 and got %s \n", tx ? bstr_util_strdup_to_c(tx->request_method) :
"tx null",
6472 tx ? bstr_util_strdup_to_c(tx->request_protocol) :
"tx null");
6476 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
6481 if (decoder_events == NULL) {
6482 printf(
"no app events: ");
6487 printf(
"HTTP_DECODER_EVENT_METHOD_DELIM_NON_COMPLIANT not set: ");
6492 printf(
"HTTP_DECODER_EVENT_URI_DELIM_NON_COMPLIANT not set: ");
6508 static int HTPParserTest20(
void)
6511 uint8_t httpbuf1[] =
"GET /ld/index.php?id=412784631&cid=0064&version=4&"
6512 "name=try HTTP/1.1\r\nAccept: */*\r\nUser-Agent: "
6513 "LD-agent\r\nHost: 209.205.196.16\r\n\r\n";
6514 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
6515 uint8_t httpbuf2[] =
"NOTHTTP\r\nSOMEOTHERDATA";
6516 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
6517 uint8_t httpbuf3[] =
"STILLNOTHTTP\r\nSOMEMOREOTHERDATA";
6518 uint32_t httplen3 =
sizeof(httpbuf3) - 1;
6524 memset(&ssn, 0,
sizeof(ssn));
6526 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
6529 f->
proto = IPPROTO_TCP;
6548 htp_tx_t *tx = HTPStateGetTx(http_state, 0);
6550 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
6553 FAIL_IF(tx->request_method_number != HTP_M_GET);
6554 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_1);
6556 FAIL_IF(tx->response_status_number != 0);
6557 FAIL_IF(tx->response_protocol_number != -1);
6567 static int HTPParserTest21(
void)
6570 uint8_t httpbuf1[] =
"GET /ld/index.php?id=412784631&cid=0064&version=4&"
6571 "name=try HTTP/1.1\r\nAccept: */*\r\nUser-Agent: "
6572 "LD-agent\r\nHost: 209.205.196.16\r\n\r\n";
6573 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
6574 uint8_t httpbuf2[] =
"999 NOTHTTP REALLY\r\nSOMEOTHERDATA\r\n";
6575 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
6576 uint8_t httpbuf3[] =
"STILLNOTHTTP\r\nSOMEMOREOTHERDATA";
6577 uint32_t httplen3 =
sizeof(httpbuf3) - 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;
6607 htp_tx_t *tx = HTPStateGetTx(http_state, 0);
6609 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
6612 FAIL_IF(tx->request_method_number != HTP_M_GET);
6613 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_1);
6615 FAIL_IF(tx->response_status_number != 0);
6616 FAIL_IF(tx->response_protocol_number != -1);
6626 static int HTPParserTest22(
void)
6629 uint8_t httpbuf1[] =
"GET /ld/index.php?id=412784631&cid=0064&version=4&"
6630 "name=try HTTP/1.1\r\nAccept: */*\r\nUser-Agent: "
6631 "LD-agent\r\nHost: 209.205.196.16\r\n\r\n";
6632 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
6633 uint8_t httpbuf2[] =
"\r\n0000=0000000/ASDF3_31.zip, 456723\r\n"
6634 "AAAAAA_0000=0000000/AAAAAAAA.zip,46725\r\n";
6635 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
6641 memset(&ssn, 0,
sizeof(ssn));
6643 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
6646 f->
proto = IPPROTO_TCP;
6661 htp_tx_t *tx = HTPStateGetTx(http_state, 0);
6663 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
6666 FAIL_IF(tx->request_method_number != HTP_M_GET);
6667 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_1);
6669 FAIL_IF(tx->response_status_number != -0);
6670 FAIL_IF(tx->response_protocol_number != -1);
6680 static int HTPParserTest23(
void)
6683 uint8_t httpbuf1[] =
"GET /ld/index.php?id=412784631&cid=0064&version=4&"
6684 "name=try HTTP/1.1\r\nAccept: */*\r\nUser-Agent: "
6685 "LD-agent\r\nHost: 209.205.196.16\r\n\r\n";
6686 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
6687 uint8_t httpbuf2[] =
"HTTP0000=0000000/ASDF3_31.zip, 456723\r\n"
6688 "AAAAAA_0000=0000000/AAAAAAAA.zip,46725\r\n";
6689 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
6695 memset(&ssn, 0,
sizeof(ssn));
6697 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
6700 f->
proto = IPPROTO_TCP;
6715 htp_tx_t *tx = HTPStateGetTx(http_state, 0);
6717 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
6720 FAIL_IF(tx->request_method_number != HTP_M_GET);
6721 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_1);
6723 FAIL_IF(tx->response_status_number != -1);
6724 FAIL_IF(tx->response_protocol_number != -2);
6734 static int HTPParserTest24(
void)
6737 uint8_t httpbuf1[] =
"GET /ld/index.php?id=412784631&cid=0064&version=4&"
6738 "name=try HTTP/1.1\r\nAccept: */*\r\nUser-Agent: "
6739 "LD-agent\r\nHost: 209.205.196.16\r\n\r\n";
6740 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
6741 uint8_t httpbuf2[] =
"HTTP/1.0 0000=0000000/ASDF3_31.zip, 456723\r\n"
6742 "AAAAAA_0000=0000000/AAAAAAAA.zip,46725\r\n";
6743 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
6749 memset(&ssn, 0,
sizeof(ssn));
6751 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
6754 f->
proto = IPPROTO_TCP;
6769 htp_tx_t *tx = HTPStateGetTx(http_state, 0);
6771 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
6774 FAIL_IF(tx->request_method_number != HTP_M_GET);
6775 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_1);
6777 FAIL_IF(tx->response_status_number != -1);
6778 FAIL_IF(tx->response_protocol_number != HTP_PROTOCOL_1_0);
6787 static int HTPParserTest25(
void)
6794 memset(&ssn, 0,
sizeof(ssn));
6799 f->
proto = IPPROTO_TCP;
6802 const char *
str =
"GET / HTTP/1.1\r\nHost: www.google.com\r\nUser-Agent: Suricata/1.0\r\n\r\n";
6804 (uint8_t *)
str, strlen(
str));
6828 str =
"HTTP 1.1 200 OK\r\nServer: Suricata/1.0\r\nContent-Length: 8\r\n\r\nSuricata";
6830 (uint8_t *)
str, strlen(
str));
6864 (uint8_t *)
str, strlen(
str));
6875 (uint8_t *)
str, strlen(
str));
6895 static int HTPParserTest26(
void)
6904 request-body-limit: 1\n\
6905 response-body-limit: 1\n\
6919 uint8_t httpbuf1[] =
"GET /alice.txt HTTP/1.1\r\n\r\n";
6920 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
6921 uint8_t httpbuf2[] =
"HTTP/1.1 200 OK\r\n"
6922 "Content-Type: text/plain\r\n"
6923 "Content-Length: 228\r\n\r\n"
6924 "Alice was beginning to get very tired of sitting by her sister on the bank."
6925 "Alice was beginning to get very tired of sitting by her sister on the bank.";
6926 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
6927 uint8_t httpbuf3[] =
"Alice was beginning to get very tired of sitting by her sister on the bank.\r\n\r\n";
6928 uint32_t httplen3 =
sizeof(httpbuf3) - 1;
6934 memset(&th_v, 0,
sizeof(th_v));
6935 memset(&f, 0,
sizeof(f));
6936 memset(&ssn, 0,
sizeof(ssn));
6943 f.
proto = IPPROTO_TCP;
6964 "(filestore; sid:1; rev:1;)");
7009 AppLayerGetFileState files = HTPGetTxFiles(http_state, tx_ptr, STREAM_TOCLIENT);
7031 static int HTPParserTest27(
void)
7034 memset(&cfg, 0,
sizeof(cfg));
7038 uint32_t
len = 1000;
7063 static void HTPParserRegisterTests(
void)
7085 UtRegisterTest(
"HTPParserConfigTest04", HTPParserConfigTest04, 1);
7088 UtRegisterTest(
"HTPParserDecodingTest01", HTPParserDecodingTest01);
7089 UtRegisterTest(
"HTPParserDecodingTest01a", HTPParserDecodingTest01a);
7090 UtRegisterTest(
"HTPParserDecodingTest02", HTPParserDecodingTest02);
7091 UtRegisterTest(
"HTPParserDecodingTest03", HTPParserDecodingTest03);
7092 UtRegisterTest(
"HTPParserDecodingTest04", HTPParserDecodingTest04);
7093 UtRegisterTest(
"HTPParserDecodingTest05", HTPParserDecodingTest05);
7094 UtRegisterTest(
"HTPParserDecodingTest06", HTPParserDecodingTest06);
7095 UtRegisterTest(
"HTPParserDecodingTest07", HTPParserDecodingTest07);
7096 UtRegisterTest(
"HTPParserDecodingTest08", HTPParserDecodingTest08);
7097 UtRegisterTest(
"HTPParserDecodingTest09", HTPParserDecodingTest09);
7099 UtRegisterTest(
"HTPBodyReassemblyTest01", HTPBodyReassemblyTest01);