99 #define HTP_MAX_MESSAGES 512
105 static uint64_t htp_state_memuse = 0;
106 static uint64_t htp_state_memcnt = 0;
116 {
"INVALID_TRANSFER_ENCODING_VALUE_IN_REQUEST",
118 {
"INVALID_TRANSFER_ENCODING_VALUE_IN_RESPONSE",
120 {
"INVALID_CONTENT_LENGTH_FIELD_IN_REQUEST",
122 {
"INVALID_CONTENT_LENGTH_FIELD_IN_RESPONSE",
124 {
"DUPLICATE_CONTENT_LENGTH_FIELD_IN_REQUEST",
126 {
"DUPLICATE_CONTENT_LENGTH_FIELD_IN_RESPONSE",
129 {
"UNABLE_TO_MATCH_RESPONSE_TO_REQUEST",
144 {
"REQUEST_SERVER_PORT_TCP_PORT_MISMATCH",
158 {
"RESPONSE_ABNORMAL_TRANSFER_ENCODING",
200 static int HTTPGetFrameIdByName(
const char *frame_name)
209 static const char *HTTPGetFrameNameById(
const uint8_t frame_id)
215 static void *HTPStateGetTx(
void *alstate, uint64_t tx_id);
216 static int HTPStateGetAlstateProgress(
void *tx, uint8_t direction);
217 static uint64_t HTPStateGetTxCnt(
void *alstate);
219 static void HTPParserRegisterTests(
void);
222 static inline uint64_t HtpGetActiveRequestTxID(
HtpState *s)
224 uint64_t
id = HTPStateGetTxCnt(s);
229 static inline uint64_t HtpGetActiveResponseTxID(
HtpState *s)
242 static const char *HTPLookupPersonalityString(
int p)
244 #define CASE_HTP_PERSONALITY_STRING(p) \
245 case HTP_SERVER_ ## p: return #p
248 CASE_HTP_PERSONALITY_STRING(MINIMAL);
249 CASE_HTP_PERSONALITY_STRING(GENERIC);
250 CASE_HTP_PERSONALITY_STRING(IDS);
251 CASE_HTP_PERSONALITY_STRING(IIS_4_0);
252 CASE_HTP_PERSONALITY_STRING(IIS_5_0);
253 CASE_HTP_PERSONALITY_STRING(IIS_5_1);
254 CASE_HTP_PERSONALITY_STRING(IIS_6_0);
255 CASE_HTP_PERSONALITY_STRING(IIS_7_0);
256 CASE_HTP_PERSONALITY_STRING(IIS_7_5);
257 CASE_HTP_PERSONALITY_STRING(APACHE_2);
271 static int HTPLookupPersonality(
const char *
str)
273 #define IF_HTP_PERSONALITY_NUM(p) \
274 if (strcasecmp(#p, str) == 0) return HTP_SERVER_ ## p
286 if (strcasecmp(
"TOMCAT_6_0",
str) == 0) {
288 "longer supported by libhtp.",
291 }
else if ((strcasecmp(
"APACHE",
str) == 0) ||
292 (strcasecmp(
"APACHE_2_2",
str) == 0))
295 "longer supported by libhtp, failing back to "
296 "Apache2 personality.",
298 return HTP_SERVER_APACHE_2;
305 const uint8_t dir,
const uint8_t e)
315 const uint64_t tx_id = (dir == STREAM_TOSERVER) ?
316 HtpGetActiveRequestTxID(s) : HtpGetActiveResponseTxID(s);
318 htp_tx_t *tx = HTPStateGetTx(s, tx_id);
319 if (tx == NULL && tx_id > 0)
320 tx = HTPStateGetTx(s, tx_id - 1);
335 static void *HTPStateAlloc(
void *orig_state,
AppProto proto_orig)
349 htp_state_memuse +=
sizeof(
HtpState);
350 SCLogDebug(
"htp memory %"PRIu64
" (%"PRIu64
")", htp_state_memuse, htp_state_memcnt);
370 if (htud->
tx_data.de_state != NULL) {
396 if (s->
connp != NULL) {
400 uint64_t total_txs = HTPStateGetTxCnt(state);
402 if (s->
conn != NULL) {
403 for (tx_id = 0; tx_id < total_txs; tx_id++) {
404 htp_tx_t *tx = HTPStateGetTx(s, tx_id);
407 HtpTxUserDataFree(s, htud);
408 htp_tx_set_user_data(tx, NULL);
412 htp_connp_destroy_all(s->
connp);
420 htp_state_memuse -=
sizeof(
HtpState);
421 SCLogDebug(
"htp memory %"PRIu64
" (%"PRIu64
")", htp_state_memuse, htp_state_memcnt);
434 static void HTPStateTransactionFree(
void *state, uint64_t
id)
442 htp_tx_t *tx = HTPStateGetTx(s,
id);
446 HtpTxUserDataFree(s, htud);
447 htp_tx_set_user_data(tx, NULL);
454 tx->request_progress == HTP_REQUEST_COMPLETE &&
455 tx->response_progress == HTP_RESPONSE_COMPLETE)))
457 tx->request_progress = HTP_REQUEST_COMPLETE;
458 tx->response_progress = HTP_RESPONSE_COMPLETE;
496 static void AppLayerHtpNeedMultipartHeader(
void)
514 AppLayerHtpNeedMultipartHeader();
522 static void AppLayerHtpSetStreamDepthFlag(
void *tx,
const uint8_t
flags)
527 if (
flags & STREAM_TOCLIENT) {
537 SCLogDebug(
"cfg->body_limit %u stream_depth %u body->content_len_so_far %" PRIu64,
554 static uint32_t AppLayerHtpComputeChunkLength(uint64_t content_len_so_far, uint32_t body_limit,
555 uint32_t stream_depth, uint8_t
flags, uint32_t data_len)
557 uint32_t chunk_len = 0;
559 (content_len_so_far < (uint64_t)body_limit) &&
560 (content_len_so_far + (uint64_t)data_len) > body_limit)
562 chunk_len = body_limit - content_len_so_far;
564 (content_len_so_far < (uint64_t)stream_depth) &&
565 (content_len_so_far + (uint64_t)data_len) > stream_depth)
567 chunk_len = stream_depth - content_len_so_far;
570 return (chunk_len == 0 ? data_len : chunk_len);
634 #define HTP_ERROR_MAX (sizeof(htp_errors) / sizeof(htp_errors[0]))
635 #define HTP_WARNING_MAX (sizeof(htp_warnings) / sizeof(htp_warnings[0]))
646 static uint8_t HTPHandleWarningGetId(
const char *
msg)
670 static uint8_t HTPHandleErrorGetId(
const char *
msg)
694 static void HTPHandleError(
HtpState *s,
const uint8_t dir)
696 if (s == NULL || s->
conn == NULL ||
697 s->
conn->messages == NULL) {
701 size_t size = htp_list_size(s->
conn->messages);
716 htp_log_t *log = htp_list_get(s->
conn->messages,
msg);
721 htp_tx_t *tx = log->tx;
727 uint8_t
id = HTPHandleErrorGetId(log->msg);
729 id = HTPHandleWarningGetId(log->msg);
735 HTPSetEvent(s, htud, dir,
id);
742 static inline void HTPErrorCheckTxRequestFlags(
HtpState *s, htp_tx_t *tx)
745 BUG_ON(s == NULL || tx == NULL);
747 if (tx->flags & ( HTP_REQUEST_INVALID_T_E|HTP_REQUEST_INVALID_C_L|
748 HTP_HOST_MISSING|HTP_HOST_AMBIGUOUS|HTP_HOSTU_INVALID|
755 if (tx->flags & HTP_REQUEST_INVALID_T_E)
756 HTPSetEvent(s, htud, STREAM_TOSERVER,
758 if (tx->flags & HTP_REQUEST_INVALID_C_L)
759 HTPSetEvent(s, htud, STREAM_TOSERVER,
761 if (tx->flags & HTP_HOST_MISSING)
762 HTPSetEvent(s, htud, STREAM_TOSERVER,
764 if (tx->flags & HTP_HOST_AMBIGUOUS)
765 HTPSetEvent(s, htud, STREAM_TOSERVER,
767 if (tx->flags & HTP_HOSTU_INVALID)
768 HTPSetEvent(s, htud, STREAM_TOSERVER,
770 if (tx->flags & HTP_HOSTH_INVALID)
771 HTPSetEvent(s, htud, STREAM_TOSERVER,
774 if (tx->request_auth_type == HTP_AUTH_UNRECOGNIZED) {
778 HTPSetEvent(s, htud, STREAM_TOSERVER,
781 if (tx->is_protocol_0_9 && tx->request_method_number == HTP_M_UNKNOWN &&
782 (tx->request_protocol_number == HTP_PROTOCOL_INVALID ||
783 tx->request_protocol_number == HTP_PROTOCOL_UNKNOWN)) {
787 HTPSetEvent(s, htud, STREAM_TOSERVER,
798 htp_cfg_t *htp = cfglist.
cfg;
799 void *user_data = NULL;
814 if (user_data != NULL) {
815 htp_cfg_rec = user_data;
816 htp = htp_cfg_rec->
cfg;
819 SCLogDebug(
"Using default HTP config: %p", htp);
823 #ifdef DEBUG_VALIDATION
830 hstate->
connp = htp_connp_create(htp);
831 if (hstate->
connp == NULL) {
835 hstate->
conn = htp_connp_get_connection(hstate->
connp);
837 htp_connp_set_user_data(hstate->
connp, (
void *)hstate);
838 hstate->
cfg = htp_cfg_rec;
843 htp_connp_open(hstate->
connp, NULL, f->
sp, NULL, f->
dp, &
tv);
865 StreamSlice stream_slice,
void *local_data)
875 if (NULL == hstate->
conn) {
876 if (Setup(f, hstate) != 0) {
881 hstate->
slice = &stream_slice;
883 const uint8_t *input = StreamSliceGetData(&stream_slice);
884 uint32_t input_len = StreamSliceGetDataLen(&stream_slice);
889 const int r = htp_connp_req_data(hstate->
connp, &
ts, input, input_len);
891 case HTP_STREAM_ERROR:
897 HTPHandleError(hstate, STREAM_TOSERVER);
904 htp_connp_req_close(hstate->
connp, &
ts);
906 SCLogDebug(
"stream eof encountered, closing htp handle for ts");
910 hstate->
slice = NULL;
932 StreamSlice stream_slice,
void *local_data)
938 const uint8_t *input = StreamSliceGetData(&stream_slice);
939 uint32_t input_len = StreamSliceGetDataLen(&stream_slice);
945 if (NULL == hstate->
conn) {
946 if (Setup(f, hstate) != 0) {
951 hstate->
slice = &stream_slice;
957 const int r = htp_connp_res_data(hstate->
connp, &
ts, input, input_len);
959 case HTP_STREAM_ERROR:
962 case HTP_STREAM_TUNNEL:
963 tx = htp_connp_get_out_tx(hstate->
connp);
964 if (tx != NULL && tx->response_status_number == 101) {
966 (htp_header_t *)htp_table_get_c(tx->response_headers,
"Upgrade");
967 if (h == NULL || bstr_cmp_c(h->value,
"h2c") != 0) {
975 if (tx->request_port_number != -1) {
976 dp = (uint16_t)tx->request_port_number;
978 consumed = htp_connp_res_data_consumed(hstate->
connp);
979 hstate->
slice = NULL;
981 HTPSetEvent(hstate, NULL, STREAM_TOCLIENT,
986 if (consumed > 0 && consumed < input_len) {
995 HTPHandleError(hstate, STREAM_TOCLIENT);
1002 htp_connp_close(hstate->
connp, &
ts);
1007 hstate->
slice = NULL;
1018 static int HTTPParseContentDispositionHeader(uint8_t *name,
size_t name_len,
1019 uint8_t *data,
size_t len, uint8_t **retptr,
size_t *retlen)
1022 printf(
"DATA START: \n");
1024 printf(
"DATA END: \n");
1029 for (x = 0; x <
len; x++) {
1030 if (!(isspace(data[x])))
1037 uint8_t *line = data+x;
1038 size_t line_len =
len-x;
1041 printf(
"LINE START: \n");
1043 printf(
"LINE END: \n");
1045 for (x = 0 ; x < line_len; x++) {
1047 if (line[x - 1] !=
'\\' && line[x] ==
'\"') {
1051 if (((line[x - 1] !=
'\\' && line[x] ==
';') || ((x + 1) == line_len)) && (quote == 0 || quote % 2 == 0)) {
1052 uint8_t *token = line +
offset;
1053 size_t token_len = x -
offset;
1055 if ((x + 1) == line_len) {
1066 printf(
"TOKEN START: \n");
1068 printf(
"TOKEN END: \n");
1070 if (token_len > name_len) {
1071 if (name == NULL || SCMemcmpLowercase(name, token, name_len) == 0) {
1072 uint8_t *value = token + name_len;
1073 size_t value_len = token_len - name_len;
1075 if (value[0] ==
'\"') {
1079 if (value[value_len-1] ==
'\"') {
1083 printf(
"VALUE START: \n");
1085 printf(
"VALUE END: \n");
1088 *retlen = value_len;
1102 static int HTTPParseContentTypeHeader(uint8_t *name,
size_t name_len,
1103 uint8_t *data,
size_t len, uint8_t **retptr,
size_t *retlen)
1107 printf(
"DATA START: \n");
1109 printf(
"DATA END: \n");
1114 for (x = 0; x <
len; x++) {
1115 if (!(isspace(data[x])))
1123 uint8_t *line = data+x;
1124 size_t line_len =
len-x;
1127 printf(
"LINE START: \n");
1129 printf(
"LINE END: \n");
1131 for (x = 0 ; x < line_len; x++) {
1133 if (line[x - 1] !=
'\\' && line[x] ==
'\"') {
1137 if (((line[x - 1] !=
'\\' && line[x] ==
';') || ((x + 1) == line_len)) && (quote == 0 || quote % 2 == 0)) {
1138 uint8_t *token = line +
offset;
1139 size_t token_len = x -
offset;
1141 if ((x + 1) == line_len) {
1152 printf(
"TOKEN START: \n");
1154 printf(
"TOKEN END: \n");
1156 if (token_len > name_len) {
1157 if (name == NULL || SCMemcmpLowercase(name, token, name_len) == 0) {
1158 uint8_t *value = token + name_len;
1159 size_t value_len = token_len - name_len;
1161 if (value[0] ==
'\"') {
1165 if (value[value_len-1] ==
'\"') {
1169 printf(
"VALUE START: \n");
1171 printf(
"VALUE END: \n");
1174 *retlen = value_len;
1198 static int HtpRequestBodySetupMultipart(htp_tx_t *tx,
HtpTxUserData *htud)
1200 htp_header_t *h = (htp_header_t *)htp_table_get_c(tx->request_headers,
1202 if (h != NULL && bstr_len(h->value) > 0) {
1203 uint8_t *boundary = NULL;
1204 size_t boundary_len = 0;
1206 int r = HTTPParseContentTypeHeader((uint8_t *)
"boundary=", 9,
1207 (uint8_t *) bstr_ptr(h->value), bstr_len(h->value),
1208 &boundary, &boundary_len);
1211 printf(
"BOUNDARY START: \n");
1213 printf(
"BOUNDARY END: \n");
1221 memcpy(htud->
boundary, boundary, boundary_len);
1235 #define C_D_HDR "content-disposition:"
1236 #define C_D_HDR_LEN 20
1237 #define C_T_HDR "content-type:"
1238 #define C_T_HDR_LEN 13
1240 static void HtpRequestBodyMultipartParseHeader(
HtpState *hstate,
1242 uint8_t *header, uint32_t header_len,
1243 uint8_t **filename, uint16_t *filename_len,
1244 uint8_t **filetype, uint16_t *filetype_len)
1252 printf(
"HEADER START: \n");
1254 printf(
"HEADER END: \n");
1257 while (header_len > 0) {
1258 uint8_t *next_line =
Bs2bmSearch(header, header_len, (uint8_t *)
"\r\n", 2);
1259 uint8_t *line = header;
1262 if (next_line == NULL) {
1263 line_len = header_len;
1265 line_len = next_line - header;
1267 uint8_t *sc = (uint8_t *)memchr(line,
':', line_len);
1269 HTPSetEvent(hstate, htud, STREAM_TOSERVER,
1273 }
else if (line_len > 0 && sc == &line[line_len - 1]) {
1274 HTPSetEvent(hstate, htud, STREAM_TOSERVER,
1278 printf(
"LINE START: \n");
1280 printf(
"LINE END: \n");
1288 (void)HTTPParseContentDispositionHeader((uint8_t *)
"filename=", 9,
1289 value, value_len, &fn, &fn_len);
1296 (void)HTTPParseContentTypeHeader(NULL, 0,
1297 value, value_len, &ft, &ft_len);
1301 if (next_line == NULL) {
1305 header_len -= ((next_line + 2) - header);
1306 header = next_line + 2;
1309 if (fn_len > USHRT_MAX)
1311 if (ft_len > USHRT_MAX)
1315 *filename_len = (uint16_t)fn_len;
1317 *filetype_len = (uint16_t)ft_len;
1328 const uint8_t **chunks_buffer, uint32_t *chunks_buffer_len)
1331 chunks_buffer, chunks_buffer_len,
1335 static void FlagDetectStateNewFile(
HtpTxUserData *tx,
int dir)
1338 if (tx && tx->
tx_data.de_state) {
1339 if (dir == STREAM_TOSERVER) {
1340 SCLogDebug(
"DETECT_ENGINE_STATE_FLAG_FILE_NEW set");
1342 }
else if (STREAM_TOCLIENT) {
1343 SCLogDebug(
"DETECT_ENGINE_STATE_FLAG_FILE_NEW set");
1352 static void HtpRequestBodySetupBoundary(
HtpTxUserData *htud,
1353 uint8_t *boundary, uint32_t boundary_len)
1355 memset(boundary,
'-', boundary_len);
1360 const uint8_t *chunks_buffer, uint32_t chunks_buffer_len)
1364 uint16_t expected_boundary_len = htud->
boundary_len + 2;
1365 uint16_t expected_boundary_end_len = htud->
boundary_len + 4;
1366 int tx_progress = 0;
1369 printf(
"CHUNK START: \n");
1371 printf(
"CHUNK END: \n");
1374 HtpRequestBodySetupBoundary(htud, boundary, htud->
boundary_len + 4);
1377 const uint8_t *header_start =
Bs2bmSearch(chunks_buffer, chunks_buffer_len,
1378 boundary, expected_boundary_len);
1380 const uint8_t *form_end = NULL;
1382 const uint8_t *header_end = NULL;
1383 if (header_start != NULL) {
1384 header_end =
Bs2bmSearch(header_start, chunks_buffer_len - (header_start - chunks_buffer),
1385 (uint8_t *)
"\r\n\r\n", 4);
1386 form_end =
Bs2bmSearch(header_start, chunks_buffer_len - (header_start - chunks_buffer),
1387 boundary, expected_boundary_end_len);
1390 SCLogDebug(
"header_start %p, header_end %p, form_end %p", header_start,
1391 header_end, form_end);
1398 if (header_start != NULL || (tx_progress > HTP_REQUEST_BODY)) {
1401 const uint8_t *filedata = chunks_buffer;
1402 uint32_t filedata_len = 0;
1405 if (header_start != NULL) {
1406 if (header_start == filedata + 2) {
1408 SCLogDebug(
"last chunk had all data, but not the boundary");
1410 }
else if (header_start > filedata + 2) {
1411 SCLogDebug(
"some data from last file before the boundary");
1413 filedata_len = header_start - filedata - 2;
1418 if (tx_progress > HTP_REQUEST_BODY) {
1419 filedata_len = chunks_buffer_len;
1423 if (filedata_len > chunks_buffer_len) {
1424 HTPSetEvent(hstate, htud, STREAM_TOSERVER,
1429 printf(
"FILEDATA (final chunk) START: \n");
1431 printf(
"FILEDATA (final chunk) END: \n");
1434 if (
HTPFileClose(hstate, htud, filedata, filedata_len,
flags, STREAM_TOSERVER) ==
1444 SCLogDebug(
"not yet at the end of the file");
1446 if (chunks_buffer_len > expected_boundary_end_len) {
1447 const uint8_t *filedata = chunks_buffer;
1448 uint32_t filedata_len = chunks_buffer_len - expected_boundary_len;
1450 printf(
"FILEDATA (part) START: \n");
1452 printf(
"FILEDATA (part) END: \n");
1457 hstate, htud, filedata, filedata_len, STREAM_TOSERVER);
1460 }
else if (result == -2) {
1468 SCLogDebug(
"chunk too small to already process in part");
1475 while (header_start != NULL && header_end != NULL &&
1476 header_end != form_end &&
1477 header_start < (chunks_buffer + chunks_buffer_len) &&
1478 header_end < (chunks_buffer + chunks_buffer_len) &&
1479 header_start < header_end)
1481 uint8_t *filename = NULL;
1482 uint16_t filename_len = 0;
1483 uint8_t *filetype = NULL;
1484 uint16_t filetype_len = 0;
1486 uint32_t header_len = header_end - header_start;
1488 uint8_t *header = (uint8_t *)header_start;
1491 if (expected_boundary_len == header_len) {
1493 }
else if ((uint32_t)(expected_boundary_len + 2) <= header_len) {
1494 header_len -= (expected_boundary_len + 2);
1495 header = (uint8_t *)header_start + (expected_boundary_len + 2);
1498 HtpRequestBodyMultipartParseHeader(hstate, htud, header, header_len,
1499 &filename, &filename_len, &filetype, &filetype_len);
1501 if (filename != NULL) {
1502 const uint8_t *filedata = NULL;
1503 uint32_t filedata_len = 0;
1514 if (form_end != NULL) {
1517 filedata = header_end + 4;
1518 if (form_end == filedata) {
1519 HTPSetEvent(hstate, htud, STREAM_TOSERVER,
1522 }
else if (form_end < filedata) {
1523 HTPSetEvent(hstate, htud, STREAM_TOSERVER,
1528 filedata_len = form_end - (header_end + 4 + 2);
1529 SCLogDebug(
"filedata_len %"PRIuMAX, (uintmax_t)filedata_len);
1532 uint8_t *header_next =
Bs2bmSearch(filedata, filedata_len,
1533 boundary, expected_boundary_len);
1534 if (header_next != NULL) {
1535 filedata_len -= (form_end - header_next);
1538 if (filedata_len > chunks_buffer_len) {
1539 HTPSetEvent(hstate, htud, STREAM_TOSERVER,
1543 SCLogDebug(
"filedata_len %"PRIuMAX, (uintmax_t)filedata_len);
1545 printf(
"FILEDATA START: \n");
1547 printf(
"FILEDATA END: \n");
1550 result =
HTPFileOpen(hstate, htud, filename, filename_len, filedata, filedata_len,
1551 HtpGetActiveRequestTxID(hstate), STREAM_TOSERVER);
1554 }
else if (result == -2) {
1557 if (
HTPFileClose(hstate, htud, NULL, 0, 0, STREAM_TOSERVER) == -1) {
1561 FlagDetectStateNewFile(htud, STREAM_TOSERVER);
1566 SCLogDebug(
"chunk doesn't contain form end");
1568 filedata = header_end + 4;
1569 filedata_len = chunks_buffer_len - (filedata - chunks_buffer);
1570 SCLogDebug(
"filedata_len %u (chunks_buffer_len %u)", filedata_len, chunks_buffer_len);
1572 if (filedata_len > chunks_buffer_len) {
1573 HTPSetEvent(hstate, htud, STREAM_TOSERVER,
1579 printf(
"FILEDATA START: \n");
1581 printf(
"FILEDATA END: \n");
1585 uint8_t *header_next =
Bs2bmSearch(filedata, filedata_len,
1586 boundary, expected_boundary_len);
1588 if (header_next == NULL) {
1591 uint32_t
offset = (header_end + 4) - chunks_buffer;
1595 if (filedata_len >= (uint32_t)(expected_boundary_len + 2)) {
1596 filedata_len -= (expected_boundary_len + 2 - 1);
1597 SCLogDebug(
"opening file with partial data");
1602 result =
HTPFileOpen(hstate, htud, filename, filename_len, filedata,
1603 filedata_len, HtpGetActiveRequestTxID(hstate), STREAM_TOSERVER);
1606 }
else if (result == -2) {
1609 FlagDetectStateNewFile(htud, STREAM_TOSERVER);
1613 }
else if (header_next - filedata > 2) {
1614 filedata_len = header_next - filedata - 2;
1617 result =
HTPFileOpen(hstate, htud, filename, filename_len, filedata,
1618 filedata_len, HtpGetActiveRequestTxID(hstate), STREAM_TOSERVER);
1621 }
else if (result == -2) {
1624 if (
HTPFileClose(hstate, htud, NULL, 0, 0, STREAM_TOSERVER) == -1) {
1628 FlagDetectStateNewFile(htud, STREAM_TOSERVER);
1636 SCLogDebug(
"header_start %p, header_end %p, form_end %p",
1637 header_start, header_end, form_end);
1640 uint32_t cursizeread = header_end - chunks_buffer;
1642 chunks_buffer_len - (cursizeread + 4),
1643 boundary, expected_boundary_len);
1644 if (header_start != NULL) {
1646 chunks_buffer_len - (cursizeread + 4),
1647 (uint8_t *)
"\r\n\r\n", 4);
1654 if (chunks_buffer_len > expected_boundary_end_len) {
1655 uint32_t move = chunks_buffer_len - expected_boundary_end_len + 1;
1658 SCLogDebug(
"form not ready, file not set, parsing non-file "
1659 "record: moved %u", move);
1672 htp_tx_t *tx, uint8_t *data, uint32_t data_len)
1679 uint8_t *filename = NULL;
1680 size_t filename_len = 0;
1683 if (tx->parsed_uri != NULL && tx->parsed_uri->path != NULL) {
1684 filename = (uint8_t *)bstr_ptr(tx->parsed_uri->path);
1685 filename_len = bstr_len(tx->parsed_uri->path);
1688 if (filename != NULL) {
1694 result =
HTPFileOpen(hstate, htud, filename, (uint16_t)filename_len, data, data_len,
1695 HtpGetActiveRequestTxID(hstate), STREAM_TOSERVER);
1698 }
else if (result == -2) {
1701 FlagDetectStateNewFile(htud, STREAM_TOSERVER);
1715 }
else if (result == -2) {
1728 htp_tx_t *tx, uint8_t *data, uint32_t data_len)
1739 (tx->response_line != NULL || tx->is_protocol_0_9))
1743 uint8_t *filename = NULL;
1744 size_t filename_len = 0;
1747 htp_header_t *h = (htp_header_t *)htp_table_get_c(tx->response_headers,
1748 "Content-Disposition");
1749 if (h != NULL && bstr_len(h->value) > 0) {
1751 (void)HTTPParseContentDispositionHeader((uint8_t *)
"filename=", 9,
1752 (uint8_t *) bstr_ptr(h->value), bstr_len(h->value), &filename, &filename_len);
1756 if (filename == NULL) {
1758 if (tx->parsed_uri != NULL && tx->parsed_uri->path != NULL) {
1759 filename = (uint8_t *)bstr_ptr(tx->parsed_uri->path);
1760 filename_len = bstr_len(tx->parsed_uri->path);
1764 if (filename != NULL) {
1766 htp_header_t *h_content_range = htp_table_get_c(tx->response_headers,
"content-range");
1772 if (h_content_range != NULL) {
1774 data_len, HtpGetActiveResponseTxID(hstate), h_content_range->value, htud);
1776 result =
HTPFileOpen(hstate, htud, filename, (uint16_t)filename_len, data, data_len,
1777 HtpGetActiveResponseTxID(hstate), STREAM_TOCLIENT);
1782 }
else if (result == -2) {
1785 FlagDetectStateNewFile(htud, STREAM_TOCLIENT);
1791 else if (tx->response_line != NULL || tx->is_protocol_0_9)
1800 }
else if (result == -2) {
1818 static int HTPCallbackRequestBodyData(htp_tx_data_t *d)
1829 printf(
"HTPBODY START: \n");
1831 printf(
"HTPBODY END: \n");
1834 HtpState *hstate = htp_connp_get_user_data(d->tx->connp);
1835 if (hstate == NULL) {
1839 SCLogDebug(
"New request body data available at %p -> %p -> %p, bodylen "
1840 "%"PRIu32
"", hstate, d, d->data, (uint32_t)d->len);
1843 if (tx_ud == NULL) {
1851 if (d->tx->request_method_number == HTP_M_POST) {
1853 int r = HtpRequestBodySetupMultipart(d->tx, tx_ud);
1856 }
else if (r == 0) {
1860 }
else if (d->tx->request_method_number == HTP_M_PUT) {
1883 const uint8_t *chunks_buffer = NULL;
1884 uint32_t chunks_buffer_len = 0;
1892 HtpRequestBodyReassemble(tx_ud, &chunks_buffer, &chunks_buffer_len);
1893 if (chunks_buffer == NULL) {
1897 printf(
"REASSCHUNK START: \n");
1899 printf(
"REASSCHUNK END: \n");
1902 HtpRequestBodyHandleMultipart(hstate, tx_ud, d->tx, chunks_buffer, chunks_buffer_len);
1906 HtpRequestBodyHandlePOSTorPUT(hstate, tx_ud, d->tx, (uint8_t *)d->data,
len);
1911 SCLogDebug(
"closing file that was being stored");
1918 if (hstate->
conn != NULL) {
1919 SCLogDebug(
"checking body size %"PRIu64
" against inspect limit %u (cur %"PRIu64
", last %"PRIu64
")",
1933 const uint32_t data_size = (uint32_t)(
1954 static int HTPCallbackResponseBodyData(htp_tx_data_t *d)
1964 HtpState *hstate = htp_connp_get_user_data(d->tx->connp);
1965 if (hstate == NULL) {
1969 SCLogDebug(
"New response body data available at %p -> %p -> %p, bodylen "
1970 "%"PRIu32
"", hstate, d, d->data, (uint32_t)d->len);
1973 if (tx_ud == NULL) {
1999 HtpResponseBodyHandle(hstate, tx_ud, d->tx, (uint8_t *)d->data,
len);
2002 SCLogDebug(
"closing file that was being stored");
2008 if (hstate->
conn != NULL) {
2009 SCLogDebug(
"checking body size %"PRIu64
" against inspect limit %u (cur %"PRIu64
", last %"PRIu64
")",
2022 const uint32_t data_size = (uint32_t)((uint64_t)hstate->
conn->out_data_counter -
2046 SCLogDebug(
"http_state_memcnt %"PRIu64
", http_state_memuse %"PRIu64
"",
2047 htp_state_memcnt, htp_state_memuse);
2067 htp_config_destroy(cfglist.
cfg);
2068 while (nextrec != NULL) {
2070 nextrec = nextrec->
next;
2072 htp_config_destroy(htprec->
cfg);
2078 static int HTPCallbackRequestHasTrailer(htp_tx_t *tx)
2087 static int HTPCallbackResponseHasTrailer(htp_tx_t *tx)
2100 static int HTPCallbackRequestStart(htp_tx_t *tx)
2102 HtpState *hstate = htp_connp_get_user_data(tx->connp);
2103 if (hstate == NULL) {
2107 uint64_t consumed = hstate->
slice->offset + htp_connp_req_data_consumed(hstate->
connp);
2108 SCLogDebug(
"HTTP request start: data offset %" PRIu64
", in_data_counter %" PRIu64, consumed,
2109 (uint64_t)hstate->
conn->in_data_counter);
2126 if (tx_ud == NULL) {
2131 tx_ud->
tx_data.file_tx = STREAM_TOSERVER | STREAM_TOCLIENT;
2132 htp_tx_set_user_data(tx, tx_ud);
2141 static int HTPCallbackResponseStart(htp_tx_t *tx)
2143 HtpState *hstate = htp_connp_get_user_data(tx->connp);
2144 if (hstate == NULL) {
2148 uint64_t consumed = hstate->
slice->offset + htp_connp_res_data_consumed(hstate->
connp);
2149 SCLogDebug(
"HTTP response start: data offset %" PRIu64
", out_data_counter %" PRIu64, consumed,
2150 (uint64_t)hstate->
conn->out_data_counter);
2165 if (tx_ud == NULL) {
2172 htp_tx_set_user_data(tx, tx_ud);
2184 static int HTPCallbackRequestComplete(htp_tx_t *tx)
2192 HtpState *hstate = htp_connp_get_user_data(tx->connp);
2193 if (hstate == NULL) {
2197 const uint64_t abs_right_edge =
2198 hstate->
slice->offset + htp_connp_req_data_consumed(hstate->
connp);
2206 SCLogDebug(
"HTTP request complete: data offset %" PRIu64
", request_size %" PRIu64,
2208 SCLogDebug(
"frame %p/%" PRIi64
" setting len to %" PRIu64, frame, frame->
id,
2210 frame->
len = (int64_t)request_size;
2216 SCLogDebug(
"transaction_cnt %"PRIu64
", list_size %"PRIu64,
2221 HTPErrorCheckTxRequestFlags(hstate, tx);
2226 SCLogDebug(
"closing file that was being stored");
2227 (void)
HTPFileClose(hstate, htud, NULL, 0, 0, STREAM_TOSERVER);
2229 if (abs_right_edge < (uint64_t)UINT32_MAX) {
2231 hstate->
f->
protoctx, STREAM_TOSERVER, (uint32_t)abs_right_edge);
2249 static int HTPCallbackResponseComplete(htp_tx_t *tx)
2253 HtpState *hstate = htp_connp_get_user_data(tx->connp);
2254 if (hstate == NULL) {
2261 const uint64_t abs_right_edge =
2262 hstate->
slice->offset + htp_connp_res_data_consumed(hstate->
connp);
2269 SCLogDebug(
"HTTP response complete: data offset %" PRIu64
", response_size %" PRIu64,
2271 SCLogDebug(
"frame %p/%" PRIi64
" setting len to %" PRIu64, frame, frame->
id,
2273 frame->
len = (int64_t)response_size;
2281 SCLogDebug(
"closing file that was being stored");
2282 (void)
HTPFileClose(hstate, htud, NULL, 0, 0, STREAM_TOCLIENT);
2292 if (tx->request_method_number == HTP_M_CONNECT) {
2295 if ((tx->response_status_number >= 200) &&
2296 (tx->response_status_number < 300) &&
2299 if (tx->request_port_number != -1) {
2300 dp = (uint16_t)tx->request_port_number;
2307 tx->request_progress = HTP_REQUEST_COMPLETE;
2308 tx->response_progress = HTP_RESPONSE_COMPLETE;
2316 static int HTPCallbackRequestLine(htp_tx_t *tx)
2319 bstr *request_uri_normalized;
2320 HtpState *hstate = htp_connp_get_user_data(tx->connp);
2324 if (request_uri_normalized == NULL)
2327 tx_ud = htp_tx_get_user_data(tx);
2336 HTPErrorCheckTxRequestFlags(hstate, tx);
2341 static int HTPCallbackDoubleDecodeUriPart(htp_tx_t *tx, bstr *part)
2347 size_t prevlen = bstr_len(part);
2348 htp_status_t res = htp_urldecode_inplace(tx->cfg, HTP_DECODER_URLENCODED, part, &
flags);
2350 if (res == HTP_OK && prevlen > bstr_len(part)) {
2354 HtpState *s = htp_connp_get_user_data(tx->connp);
2357 HTPSetEvent(s, htud, STREAM_TOSERVER,
2364 static int HTPCallbackDoubleDecodeQuery(htp_tx_t *tx)
2366 if (tx->parsed_uri == NULL)
2369 return HTPCallbackDoubleDecodeUriPart(tx, tx->parsed_uri->query);
2372 static int HTPCallbackDoubleDecodePath(htp_tx_t *tx)
2374 if (tx->parsed_uri == NULL)
2377 return HTPCallbackDoubleDecodeUriPart(tx, tx->parsed_uri->path);
2380 static int HTPCallbackRequestHeaderData(htp_tx_data_t *tx_data)
2383 if (tx_data->len == 0 || tx_data->tx == NULL)
2387 if (tx_ud == NULL) {
2399 tx_data->data, tx_data->len);
2402 if (tx_data->tx && tx_data->tx->flags) {
2403 HtpState *hstate = htp_connp_get_user_data(tx_data->tx->connp);
2404 HTPErrorCheckTxRequestFlags(hstate, tx_data->tx);
2409 static int HTPCallbackResponseHeaderData(htp_tx_data_t *tx_data)
2412 if (tx_data->len == 0 || tx_data->tx == NULL)
2416 if (tx_ud == NULL) {
2428 tx_data->data, tx_data->len);
2437 static void HTPConfigSetDefaultsPhase1(
HTPCfgRec *cfg_prec)
2454 htp_config_register_request_header_data(cfg_prec->
cfg, HTPCallbackRequestHeaderData);
2455 htp_config_register_request_trailer_data(cfg_prec->
cfg, HTPCallbackRequestHeaderData);
2456 htp_config_register_response_header_data(cfg_prec->
cfg, HTPCallbackResponseHeaderData);
2457 htp_config_register_response_trailer_data(cfg_prec->
cfg, HTPCallbackResponseHeaderData);
2459 htp_config_register_request_trailer(cfg_prec->
cfg, HTPCallbackRequestHasTrailer);
2460 htp_config_register_response_trailer(cfg_prec->
cfg, HTPCallbackResponseHasTrailer);
2462 htp_config_register_request_body_data(cfg_prec->
cfg, HTPCallbackRequestBodyData);
2463 htp_config_register_response_body_data(cfg_prec->
cfg, HTPCallbackResponseBodyData);
2465 htp_config_register_request_start(cfg_prec->
cfg, HTPCallbackRequestStart);
2466 htp_config_register_request_complete(cfg_prec->
cfg, HTPCallbackRequestComplete);
2468 htp_config_register_response_start(cfg_prec->
cfg, HTPCallbackResponseStart);
2469 htp_config_register_response_complete(cfg_prec->
cfg, HTPCallbackResponseComplete);
2471 htp_config_set_parse_request_cookies(cfg_prec->
cfg, 0);
2474 htp_config_set_plusspace_decode(cfg_prec->
cfg, HTP_DECODER_URLENCODED, 0);
2476 htp_config_set_request_decompression(cfg_prec->
cfg, 1);
2477 #ifdef HAVE_HTP_CONFIG_SET_LZMA_LAYERS
2481 #ifdef HAVE_HTP_CONFIG_SET_LZMA_MEMLIMIT
2482 htp_config_set_lzma_memlimit(cfg_prec->
cfg,
2485 #ifdef HAVE_HTP_CONFIG_SET_COMPRESSION_BOMB_LIMIT
2486 htp_config_set_compression_bomb_limit(cfg_prec->
cfg,
2489 #ifdef HAVE_HTP_CONFIG_SET_COMPRESSION_TIME_LIMIT
2498 htp_config_set_field_limits(cfg_prec->
cfg,
2507 static int RandomGetWrap(
void)
2513 }
while(r >= ULONG_MAX - (ULONG_MAX % RAND_MAX));
2515 return r % RAND_MAX;
2524 static void HTPConfigSetDefaultsPhase2(
const char *name,
HTPCfgRec *cfg_prec)
2530 long int r = RandomGetWrap();
2532 ((
double)r / RAND_MAX - 0.5) * rdrange / 100);
2534 r = RandomGetWrap();
2536 ((
double)r / RAND_MAX - 0.5) * rdrange / 100);
2537 SCLogConfig(
"'%s' server has 'request-body-minimal-inspect-size' set to"
2538 " %u and 'request-body-inspect-window' set to %u after"
2542 r = RandomGetWrap();
2544 ((
double)r / RAND_MAX - 0.5) * rdrange / 100);
2546 r = RandomGetWrap();
2548 ((
double)r / RAND_MAX - 0.5) * rdrange / 100);
2550 SCLogConfig(
"'%s' server has 'response-body-minimal-inspect-size' set to"
2551 " %u and 'response-body-inspect-window' set to %u after"
2556 htp_config_register_request_line(cfg_prec->
cfg, HTPCallbackRequestLine);
2563 if (cfg_prec == NULL || s == NULL || tree == NULL)
2571 if (strcasecmp(
"address", p->
name) == 0) {
2579 if (strchr(pval->
val,
':') != NULL) {
2580 SCLogDebug(
"LIBHTP adding ipv6 server %s at %s: %p",
2584 "add ipv6 server %s, ignoring",
2588 SCLogDebug(
"LIBHTP adding ipv4 server %s at %s: %p",
2592 "to add ipv4 server %s, ignoring",
2598 }
else if (strcasecmp(
"personality", p->
name) == 0) {
2600 int personality = HTPLookupPersonality(p->
val);
2604 if (personality >= 0) {
2607 if (htp_config_set_server_personality(cfg_prec->
cfg, personality) == HTP_ERROR){
2609 "personality \"%s\", ignoring",
2613 HTPLookupPersonalityString(personality));
2619 htp_config_set_convert_lowercase(cfg_prec->
cfg, HTP_DECODER_URL_PATH, 0);
2627 }
else if (strcasecmp(
"request-body-limit", p->
name) == 0 ||
2628 strcasecmp(
"request_body_limit", p->
name) == 0) {
2630 SCLogError(
"Error parsing request-body-limit "
2631 "from conf file - %s. Killing engine",
2636 }
else if (strcasecmp(
"response-body-limit", p->
name) == 0) {
2638 SCLogError(
"Error parsing response-body-limit "
2639 "from conf file - %s. Killing engine",
2644 }
else if (strcasecmp(
"request-body-minimal-inspect-size", p->
name) == 0) {
2646 SCLogError(
"Error parsing request-body-minimal-inspect-size "
2647 "from conf file - %s. Killing engine",
2652 }
else if (strcasecmp(
"request-body-inspect-window", p->
name) == 0) {
2654 SCLogError(
"Error parsing request-body-inspect-window "
2655 "from conf file - %s. Killing engine",
2660 }
else if (strcasecmp(
"double-decode-query", p->
name) == 0) {
2662 htp_config_register_request_line(cfg_prec->
cfg,
2663 HTPCallbackDoubleDecodeQuery);
2666 }
else if (strcasecmp(
"double-decode-path", p->
name) == 0) {
2668 htp_config_register_request_line(cfg_prec->
cfg,
2669 HTPCallbackDoubleDecodePath);
2672 }
else if (strcasecmp(
"response-body-minimal-inspect-size", p->
name) == 0) {
2674 SCLogError(
"Error parsing response-body-minimal-inspect-size "
2675 "from conf file - %s. Killing engine",
2680 }
else if (strcasecmp(
"response-body-inspect-window", p->
name) == 0) {
2682 SCLogError(
"Error parsing response-body-inspect-window "
2683 "from conf file - %s. Killing engine",
2688 }
else if (strcasecmp(
"response-body-decompress-layer-limit", p->
name) == 0) {
2691 SCLogError(
"Error parsing response-body-inspect-window "
2692 "from conf file - %s. Killing engine",
2696 #ifdef HAVE_HTP_CONFIG_SET_RESPONSE_DECOMPRESSION_LAYER_LIMIT
2697 htp_config_set_response_decompression_layer_limit(cfg_prec->
cfg, value);
2699 SCLogWarning(
"can't set response-body-decompress-layer-limit "
2700 "to %u, libhtp version too old",
2703 }
else if (strcasecmp(
"path-convert-backslash-separators", p->
name) == 0) {
2704 htp_config_set_backslash_convert_slashes(cfg_prec->
cfg,
2705 HTP_DECODER_URL_PATH,
2707 }
else if (strcasecmp(
"path-bestfit-replacement-char", p->
name) == 0) {
2708 if (strlen(p->
val) == 1) {
2709 htp_config_set_bestfit_replacement_byte(cfg_prec->
cfg,
2710 HTP_DECODER_URL_PATH,
2714 "for libhtp param path-bestfit-replacement-char");
2716 }
else if (strcasecmp(
"path-convert-lowercase", p->
name) == 0) {
2717 htp_config_set_convert_lowercase(cfg_prec->
cfg,
2718 HTP_DECODER_URL_PATH,
2720 }
else if (strcasecmp(
"path-nul-encoded-terminates", p->
name) == 0) {
2721 htp_config_set_nul_encoded_terminates(cfg_prec->
cfg,
2722 HTP_DECODER_URL_PATH,
2724 }
else if (strcasecmp(
"path-nul-raw-terminates", p->
name) == 0) {
2725 htp_config_set_nul_raw_terminates(cfg_prec->
cfg,
2726 HTP_DECODER_URL_PATH,
2728 }
else if (strcasecmp(
"path-separators-compress", p->
name) == 0) {
2729 htp_config_set_path_separators_compress(cfg_prec->
cfg,
2730 HTP_DECODER_URL_PATH,
2732 }
else if (strcasecmp(
"path-separators-decode", p->
name) == 0) {
2733 htp_config_set_path_separators_decode(cfg_prec->
cfg,
2734 HTP_DECODER_URL_PATH,
2736 }
else if (strcasecmp(
"path-u-encoding-decode", p->
name) == 0) {
2737 htp_config_set_u_encoding_decode(cfg_prec->
cfg,
2738 HTP_DECODER_URL_PATH,
2740 }
else if (strcasecmp(
"path-url-encoding-invalid-handling", p->
name) == 0) {
2741 enum htp_url_encoding_handling_t handling;
2742 if (strcasecmp(p->
val,
"preserve_percent") == 0) {
2743 handling = HTP_URL_DECODE_PRESERVE_PERCENT;
2744 }
else if (strcasecmp(p->
val,
"remove_percent") == 0) {
2745 handling = HTP_URL_DECODE_REMOVE_PERCENT;
2746 }
else if (strcasecmp(p->
val,
"decode_invalid") == 0) {
2747 handling = HTP_URL_DECODE_PROCESS_INVALID;
2750 "for libhtp param path-url-encoding-invalid-handling");
2753 htp_config_set_url_encoding_invalid_handling(cfg_prec->
cfg,
2754 HTP_DECODER_URL_PATH,
2756 }
else if (strcasecmp(
"path-utf8-convert-bestfit", p->
name) == 0) {
2757 htp_config_set_utf8_convert_bestfit(cfg_prec->
cfg,
2758 HTP_DECODER_URL_PATH,
2760 }
else if (strcasecmp(
"uri-include-all", p->
name) == 0) {
2764 }
else if (strcasecmp(
"query-plusspace-decode", p->
name) == 0) {
2765 htp_config_set_plusspace_decode(cfg_prec->
cfg,
2766 HTP_DECODER_URLENCODED,
2768 }
else if (strcasecmp(
"meta-field-limit", p->
name) == 0) {
2772 "from conf file - %s. Killing engine",
2778 "from conf file cannot be 0. Killing engine");
2781 htp_config_set_field_limits(cfg_prec->
cfg,
2784 #ifdef HAVE_HTP_CONFIG_SET_LZMA_MEMLIMIT
2785 }
else if (strcasecmp(
"lzma-memlimit", p->
name) == 0) {
2788 FatalError(
"failed to parse 'lzma-memlimit' "
2789 "from conf file - %s.",
2794 "from conf file cannot be 0.");
2797 SCLogConfig(
"Setting HTTP LZMA memory limit to %"PRIu32
" bytes", limit);
2798 htp_config_set_lzma_memlimit(cfg_prec->
cfg, (
size_t)limit);
2800 #ifdef HAVE_HTP_CONFIG_SET_LZMA_LAYERS
2801 }
else if (strcasecmp(
"lzma-enabled", p->
name) == 0) {
2803 htp_config_set_lzma_layers(cfg_prec->
cfg, 1);
2808 "from conf file - %s.",
2811 SCLogConfig(
"Setting HTTP LZMA decompression layers to %" PRIu32
"", (
int)limit);
2812 htp_config_set_lzma_layers(cfg_prec->
cfg, limit);
2815 #ifdef HAVE_HTP_CONFIG_SET_COMPRESSION_BOMB_LIMIT
2816 }
else if (strcasecmp(
"compression-bomb-limit", p->
name) == 0) {
2819 FatalError(
"failed to parse 'compression-bomb-limit' "
2820 "from conf file - %s.",
2825 "from conf file cannot be 0.");
2828 SCLogConfig(
"Setting HTTP compression bomb limit to %"PRIu32
" bytes", limit);
2829 htp_config_set_compression_bomb_limit(cfg_prec->
cfg, (
size_t)limit);
2831 #ifdef HAVE_HTP_CONFIG_SET_COMPRESSION_TIME_LIMIT
2832 }
else if (strcasecmp(
"decompression-time-limit", p->
name) == 0) {
2836 FatalError(
"failed to parse 'decompression-time-limit' "
2837 "from conf file - %s.",
2840 SCLogConfig(
"Setting HTTP decompression time limit to %" PRIu32
" usec", limit);
2841 htp_config_set_compression_time_limit(cfg_prec->
cfg, (
size_t)limit);
2843 }
else if (strcasecmp(
"randomize-inspection-sizes", p->
name) == 0) {
2847 }
else if (strcasecmp(
"randomize-inspection-range", p->
name) == 0) {
2850 (
const char *)p->
val, 0, 100) < 0) {
2852 "-inspection-range setting from conf file - \"%s\"."
2853 " It should be a valid integer less than or equal to 100."
2859 }
else if (strcasecmp(
"http-body-inline", p->
name) == 0) {
2865 if (strcmp(
"auto", p->
val) != 0) {
2874 }
else if (strcasecmp(
"swf-decompression", p->
name) == 0) {
2878 if (strcasecmp(
"enabled", pval->
name) == 0) {
2886 }
else if (strcasecmp(
"type", pval->
name) == 0) {
2887 if (strcasecmp(
"no", pval->
val) == 0) {
2889 }
else if (strcasecmp(
"deflate", pval->
val) == 0) {
2891 }
else if (strcasecmp(
"lzma", pval->
val) == 0) {
2893 }
else if (strcasecmp(
"both", pval->
val) == 0) {
2897 "swf-decompression.type: %s - "
2902 }
else if (strcasecmp(
"compress-depth", pval->
name) == 0) {
2904 SCLogError(
"Error parsing swf-decompression.compression-depth "
2905 "from conf file - %s. Killing engine",
2909 }
else if (strcasecmp(
"decompress-depth", pval->
name) == 0) {
2911 SCLogError(
"Error parsing swf-decompression.decompression-depth "
2912 "from conf file - %s. Killing engine",
2922 "default config: %s",
2934 cfglist.
next = NULL;
2941 if (NULL == cfgtree)
2945 cfglist.
cfg = htp_config_create();
2946 if (NULL == cfglist.
cfg) {
2947 FatalError(
"Failed to create HTP default config");
2950 HTPConfigSetDefaultsPhase1(&cfglist);
2951 if (
ConfGetNode(
"app-layer.protocols.http.libhtp") == NULL) {
2952 HTPConfigParseParameters(&cfglist,
ConfGetNode(
"libhtp.default-config"),
2955 HTPConfigParseParameters(&cfglist,
ConfGetNode(
"app-layer.protocols.http.libhtp.default-config"), cfgtree);
2957 HTPConfigSetDefaultsPhase2(
"default", &cfglist);
2963 if (server_config == NULL) {
2964 server_config =
ConfGetNode(
"libhtp.server-config");
2965 if (server_config == NULL) {
2966 SCLogDebug(
"LIBHTP Configuring %p", server_config);
2970 SCLogDebug(
"LIBHTP Configuring %p", server_config);
2988 memset(htprec, 0x00,
sizeof(*htprec));
2990 cfglist.
next = htprec;
2993 cfglist.
next->
cfg = htp_config_create();
2994 if (NULL == cfglist.
next->
cfg) {
2995 FatalError(
"Failed to create HTP server config");
2998 HTPConfigSetDefaultsPhase1(htprec);
2999 HTPConfigParseParameters(htprec, s, cfgtree);
3000 HTPConfigSetDefaultsPhase2(s->
name, htprec);
3010 SCLogPerf(
"htp memory %"PRIu64
" (%"PRIu64
")", htp_state_memuse, htp_state_memcnt);
3021 static AppLayerGetFileState HTPGetTxFiles(
void *state,
void *txv, uint8_t direction)
3023 AppLayerGetFileState files = { .fc = NULL, .cfg = &
htp_sbcfg };
3024 htp_tx_t *tx = (htp_tx_t *)txv;
3027 if (direction & STREAM_TOCLIENT) {
3036 static int HTPStateGetAlstateProgress(
void *tx, uint8_t direction)
3038 if (direction & STREAM_TOSERVER)
3039 return ((htp_tx_t *)tx)->request_progress;
3041 return ((htp_tx_t *)tx)->response_progress;
3044 static uint64_t HTPStateGetTxCnt(
void *alstate)
3048 if (http_state != NULL && http_state->
conn != NULL) {
3049 const int64_t size = (int64_t)htp_list_size(http_state->
conn->transactions);
3053 return (uint64_t)size;
3059 static void *HTPStateGetTx(
void *alstate, uint64_t tx_id)
3063 if (http_state != NULL && http_state->
conn != NULL)
3064 return htp_list_get(http_state->
conn->transactions, tx_id);
3073 if (http_state != NULL && http_state->
conn != NULL) {
3074 size_t txid = htp_list_array_size(http_state->
conn->transactions);
3076 return htp_list_get(http_state->
conn->transactions, txid - 1);
3082 static int HTPStateGetEventInfo(
const char *event_name,
3086 if (*event_id == -1) {
3088 "http's enum map table.",
3099 static int HTPStateGetEventInfoById(
int event_id,
const char **event_name,
3103 if (*event_name == NULL) {
3105 "http's enum map table.",
3118 htp_tx_t *tx = (htp_tx_t *)vtx;
3126 static AppLayerStateData *HTPGetStateData(
void *vstate)
3132 static int HTPRegisterPatternsForProtocolDetection(
void)
3134 const char *methods[] = {
"GET",
"PUT",
"POST",
"HEAD",
"TRACE",
"OPTIONS",
3135 "CONNECT",
"DELETE",
"PATCH",
"PROPFIND",
"PROPPATCH",
"MKCOL",
3136 "COPY",
"MOVE",
"LOCK",
"UNLOCK",
"CHECKOUT",
"UNCHECKOUT",
"CHECKIN",
3137 "UPDATE",
"LABEL",
"REPORT",
"MKWORKSPACE",
"MKACTIVITY",
"MERGE",
3138 "INVALID",
"VERSION-CONTROL",
"BASELINE-CONTROL", NULL};
3139 const char *spacings[] = {
"|20|",
"|09|", NULL };
3140 const char *versions[] = {
"HTTP/0.9",
"HTTP/1.0",
"HTTP/1.1", NULL };
3145 int register_result;
3146 char method_buffer[32] =
"";
3149 for (methods_pos = 0; methods[methods_pos]; methods_pos++) {
3150 for (spacings_pos = 0; spacings[spacings_pos]; spacings_pos++) {
3153 snprintf(method_buffer,
sizeof(method_buffer),
"%s%s", methods[methods_pos], spacings[spacings_pos]);
3160 method_buffer, (uint16_t)strlen(method_buffer) - 3, 0, STREAM_TOSERVER);
3161 if (register_result < 0) {
3168 for (versions_pos = 0; versions[versions_pos]; versions_pos++) {
3170 versions[versions_pos], (uint16_t)strlen(versions[versions_pos]), 0,
3172 if (register_result < 0) {
3188 const char *proto_name =
"http";
3193 if (HTPRegisterPatternsForProtocolDetection() < 0)
3196 SCLogInfo(
"Protocol detection and parser disabled for %s protocol",
3211 ALPROTO_HTTP1, HTP_REQUEST_COMPLETE, HTP_RESPONSE_COMPLETE);
3223 IPPROTO_TCP,
ALPROTO_HTTP1, STREAM_TOSERVER, HTPHandleRequestData);
3225 IPPROTO_TCP,
ALPROTO_HTTP1, STREAM_TOCLIENT, HTPHandleResponseData);
3231 IPPROTO_TCP,
ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_TOCLIENT);
3234 IPPROTO_TCP,
ALPROTO_HTTP1, HTTPGetFrameIdByName, HTTPGetFrameNameById);
3238 SCLogInfo(
"Parsed disabled for %s protocol. Protocol detection"
3239 "still on.", proto_name);
3255 cfglist_backup = cfglist;
3262 cfglist = cfglist_backup;
3269 static int HTPParserTest01(
void)
3271 uint8_t httpbuf1[] =
"POST / HTTP/1.0\r\nUser-Agent: Victor/1.0\r\n\r\nPost"
3273 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3276 memset(&ssn, 0,
sizeof(ssn));
3284 f->
proto = IPPROTO_TCP;
3290 for (u = 0; u < httplen1; u++) {
3294 flags = STREAM_TOSERVER|STREAM_START;
3295 else if (u == (httplen1 - 1))
3296 flags = STREAM_TOSERVER|STREAM_EOF;
3298 flags = STREAM_TOSERVER;
3307 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3310 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3313 FAIL_IF(strcmp(bstr_util_strdup_to_c(h->value),
"Victor/1.0"));
3314 FAIL_IF(tx->request_method_number != HTP_M_POST);
3315 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_0);
3324 static int HTPParserTest01b(
void)
3326 uint8_t httpbuf1[] =
"POST / HTTP/1.0\r\nUser-Agent:\r\n Victor/1.0\r\n\r\nPost"
3328 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3331 memset(&ssn, 0,
sizeof(ssn));
3339 f->
proto = IPPROTO_TCP;
3344 uint8_t
flags =STREAM_TOSERVER|STREAM_START|STREAM_EOF;
3351 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3354 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3357 FAIL_IF(strcmp(bstr_util_strdup_to_c(h->value),
"Victor/1.0"));
3358 FAIL_IF(tx->request_method_number != HTP_M_POST);
3359 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_0);
3368 static int HTPParserTest01c(
void)
3370 uint8_t httpbuf1[] =
"POST / HTTP/1.0\r\nUser-Agent:\r\n Victor/1.0\r\n\r\nPost"
3372 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3375 memset(&ssn, 0,
sizeof(ssn));
3383 f->
proto = IPPROTO_TCP;
3389 for (u = 0; u < httplen1; u++) {
3393 flags = STREAM_TOSERVER|STREAM_START;
3394 else if (u == (httplen1 - 1))
3395 flags = STREAM_TOSERVER|STREAM_EOF;
3397 flags = STREAM_TOSERVER;
3406 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3409 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3412 FAIL_IF(strcmp(bstr_util_strdup_to_c(h->value),
"Victor/1.0"));
3413 FAIL_IF(tx->request_method_number != HTP_M_POST);
3414 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_0);
3424 static int HTPParserTest01a(
void)
3428 uint8_t httpbuf1[] =
" POST / HTTP/1.0\r\nUser-Agent: Victor/1.0\r\n\r\nPost"
3430 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3436 memset(&ssn, 0,
sizeof(ssn));
3438 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
3442 f->
proto = IPPROTO_TCP;
3448 for (u = 0; u < httplen1; u++) {
3452 flags = STREAM_TOSERVER|STREAM_START;
3453 else if (u == (httplen1 - 1))
3454 flags = STREAM_TOSERVER|STREAM_EOF;
3456 flags = STREAM_TOSERVER;
3460 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
3467 if (htp_state == NULL) {
3468 printf(
"no http state: ");
3472 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3473 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3474 if (strcmp(bstr_util_strdup_to_c(h->value),
"Victor/1.0")
3475 || tx->request_method_number != HTP_M_POST ||
3476 tx->request_protocol_number != HTP_PROTOCOL_1_0)
3478 printf(
"expected header value: Victor/1.0 and got %s: and expected"
3479 " method: POST and got %s, expected protocol number HTTP/1.0"
3480 " and got: %s \n", bstr_util_strdup_to_c(h->value),
3481 bstr_util_strdup_to_c(tx->request_method),
3482 bstr_util_strdup_to_c(tx->request_protocol));
3495 static int HTPParserTest02(
void)
3499 uint8_t httpbuf1[] =
"POST";
3500 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3505 memset(&ssn, 0,
sizeof(ssn));
3507 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
3511 f->
proto = IPPROTO_TCP;
3517 STREAM_TOSERVER | STREAM_START | STREAM_EOF, httpbuf1, httplen1);
3519 printf(
"toserver chunk 1 returned %" PRId32
", expected 0: ", r);
3524 if (http_state == NULL) {
3525 printf(
"no http state: ");
3529 htp_tx_t *tx = HTPStateGetTx(http_state, 0);
3531 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3535 char *method = bstr_util_strdup_to_c(tx->request_method);
3538 FAIL_IF(strcmp(method,
"POST") != 0);
3552 static int HTPParserTest03(
void)
3556 uint8_t httpbuf1[] =
"HELLO / HTTP/1.0\r\n";
3557 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3563 memset(&ssn, 0,
sizeof(ssn));
3565 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
3569 f->
proto = IPPROTO_TCP;
3575 for (u = 0; u < httplen1; u++) {
3578 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
3579 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
3580 else flags = STREAM_TOSERVER;
3584 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
3590 if (htp_state == NULL) {
3591 printf(
"no http state: ");
3595 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3597 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3598 if (tx->request_method_number != HTP_M_UNKNOWN ||
3599 h != NULL || tx->request_protocol_number != HTP_PROTOCOL_1_0)
3601 printf(
"expected method M_UNKNOWN and got %s: , expected protocol "
3602 "HTTP/1.0 and got %s \n", bstr_util_strdup_to_c(tx->request_method),
3603 bstr_util_strdup_to_c(tx->request_protocol));
3617 static int HTPParserTest04(
void)
3622 uint8_t httpbuf1[] =
"World!\r\n";
3623 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3628 memset(&ssn, 0,
sizeof(ssn));
3630 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
3634 f->
proto = IPPROTO_TCP;
3640 STREAM_TOSERVER | STREAM_START | STREAM_EOF, httpbuf1, httplen1);
3646 if (htp_state == NULL) {
3647 printf(
"no http state: ");
3651 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3652 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3653 if (tx->request_method_number != HTP_M_UNKNOWN ||
3654 h != NULL || tx->request_protocol_number != HTP_PROTOCOL_0_9)
3656 printf(
"expected method M_UNKNOWN and got %s: , expected protocol "
3657 "NULL and got %s \n", bstr_util_strdup_to_c(tx->request_method),
3658 bstr_util_strdup_to_c(tx->request_protocol));
3672 static int HTPParserTest05(
void)
3674 uint8_t httpbuf1[] =
"POST / HTTP/1.0\r\nUser-Agent: Victor/1.0\r\nContent-Length: 17\r\n\r\n";
3675 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3676 uint8_t httpbuf2[] =
"Post D";
3677 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
3678 uint8_t httpbuf3[] =
"ata is c0oL!";
3679 uint32_t httplen3 =
sizeof(httpbuf3) - 1;
3681 uint8_t httpbuf4[] =
"HTTP/1.0 200 OK\r\nServer: VictorServer/1.0\r\n\r\n";
3682 uint32_t httplen4 =
sizeof(httpbuf4) - 1;
3683 uint8_t httpbuf5[] =
"post R";
3684 uint32_t httplen5 =
sizeof(httpbuf5) - 1;
3685 uint8_t httpbuf6[] =
"esults are tha bomb!";
3686 uint32_t httplen6 =
sizeof(httpbuf6) - 1;
3689 memset(&ssn, 0,
sizeof(ssn));
3697 f->
proto = IPPROTO_TCP;
3727 htp_tx_t *tx = HTPStateGetTx(http_state, 0);
3729 FAIL_IF_NOT(tx->request_method_number == HTP_M_POST);
3730 FAIL_IF_NOT(tx->request_protocol_number == HTP_PROTOCOL_1_0);
3732 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3745 static int HTPParserTest06(
void)
3747 uint8_t httpbuf1[] =
"GET /ld/index.php?id=412784631&cid=0064&version=4&"
3748 "name=try HTTP/1.1\r\nAccept: */*\r\nUser-Agent: "
3749 "LD-agent\r\nHost: 209.205.196.16\r\n\r\n";
3750 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3751 uint8_t httpbuf2[] =
"HTTP/1.1 200 OK\r\nDate: Sat, 03 Oct 2009 10:16:02 "
3753 "Server: Apache/1.3.37 (Unix) mod_ssl/2.8.28 "
3754 "OpenSSL/0.9.7a PHP/4.4.7 mod_perl/1.29 "
3755 "FrontPage/5.0.2.2510\r\n"
3756 "X-Powered-By: PHP/4.4.7\r\nTransfer-Encoding: "
3758 "Content-Type: text/html\r\n\r\n"
3760 "W2dyb3VwMV0NCnBob25lMT1wMDB3ODgyMTMxMzAyMTINCmxvZ2lu"
3761 "MT0NCnBhc3N3b3JkMT0NCnBob25lMj1wMDB3ODgyMTMxMzAyMTIN"
3762 "CmxvZ2luMj0NCnBhc3N3b3JkMj0NCnBob25lMz0NCmxvZ2luMz0N"
3763 "CnBhc3N3b3JkMz0NCnBob25lND0NCmxvZ2luND0NCnBhc3N3b3Jk"
3764 "ND0NCnBob25lNT0NCmxvZ2luNT0NCnBhc3N3b3JkNT0NCnBob25l"
3765 "Nj0NCmxvZ2luNj0NCnBhc3N3b3JkNj0NCmNhbGxfdGltZTE9MzIN"
3766 "CmNhbGxfdGltZTI9MjMyDQpkYXlfbGltaXQ9NQ0KbW9udGhfbGlt"
3767 "aXQ9MTUNCltncm91cDJdDQpwaG9uZTE9DQpsb2dpbjE9DQpwYXNz"
3768 "d29yZDE9DQpwaG9uZTI9DQpsb2dpbjI9DQpwYXNzd29yZDI9DQpw"
3769 "aG9uZTM9DQpsb2dpbjM9DQpwYXNzd29yZDM9DQpwaG9uZTQ9DQps"
3770 "b2dpbjQ9DQpwYXNzd29yZDQ9DQpwaG9uZTU9DQpsb2dpbjU9DQpw"
3771 "YXNzd29yZDU9DQpwaG9uZTY9DQpsb2dpbjY9DQpwYXNzd29yZDY9"
3772 "DQpjYWxsX3RpbWUxPQ0KY2FsbF90aW1lMj0NCmRheV9saW1pdD0N"
3773 "Cm1vbnRoX2xpbWl0PQ0KW2dyb3VwM10NCnBob25lMT0NCmxvZ2lu"
3774 "MT0NCnBhc3N3b3JkMT0NCnBob25lMj0NCmxvZ2luMj0NCnBhc3N3"
3775 "b3JkMj0NCnBob25lMz0NCmxvZ2luMz0NCnBhc3N3b3JkMz0NCnBo"
3776 "b25lND0NCmxvZ2luND0NCnBhc3N3b3JkND0NCnBob25lNT0NCmxv"
3777 "Z2luNT0NCnBhc3N3b3JkNT0NCnBob25lNj0NCmxvZ2luNj0NCnBh"
3778 "c3N3b3JkNj0NCmNhbGxfdGltZTE9DQpjYWxsX3RpbWUyPQ0KZGF5"
3779 "X2xpbWl0PQ0KbW9udGhfbGltaXQ9DQpbZ3JvdXA0XQ0KcGhvbmUx"
3780 "PQ0KbG9naW4xPQ0KcGFzc3dvcmQxPQ0KcGhvbmUyPQ0KbG9naW4y"
3781 "PQ0KcGFzc3dvcmQyPQ0KcGhvbmUzPQ0KbG9naW4zPQ0KcGFzc3dv"
3782 "cmQzPQ0KcGhvbmU0PQ0KbG9naW40PQ0KcGFzc3dvcmQ0PQ0KcGhv"
3783 "bmU1PQ0KbG9naW41PQ0KcGFzc3dvcmQ1PQ0KcGhvbmU2PQ0KbG9n"
3784 "aW42PQ0KcGFzc3dvcmQ2PQ0KY2FsbF90aW1lMT0NCmNhbGxfdGlt"
3785 "ZTI9DQpkYXlfbGltaXQ9DQptb250aF9saW1pdD0NCltmaWxlc10N"
3786 "Cmxpbms9aHR0cDovLzIwOS4yMDUuMTk2LjE2L2xkL2dldGJvdC5w"
3787 "aHA=\r\n0\r\n\r\n";
3788 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
3794 memset(&ssn, 0,
sizeof(ssn));
3799 f->
proto = IPPROTO_TCP;
3814 htp_tx_t *tx = HTPStateGetTx(http_state, 0);
3817 FAIL_IF(tx->request_method_number != HTP_M_GET);
3818 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_1);
3820 FAIL_IF(tx->response_status_number != 200);
3821 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_1);
3823 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3834 static int HTPParserTest07(
void)
3838 uint8_t httpbuf1[] =
"GET /awstats.pl?/migratemigrate%20=%20| HTTP/1.0\r\n\r\n";
3839 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3845 memset(&ssn, 0,
sizeof(ssn));
3847 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
3851 f->
proto = IPPROTO_TCP;
3857 for (u = 0; u < httplen1; u++) {
3861 flags = STREAM_TOSERVER|STREAM_START;
3862 else if (u == (httplen1 - 1))
3863 flags = STREAM_TOSERVER|STREAM_EOF;
3865 flags = STREAM_TOSERVER;
3869 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
3876 if (htp_state == NULL) {
3877 printf(
"no http state: ");
3881 uint8_t ref[] =
"/awstats.pl?/migratemigrate = |";
3882 size_t reflen =
sizeof(ref) - 1;
3884 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3890 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
3899 printf(
"normalized uri \"");
3921 static int HTPParserTest08(
void)
3925 uint8_t httpbuf1[] =
"GET /secondhouse/image/js/\%ce\%de\%ce\%fd_RentCity.js?v=2011.05.02 HTTP/1.0\r\n\r\n";
3926 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3948 memset(&ssn, 0,
sizeof(ssn));
3950 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
3954 f->
proto = IPPROTO_TCP;
3960 flags = STREAM_TOSERVER|STREAM_START|STREAM_EOF;
3964 printf(
"toserver chunk returned %" PRId32
", expected"
3971 if (htp_state == NULL) {
3972 printf(
"no http state: ");
3977 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4002 static int HTPParserTest09(
void)
4006 uint8_t httpbuf1[] =
"GET /secondhouse/image/js/\%ce\%de\%ce\%fd_RentCity.js?v=2011.05.02 HTTP/1.0\r\n\r\n";
4007 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4017 personality: Apache_2_2\n\
4030 memset(&ssn, 0,
sizeof(ssn));
4032 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
4036 f->
proto = IPPROTO_TCP;
4042 flags = STREAM_TOSERVER|STREAM_START|STREAM_EOF;
4046 printf(
"toserver chunk returned %" PRId32
", expected"
4052 if (htp_state == NULL) {
4053 printf(
"no http state: ");
4057 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4082 static int HTPParserTest10(
void)
4086 uint8_t httpbuf1[] =
"GET / HTTP/1.0\r\nHost:www.google.com\r\n\r\n";
4087 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
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 for (u = 0; u < httplen1; u++) {
4109 flags = STREAM_TOSERVER|STREAM_START;
4110 else if (u == (httplen1 - 1))
4111 flags = STREAM_TOSERVER|STREAM_EOF;
4113 flags = STREAM_TOSERVER;
4117 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
4124 if (htp_state == NULL) {
4125 printf(
"no http state: ");
4129 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4130 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
4135 char *name = bstr_util_strdup_to_c(h->name);
4140 if (strcmp(name,
"Host") != 0) {
4141 printf(
"header name not \"Host\", instead \"%s\": ", name);
4147 char *value = bstr_util_strdup_to_c(h->value);
4148 if (value == NULL) {
4152 if (strcmp(value,
"www.google.com") != 0) {
4153 printf(
"header value not \"www.google.com\", instead \"%s\": ", value);
4170 static int HTPParserTest11(
void)
4174 uint8_t httpbuf1[] =
"GET /%2500 HTTP/1.0\r\n\r\n";
4175 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4181 memset(&ssn, 0,
sizeof(ssn));
4183 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
4187 f->
proto = IPPROTO_TCP;
4193 for (u = 0; u < httplen1; u++) {
4197 flags = STREAM_TOSERVER|STREAM_START;
4198 else if (u == (httplen1 - 1))
4199 flags = STREAM_TOSERVER|STREAM_EOF;
4201 flags = STREAM_TOSERVER;
4205 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
4212 if (htp_state == NULL) {
4213 printf(
"no http state: ");
4217 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4223 printf(
"normalized uri len should be 2, is %"PRIuMAX,
4233 printf(
"normalized uri \"");
4251 static int HTPParserTest12(
void)
4255 uint8_t httpbuf1[] =
"GET /?a=%2500 HTTP/1.0\r\n\r\n";
4256 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4262 memset(&ssn, 0,
sizeof(ssn));
4264 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
4268 f->
proto = IPPROTO_TCP;
4274 for (u = 0; u < httplen1; u++) {
4278 flags = STREAM_TOSERVER|STREAM_START;
4279 else if (u == (httplen1 - 1))
4280 flags = STREAM_TOSERVER|STREAM_EOF;
4282 flags = STREAM_TOSERVER;
4286 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
4293 if (htp_state == NULL) {
4294 printf(
"no http state: ");
4298 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4304 printf(
"normalized uri len should be 5, is %"PRIuMAX,
4317 printf(
"normalized uri \"");
4335 static int HTPParserTest13(
void)
4339 uint8_t httpbuf1[] =
"GET / HTTP/1.0\r\nHost:www.google.com\rName: Value\r\n\r\n";
4340 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4346 memset(&ssn, 0,
sizeof(ssn));
4348 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
4352 f->
proto = IPPROTO_TCP;
4358 for (u = 0; u < httplen1; u++) {
4362 flags = STREAM_TOSERVER|STREAM_START;
4363 else if (u == (httplen1 - 1))
4364 flags = STREAM_TOSERVER|STREAM_EOF;
4366 flags = STREAM_TOSERVER;
4370 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
4377 if (htp_state == NULL) {
4378 printf(
"no http state: ");
4382 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4383 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
4388 char *name = bstr_util_strdup_to_c(h->name);
4393 if (strcmp(name,
"Host") != 0) {
4394 printf(
"header name not \"Host\", instead \"%s\": ", name);
4400 char *value = bstr_util_strdup_to_c(h->value);
4401 if (value == NULL) {
4405 if (strcmp(value,
"www.google.com\rName: Value") != 0) {
4406 printf(
"header value not \"www.google.com\", instead \"");
4424 static int HTPParserConfigTest01(
void)
4438 address: [192.168.1.0/24, 127.0.0.0/8, \"::1\"]\n\
4439 personality: Tomcat_6_0\n\
4444 - 192.168.10.0/24\n\
4445 personality: IIS_7_0\n\
4454 outputs =
ConfGetNode(
"libhtp.default-config.personality");
4455 if (outputs == NULL) {
4460 if (outputs == NULL) {
4468 if (strcmp(node->
name,
"0") != 0) {
4475 if (strcmp(node->
name,
"apache-tomcat") != 0) {
4483 if (node2 == NULL) {
4486 if (strcmp(node2->
val,
"Tomcat_6_0") != 0) {
4501 if (strcmp(n->
name,
"0") != 0) {
4504 if (strcmp(n->
val,
"192.168.1.0/24") != 0) {
4509 if (strcmp(n->
name,
"1") != 0) {
4512 if (strcmp(n->
val,
"127.0.0.0/8") != 0) {
4517 if (strcmp(n->
name,
"2") != 0) {
4520 if (strcmp(n->
val,
"::1") != 0) {
4531 if (outputs == NULL) {
4540 if (strcmp(node->
name,
"1") != 0) {
4547 if (strcmp(node->
name,
"iis7") != 0) {
4552 if (node2 == NULL) {
4555 if (strcmp(node2->
val,
"IIS_7_0") != 0) {
4572 if (strcmp(n->
name,
"0") != 0) {
4575 if (strcmp(n->
val,
"192.168.0.0/24") != 0) {
4580 if (strcmp(n->
name,
"1") != 0) {
4583 if (strcmp(n->
val,
"192.168.10.0/24") != 0) {
4603 static int HTPParserConfigTest02(
void)
4617 address: [192.168.1.0/24, 127.0.0.0/8, \"::1\"]\n\
4618 personality: Tomcat_6_0\n\
4623 - 192.168.10.0/24\n\
4624 personality: IIS_7_0\n\
4635 if (cfglist.
cfg == NULL) {
4636 printf(
"No default config created.\n");
4640 if (cfgtree == NULL) {
4641 printf(
"No config tree created.\n");
4645 htp_cfg_t *htp = cfglist.
cfg;
4648 void *user_data = NULL;
4650 addr =
"192.168.10.42";
4651 if (inet_pton(AF_INET, addr, buf) == 1) {
4653 if (user_data != NULL) {
4655 htp = htp_cfg_rec->
cfg;
4659 printf(
"Could not get config for: %s\n", addr);
4664 printf(
"Failed to parse address: %s\n", addr);
4670 if (inet_pton(AF_INET6, addr, buf) == 1) {
4672 if (user_data != NULL) {
4674 htp = htp_cfg_rec->
cfg;
4678 printf(
"Could not get config for: %s\n", addr);
4683 printf(
"Failed to parse address: %s\n", addr);
4699 static int HTPParserConfigTest03(
void)
4703 uint8_t httpbuf1[] =
"POST / HTTP/1.0\r\nUser-Agent: Victor/1.0\r\n\r\nPost"
4705 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4722 address: [192.168.1.0/24, 127.0.0.0/8, \"::1\"]\n\
4723 personality: Tomcat_6_0\n\
4728 - 192.168.10.0/24\n\
4729 personality: IIS_7_0\n\
4740 const char *addr =
"192.168.10.42";
4742 memset(&ssn, 0,
sizeof(ssn));
4748 f->
proto = IPPROTO_TCP;
4751 htp_cfg_t *htp = cfglist.
cfg;
4753 void *user_data = NULL;
4755 if (user_data != NULL) {
4757 htp = htp_cfg_rec->
cfg;
4761 printf(
"Could not get config for: %s\n", addr);
4768 for (u = 0; u < httplen1; u++) {
4771 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
4772 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
4773 else flags = STREAM_TOSERVER;
4777 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
4785 if (htp_state == NULL) {
4786 printf(
"no http state: ");
4791 if (HTPStateGetTxCnt(htp_state) != 2) {
4792 printf(
"HTPStateGetTxCnt(htp_state) failure\n");
4796 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4799 if (tx->cfg != htp) {
4800 printf(
"wrong HTP config (%p instead of %p - default=%p): ",
4801 tx->cfg, htp, cfglist.
cfg);
4804 tx = HTPStateGetTx(htp_state, 1);
4807 if (tx->cfg != htp) {
4808 printf(
"wrong HTP config (%p instead of %p - default=%p): ",
4809 tx->cfg, htp, cfglist.
cfg);
4828 static int HTPParserConfigTest04(
void)
4839 path-control-char-handling: status_400\n\
4840 path-convert-utf8: yes\n\
4841 path-invalid-encoding-handling: remove_percent\n\
4846 personality: Tomcat_6_0\n\
4847 path-invalid-utf8-handling: none\n\
4848 path-nul-encoded-handling: status_404\n\
4849 path-nul-raw-handling: status_400\n\
4852 personality: IIS_7_0\n\
4853 path-replacement-char: o\n\
4854 path-unicode-mapping: status_400\n\
4866 if (cfg_rec->
cfg->path_control_char_handling != STATUS_400 ||
4867 cfg_rec->
cfg->path_convert_utf8 != 1 ||
4868 cfg_rec->
cfg->path_invalid_encoding_handling != URL_DECODER_REMOVE_PERCENT) {
4869 printf(
"failed 1\n");
4873 cfg_rec = cfg_rec->
next;
4874 if (cfg_rec->
cfg->bestfit_replacement_char !=
'o' ||
4875 cfg_rec->
cfg->path_unicode_mapping != STATUS_400) {
4876 printf(
"failed 2\n");
4880 cfg_rec = cfg_rec->
next;
4881 if (cfg_rec->
cfg->path_invalid_utf8_handling != NONE ||
4882 cfg_rec->
cfg->path_nul_encoded_handling != STATUS_404 ||
4883 cfg_rec->
cfg->path_nul_raw_handling != STATUS_400) {
4884 printf(
"failed 3\n");
4906 static int HTPParserDecodingTest01(
void)
4908 uint8_t httpbuf1[] =
4909 "GET /abc%2fdef HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
4910 "GET /abc/def?ghi%2fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
4911 "GET /abc/def?ghi%252fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
4912 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4923 personality: Apache_2\n\
4931 const char *addr =
"4.3.2.1";
4932 memset(&ssn, 0,
sizeof(ssn));
4937 f->
proto = IPPROTO_TCP;
4942 for (uint32_t u = 0; u < httplen1; u++) {
4944 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
4945 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
4946 else flags = STREAM_TOSERVER;
4955 uint8_t ref1[] =
"/abc%2fdef";
4956 size_t reflen =
sizeof(ref1) - 1;
4958 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4968 uint8_t ref2[] =
"/abc/def?ghi/jkl";
4969 reflen =
sizeof(ref2) - 1;
4971 tx = HTPStateGetTx(htp_state, 1);
4981 uint8_t ref3[] =
"/abc/def?ghi%2fjkl";
4982 reflen =
sizeof(ref3) - 1;
4983 tx = HTPStateGetTx(htp_state, 2);
5004 static int HTPParserDecodingTest01a(
void)
5006 uint8_t httpbuf1[] =
"GET /abc%2fdef HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
5007 "GET /abc/def?ghi%2fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
5008 "GET /abc/def?ghi%252fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5009 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5020 personality: Apache_2\n\
5028 const char *addr =
"4.3.2.1";
5029 memset(&ssn, 0,
sizeof(ssn));
5034 f->
proto = IPPROTO_TCP;
5040 (STREAM_TOSERVER | STREAM_START | STREAM_EOF), httpbuf1, httplen1);
5046 uint8_t ref1[] =
"/abc%2fdef";
5047 size_t reflen =
sizeof(ref1) - 1;
5049 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5059 uint8_t ref2[] =
"/abc/def?ghi/jkl";
5060 reflen =
sizeof(ref2) - 1;
5062 tx = HTPStateGetTx(htp_state, 1);
5072 uint8_t ref3[] =
"/abc/def?ghi%2fjkl";
5073 reflen =
sizeof(ref3) - 1;
5074 tx = HTPStateGetTx(htp_state, 2);
5101 static int HTPParserDecodingTest02(
void)
5105 uint8_t httpbuf1[] =
5106 "GET /abc%2fdef HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
5107 "GET /abc/def?ghi%2fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
5108 "GET /abc/def?ghi%252fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5109 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5122 double-decode-path: no\n\
5123 double-decode-query: no\n\
5131 const char *addr =
"4.3.2.1";
5132 memset(&ssn, 0,
sizeof(ssn));
5138 f->
proto = IPPROTO_TCP;
5144 for (u = 0; u < httplen1; u++) {
5147 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
5148 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
5149 else flags = STREAM_TOSERVER;
5153 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5160 if (htp_state == NULL) {
5161 printf(
"no http state: ");
5165 uint8_t ref1[] =
"/abc/def";
5166 size_t reflen =
sizeof(ref1) - 1;
5168 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5174 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5183 printf(
"normalized uri \"");
5192 uint8_t ref2[] =
"/abc/def?ghi/jkl";
5193 reflen =
sizeof(ref2) - 1;
5195 tx = HTPStateGetTx(htp_state, 1);
5201 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5210 printf(
"normalized uri \"");
5219 uint8_t ref3[] =
"/abc/def?ghi%2fjkl";
5220 reflen =
sizeof(ref3) - 1;
5221 tx = HTPStateGetTx(htp_state, 2);
5227 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX
" (3): ",
5236 printf(
"normalized uri \"");
5265 static int HTPParserDecodingTest03(
void)
5269 uint8_t httpbuf1[] =
5270 "GET /abc%252fdef HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
5271 "GET /abc/def?ghi%252fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5272 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5285 double-decode-path: yes\n\
5286 double-decode-query: yes\n\
5294 const char *addr =
"4.3.2.1";
5295 memset(&ssn, 0,
sizeof(ssn));
5301 f->
proto = IPPROTO_TCP;
5307 for (u = 0; u < httplen1; u++) {
5310 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
5311 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
5312 else flags = STREAM_TOSERVER;
5316 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5323 if (htp_state == NULL) {
5324 printf(
"no http state: ");
5328 uint8_t ref1[] =
"/abc/def";
5329 size_t reflen =
sizeof(ref1) - 1;
5331 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5337 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5346 printf(
"normalized uri \"");
5355 uint8_t ref2[] =
"/abc/def?ghi/jkl";
5356 reflen =
sizeof(ref2) - 1;
5358 tx = HTPStateGetTx(htp_state, 1);
5364 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5373 printf(
"normalized uri \"");
5399 static int HTPParserDecodingTest04(
void)
5403 uint8_t httpbuf1[] =
5404 "GET /abc/def?a=http://www.abc.com/ HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5405 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5418 double-decode-path: yes\n\
5419 double-decode-query: yes\n\
5427 const char *addr =
"4.3.2.1";
5428 memset(&ssn, 0,
sizeof(ssn));
5434 f->
proto = IPPROTO_TCP;
5440 for (u = 0; u < httplen1; u++) {
5443 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
5444 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
5445 else flags = STREAM_TOSERVER;
5449 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5456 if (htp_state == NULL) {
5457 printf(
"no http state: ");
5461 uint8_t ref1[] =
"/abc/def?a=http://www.abc.com/";
5462 size_t reflen =
sizeof(ref1) - 1;
5464 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5470 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5479 printf(
"normalized uri \"");
5505 static int HTPParserDecodingTest05(
void)
5509 uint8_t httpbuf1[] =
5510 "GET /index?id=\\\"<script>alert(document.cookie)</script> HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5511 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5524 double-decode-path: yes\n\
5525 double-decode-query: yes\n\
5533 const char *addr =
"4.3.2.1";
5534 memset(&ssn, 0,
sizeof(ssn));
5540 f->
proto = IPPROTO_TCP;
5546 for (u = 0; u < httplen1; u++) {
5549 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
5550 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
5551 else flags = STREAM_TOSERVER;
5555 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5562 if (htp_state == NULL) {
5563 printf(
"no http state: ");
5567 uint8_t ref1[] =
"/index?id=\\\"<script>alert(document.cookie)</script>";
5568 size_t reflen =
sizeof(ref1) - 1;
5570 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5576 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5585 printf(
"normalized uri \"");
5611 static int HTPParserDecodingTest06(
void)
5615 uint8_t httpbuf1[] =
5616 "GET /put.php?ip=1.2.3.4&port=+6000 HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5617 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5630 double-decode-path: yes\n\
5631 double-decode-query: yes\n\
5639 const char *addr =
"4.3.2.1";
5640 memset(&ssn, 0,
sizeof(ssn));
5646 f->
proto = IPPROTO_TCP;
5652 for (u = 0; u < httplen1; u++) {
5655 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
5656 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
5657 else flags = STREAM_TOSERVER;
5661 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5668 if (htp_state == NULL) {
5669 printf(
"no http state: ");
5673 uint8_t ref1[] =
"/put.php?ip=1.2.3.4&port=+6000";
5674 size_t reflen =
sizeof(ref1) - 1;
5676 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5682 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5691 printf(
"normalized uri \"");
5717 static int HTPParserDecodingTest07(
void)
5721 uint8_t httpbuf1[] =
5722 "GET /put.php?ip=1.2.3.4&port=+6000 HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5723 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5736 double-decode-path: yes\n\
5737 double-decode-query: yes\n\
5738 query-plusspace-decode: yes\n\
5746 const char *addr =
"4.3.2.1";
5747 memset(&ssn, 0,
sizeof(ssn));
5753 f->
proto = IPPROTO_TCP;
5759 for (u = 0; u < httplen1; u++) {
5762 if (u == 0)
flags = STREAM_TOSERVER|STREAM_START;
5763 else if (u == (httplen1 - 1))
flags = STREAM_TOSERVER|STREAM_EOF;
5764 else flags = STREAM_TOSERVER;
5768 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5775 if (htp_state == NULL) {
5776 printf(
"no http state: ");
5780 uint8_t ref1[] =
"/put.php?ip=1.2.3.4&port= 6000";
5781 size_t reflen =
sizeof(ref1) - 1;
5783 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5789 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5798 printf(
"normalized uri \"");
5824 static int HTPParserDecodingTest08(
void)
5828 uint8_t httpbuf1[] =
5829 "GET http://suricata-ids.org/blah/ HTTP/1.1\r\nHost: suricata-ids.org\r\n\r\n";
5830 uint32_t httplen1 =
sizeof(httpbuf1) - 1;