92 #define HTP_MAX_MESSAGES 512
98 static uint64_t htp_state_memuse = 0;
99 static uint64_t htp_state_memcnt = 0;
105 {
"GZIP_DECOMPRESSION_FAILED",
107 {
"REQUEST_FIELD_MISSING_COLON",
109 {
"RESPONSE_FIELD_MISSING_COLON",
111 {
"INVALID_REQUEST_CHUNK_LEN",
113 {
"INVALID_RESPONSE_CHUNK_LEN",
115 {
"INVALID_TRANSFER_ENCODING_VALUE_IN_REQUEST",
117 {
"INVALID_TRANSFER_ENCODING_VALUE_IN_RESPONSE",
119 {
"INVALID_CONTENT_LENGTH_FIELD_IN_REQUEST",
121 {
"INVALID_CONTENT_LENGTH_FIELD_IN_RESPONSE",
123 {
"DUPLICATE_CONTENT_LENGTH_FIELD_IN_REQUEST",
125 {
"DUPLICATE_CONTENT_LENGTH_FIELD_IN_RESPONSE",
127 {
"100_CONTINUE_ALREADY_SEEN",
129 {
"UNABLE_TO_MATCH_RESPONSE_TO_REQUEST",
131 {
"INVALID_SERVER_PORT_IN_REQUEST",
133 {
"INVALID_AUTHORITY_PORT",
135 {
"REQUEST_HEADER_INVALID",
137 {
"RESPONSE_HEADER_INVALID",
139 {
"MISSING_HOST_HEADER",
141 {
"HOST_HEADER_AMBIGUOUS",
143 {
"INVALID_REQUEST_FIELD_FOLDING",
145 {
"INVALID_RESPONSE_FIELD_FOLDING",
147 {
"REQUEST_FIELD_TOO_LONG",
149 {
"RESPONSE_FIELD_TOO_LONG",
151 {
"REQUEST_LINE_INVALID",
153 {
"REQUEST_BODY_UNEXPECTED",
155 {
"REQUEST_SERVER_PORT_TCP_PORT_MISMATCH",
157 {
"REQUEST_URI_HOST_INVALID",
159 {
"REQUEST_HEADER_HOST_INVALID",
161 {
"REQUEST_AUTH_UNRECOGNIZED",
163 {
"REQUEST_HEADER_REPETITION",
165 {
"RESPONSE_HEADER_REPETITION",
167 {
"DOUBLE_ENCODED_URI",
169 {
"URI_DELIM_NON_COMPLIANT",
171 {
"METHOD_DELIM_NON_COMPLIANT",
173 {
"REQUEST_LINE_LEADING_WHITESPACE",
175 {
"TOO_MANY_ENCODING_LAYERS",
177 {
"ABNORMAL_CE_HEADER",
179 {
"RESPONSE_MULTIPART_BYTERANGES",
181 {
"RESPONSE_ABNORMAL_TRANSFER_ENCODING",
183 {
"RESPONSE_CHUNKED_OLD_PROTO",
185 {
"RESPONSE_INVALID_PROTOCOL",
187 {
"RESPONSE_INVALID_STATUS",
189 {
"REQUEST_LINE_INCOMPLETE",
192 {
"LZMA_MEMLIMIT_REACHED",
194 {
"COMPRESSION_BOMB",
198 {
"MULTIPART_GENERIC_ERROR",
200 {
"MULTIPART_NO_FILEDATA",
202 {
"MULTIPART_INVALID_HEADER",
205 {
"TOO_MANY_WARNINGS",
211 static void *HTPStateGetTx(
void *alstate, uint64_t tx_id);
212 static int HTPStateGetAlstateProgress(
void *tx, uint8_t direction);
213 static uint64_t HTPStateGetTxCnt(
void *alstate);
215 static void HTPParserRegisterTests(
void);
218 static inline uint64_t HtpGetActiveRequestTxID(
HtpState *s)
220 uint64_t
id = HTPStateGetTxCnt(s);
225 static inline uint64_t HtpGetActiveResponseTxID(
HtpState *s)
238 static const char *HTPLookupPersonalityString(
int p)
240 #define CASE_HTP_PERSONALITY_STRING(p) \
241 case HTP_SERVER_ ## p: return #p
244 CASE_HTP_PERSONALITY_STRING(MINIMAL);
245 CASE_HTP_PERSONALITY_STRING(GENERIC);
246 CASE_HTP_PERSONALITY_STRING(IDS);
247 CASE_HTP_PERSONALITY_STRING(IIS_4_0);
248 CASE_HTP_PERSONALITY_STRING(IIS_5_0);
249 CASE_HTP_PERSONALITY_STRING(IIS_5_1);
250 CASE_HTP_PERSONALITY_STRING(IIS_6_0);
251 CASE_HTP_PERSONALITY_STRING(IIS_7_0);
252 CASE_HTP_PERSONALITY_STRING(IIS_7_5);
253 CASE_HTP_PERSONALITY_STRING(APACHE_2);
267 static int HTPLookupPersonality(
const char *
str)
269 #define IF_HTP_PERSONALITY_NUM(p) \
270 if (strcasecmp(#p, str) == 0) return HTP_SERVER_ ## p
282 if (strcasecmp(
"TOMCAT_6_0",
str) == 0) {
284 "longer supported by libhtp.",
str);
286 }
else if ((strcasecmp(
"APACHE",
str) == 0) ||
287 (strcasecmp(
"APACHE_2_2",
str) == 0))
290 "longer supported by libhtp, failing back to "
291 "Apache2 personality.",
str);
292 return HTP_SERVER_APACHE_2;
299 const uint8_t dir,
const uint8_t e)
310 HtpGetActiveRequestTxID(s) : HtpGetActiveResponseTxID(s);
312 htp_tx_t *tx = HTPStateGetTx(s, tx_id);
313 if (tx == NULL && tx_id > 0)
314 tx = HTPStateGetTx(s, tx_id - 1);
342 static void *HTPStateAlloc(
void *orig_state,
AppProto proto_orig)
356 htp_state_memuse +=
sizeof(
HtpState);
357 SCLogDebug(
"htp memory %"PRIu64
" (%"PRIu64
")", htp_state_memuse, htp_state_memcnt);
397 if (s->
connp != NULL) {
401 uint64_t total_txs = HTPStateGetTxCnt(state);
403 if (s->
conn != NULL) {
404 for (tx_id = 0; tx_id < total_txs; tx_id++) {
405 htp_tx_t *tx = HTPStateGetTx(s, tx_id);
408 HtpTxUserDataFree(s, htud);
409 htp_tx_set_user_data(tx, NULL);
413 htp_connp_destroy_all(s->
connp);
423 htp_state_memuse -=
sizeof(
HtpState);
424 SCLogDebug(
"htp memory %"PRIu64
" (%"PRIu64
")", htp_state_memuse, htp_state_memcnt);
437 static void HTPStateTransactionFree(
void *state, uint64_t
id)
445 htp_tx_t *tx = HTPStateGetTx(s,
id);
449 HtpTxUserDataFree(s, htud);
450 htp_tx_set_user_data(tx, NULL);
457 tx->request_progress == HTP_REQUEST_COMPLETE &&
458 tx->response_progress == HTP_RESPONSE_COMPLETE)))
460 tx->request_progress = HTP_REQUEST_COMPLETE;
461 tx->response_progress = HTP_RESPONSE_COMPLETE;
499 static void AppLayerHtpNeedMultipartHeader(
void)
517 AppLayerHtpNeedMultipartHeader();
525 static void AppLayerHtpSetStreamDepthFlag(
void *tx, uint8_t
flags)
552 static uint32_t AppLayerHtpComputeChunkLength(uint64_t content_len_so_far, uint32_t body_limit,
553 uint32_t stream_depth, uint8_t
flags, uint32_t data_len)
555 uint32_t chunk_len = 0;
557 (content_len_so_far < (uint64_t)body_limit) &&
558 (content_len_so_far + (uint64_t)data_len) > body_limit)
560 chunk_len = body_limit - content_len_so_far;
562 (content_len_so_far < (uint64_t)stream_depth) &&
563 (content_len_so_far + (uint64_t)data_len) > stream_depth)
565 chunk_len = stream_depth - content_len_so_far;
568 return (chunk_len == 0 ? data_len : chunk_len);
632 #define HTP_ERROR_MAX (sizeof(htp_errors) / sizeof(htp_errors[0]))
633 #define HTP_WARNING_MAX (sizeof(htp_warnings) / sizeof(htp_warnings[0]))
644 static int HTPHandleWarningGetId(
const char *
msg)
668 static int HTPHandleErrorGetId(
const char *
msg)
692 static void HTPHandleError(
HtpState *s,
const uint8_t dir)
694 if (s == NULL || s->
conn == NULL ||
695 s->
conn->messages == NULL) {
699 size_t size = htp_list_size(s->
conn->messages);
714 htp_log_t *log = htp_list_get(s->
conn->messages,
msg);
719 htp_tx_t *tx = log->tx;
725 int id = HTPHandleErrorGetId(log->msg);
727 id = HTPHandleWarningGetId(log->msg);
733 HTPSetEvent(s, htud, dir,
id);
740 static inline void HTPErrorCheckTxRequestFlags(
HtpState *s, htp_tx_t *tx)
743 BUG_ON(s == NULL || tx == NULL);
745 if (tx->flags & ( HTP_REQUEST_INVALID_T_E|HTP_REQUEST_INVALID_C_L|
746 HTP_HOST_MISSING|HTP_HOST_AMBIGUOUS|HTP_HOSTU_INVALID|
753 if (tx->flags & HTP_REQUEST_INVALID_T_E)
756 if (tx->flags & HTP_REQUEST_INVALID_C_L)
759 if (tx->flags & HTP_HOST_MISSING)
762 if (tx->flags & HTP_HOST_AMBIGUOUS)
765 if (tx->flags & HTP_HOSTU_INVALID)
768 if (tx->flags & HTP_HOSTH_INVALID)
772 if (tx->request_auth_type == HTP_AUTH_UNRECOGNIZED) {
779 if (tx->is_protocol_0_9 && tx->request_method_number == HTP_M_UNKNOWN &&
780 (tx->request_protocol_number == HTP_PROTOCOL_INVALID ||
781 tx->request_protocol_number == HTP_PROTOCOL_UNKNOWN)) {
796 htp_cfg_t *htp = cfglist.
cfg;
797 void *user_data = NULL;
812 if (user_data != NULL) {
813 htp_cfg_rec = user_data;
814 htp = htp_cfg_rec->
cfg;
817 SCLogDebug(
"Using default HTP config: %p", htp);
821 #ifdef DEBUG_VALIDATION
828 hstate->
connp = htp_connp_create(htp);
829 if (hstate->
connp == NULL) {
833 hstate->
conn = htp_connp_get_connection(hstate->
connp);
835 htp_connp_set_user_data(hstate->
connp, (
void *)hstate);
836 hstate->
cfg = htp_cfg_rec;
864 static AppLayerResult HTPHandleRequestData(
Flow *f,
void *htp_state,
866 const uint8_t *input, uint32_t input_len,
867 void *local_data,
const uint8_t
flags)
877 if (NULL == hstate->
conn) {
878 if (Setup(f, hstate) != 0) {
887 const int r = htp_connp_req_data(hstate->
connp, &
ts, input, input_len);
889 case HTP_STREAM_ERROR:
902 htp_connp_req_close(hstate->
connp, &
ts);
904 SCLogDebug(
"stream eof encountered, closing htp handle for ts");
928 static AppLayerResult HTPHandleResponseData(
Flow *f,
void *htp_state,
930 const uint8_t *input, uint32_t input_len,
931 void *local_data,
const uint8_t
flags)
941 if (NULL == hstate->
conn) {
942 if (Setup(f, hstate) != 0) {
952 const int r = htp_connp_res_data(hstate->
connp, &
ts, input, input_len);
954 case HTP_STREAM_ERROR:
957 case HTP_STREAM_TUNNEL:
958 tx = htp_connp_get_out_tx(hstate->
connp);
959 if (tx != NULL && tx->response_status_number == 101) {
961 (htp_header_t *)htp_table_get_c(tx->response_headers,
"Upgrade");
963 if (bstr_cmp_c(h->value,
"h2c") == 0) {
965 if (tx->request_port_number != -1) {
966 dp = (uint16_t)tx->request_port_number;
968 consumed = htp_connp_res_data_consumed(hstate->
connp);
972 if (consumed > 0 && consumed < input_len) {
991 htp_connp_close(hstate->
connp, &
ts);
1006 static int HTTPParseContentDispositionHeader(uint8_t *name,
size_t name_len,
1007 uint8_t *data,
size_t len, uint8_t **retptr,
size_t *retlen)
1010 printf(
"DATA START: \n");
1012 printf(
"DATA END: \n");
1017 for (x = 0; x <
len; x++) {
1018 if (!(isspace(data[x])))
1025 uint8_t *line = data+x;
1026 size_t line_len =
len-x;
1029 printf(
"LINE START: \n");
1031 printf(
"LINE END: \n");
1033 for (x = 0 ; x < line_len; x++) {
1035 if (line[x - 1] !=
'\\' && line[x] ==
'\"') {
1039 if (((line[x - 1] !=
'\\' && line[x] ==
';') || ((x + 1) == line_len)) && (quote == 0 || quote % 2 == 0)) {
1040 uint8_t *token = line +
offset;
1041 size_t token_len = x -
offset;
1043 if ((x + 1) == line_len) {
1054 printf(
"TOKEN START: \n");
1056 printf(
"TOKEN END: \n");
1058 if (token_len > name_len) {
1059 if (name == NULL || SCMemcmpLowercase(name, token, name_len) == 0) {
1060 uint8_t *value = token + name_len;
1061 size_t value_len = token_len - name_len;
1063 if (value[0] ==
'\"') {
1067 if (value[value_len-1] ==
'\"') {
1071 printf(
"VALUE START: \n");
1073 printf(
"VALUE END: \n");
1076 *retlen = value_len;
1090 static int HTTPParseContentTypeHeader(uint8_t *name,
size_t name_len,
1091 uint8_t *data,
size_t len, uint8_t **retptr,
size_t *retlen)
1095 printf(
"DATA START: \n");
1097 printf(
"DATA END: \n");
1102 for (x = 0; x <
len; x++) {
1103 if (!(isspace(data[x])))
1111 uint8_t *line = data+x;
1112 size_t line_len =
len-x;
1115 printf(
"LINE START: \n");
1117 printf(
"LINE END: \n");
1119 for (x = 0 ; x < line_len; x++) {
1121 if (line[x - 1] !=
'\\' && line[x] ==
'\"') {
1125 if (((line[x - 1] !=
'\\' && line[x] ==
';') || ((x + 1) == line_len)) && (quote == 0 || quote % 2 == 0)) {
1126 uint8_t *token = line +
offset;
1127 size_t token_len = x -
offset;
1129 if ((x + 1) == line_len) {
1140 printf(
"TOKEN START: \n");
1142 printf(
"TOKEN END: \n");
1144 if (token_len > name_len) {
1145 if (name == NULL || SCMemcmpLowercase(name, token, name_len) == 0) {
1146 uint8_t *value = token + name_len;
1147 size_t value_len = token_len - name_len;
1149 if (value[0] ==
'\"') {
1153 if (value[value_len-1] ==
'\"') {
1157 printf(
"VALUE START: \n");
1159 printf(
"VALUE END: \n");
1162 *retlen = value_len;
1186 static int HtpRequestBodySetupMultipart(htp_tx_t *tx,
HtpTxUserData *htud)
1188 htp_header_t *h = (htp_header_t *)htp_table_get_c(tx->request_headers,
1190 if (h != NULL && bstr_len(h->value) > 0) {
1191 uint8_t *boundary = NULL;
1192 size_t boundary_len = 0;
1194 int r = HTTPParseContentTypeHeader((uint8_t *)
"boundary=", 9,
1195 (uint8_t *) bstr_ptr(h->value), bstr_len(h->value),
1196 &boundary, &boundary_len);
1199 printf(
"BOUNDARY START: \n");
1201 printf(
"BOUNDARY END: \n");
1209 memcpy(htud->
boundary, boundary, boundary_len);
1223 #define C_D_HDR "content-disposition:"
1224 #define C_D_HDR_LEN 20
1225 #define C_T_HDR "content-type:"
1226 #define C_T_HDR_LEN 13
1228 static void HtpRequestBodyMultipartParseHeader(
HtpState *hstate,
1230 uint8_t *header, uint32_t header_len,
1231 uint8_t **filename, uint16_t *filename_len,
1232 uint8_t **filetype, uint16_t *filetype_len)
1240 printf(
"HEADER START: \n");
1242 printf(
"HEADER END: \n");
1245 while (header_len > 0) {
1246 uint8_t *next_line =
Bs2bmSearch(header, header_len, (uint8_t *)
"\r\n", 2);
1247 uint8_t *line = header;
1250 if (next_line == NULL) {
1251 line_len = header_len;
1253 line_len = next_line - header;
1255 uint8_t *sc = (uint8_t *)memchr(line,
':', line_len);
1261 }
else if (line_len > 0 && sc == &line[line_len - 1]) {
1266 printf(
"LINE START: \n");
1268 printf(
"LINE END: \n");
1276 (void)HTTPParseContentDispositionHeader((uint8_t *)
"filename=", 9,
1277 value, value_len, &fn, &fn_len);
1284 (void)HTTPParseContentTypeHeader(NULL, 0,
1285 value, value_len, &ft, &ft_len);
1289 if (next_line == NULL) {
1293 header_len -= ((next_line + 2) - header);
1294 header = next_line + 2;
1297 if (fn_len > USHRT_MAX)
1299 if (ft_len > USHRT_MAX)
1303 *filename_len = fn_len;
1305 *filetype_len = ft_len;
1316 const uint8_t **chunks_buffer, uint32_t *chunks_buffer_len)
1319 chunks_buffer, chunks_buffer_len,
1323 static void FlagDetectStateNewFile(
HtpTxUserData *tx,
int dir)
1328 SCLogDebug(
"DETECT_ENGINE_STATE_FLAG_FILE_NEW set");
1331 SCLogDebug(
"DETECT_ENGINE_STATE_FLAG_FILE_NEW set");
1340 static void HtpRequestBodySetupBoundary(
HtpTxUserData *htud,
1341 uint8_t *boundary, uint32_t boundary_len)
1343 memset(boundary,
'-', boundary_len);
1348 const uint8_t *chunks_buffer, uint32_t chunks_buffer_len)
1352 uint32_t expected_boundary_len = htud->
boundary_len + 2;
1353 uint32_t expected_boundary_end_len = htud->
boundary_len + 4;
1354 int tx_progress = 0;
1357 printf(
"CHUNK START: \n");
1359 printf(
"CHUNK END: \n");
1362 HtpRequestBodySetupBoundary(htud, boundary, htud->
boundary_len + 4);
1365 const uint8_t *header_start =
Bs2bmSearch(chunks_buffer, chunks_buffer_len,
1366 boundary, expected_boundary_len);
1368 const uint8_t *form_end = NULL;
1370 const uint8_t *header_end = NULL;
1371 if (header_start != NULL) {
1372 header_end =
Bs2bmSearch(header_start, chunks_buffer_len - (header_start - chunks_buffer),
1373 (uint8_t *)
"\r\n\r\n", 4);
1374 form_end =
Bs2bmSearch(header_start, chunks_buffer_len - (header_start - chunks_buffer),
1375 boundary, expected_boundary_end_len);
1378 SCLogDebug(
"header_start %p, header_end %p, form_end %p", header_start,
1379 header_end, form_end);
1386 if (header_start != NULL || (tx_progress > HTP_REQUEST_BODY)) {
1389 const uint8_t *filedata = chunks_buffer;
1390 uint32_t filedata_len = 0;
1393 if (header_start != NULL) {
1394 if (header_start == filedata + 2) {
1396 SCLogDebug(
"last chunk had all data, but not the boundary");
1398 }
else if (header_start > filedata + 2) {
1399 SCLogDebug(
"some data from last file before the boundary");
1401 filedata_len = header_start - filedata - 2;
1406 if (tx_progress > HTP_REQUEST_BODY) {
1407 filedata_len = chunks_buffer_len;
1411 if (filedata_len > chunks_buffer_len) {
1417 printf(
"FILEDATA (final chunk) START: \n");
1419 printf(
"FILEDATA (final chunk) END: \n");
1433 SCLogDebug(
"not yet at the end of the file");
1435 if (chunks_buffer_len > expected_boundary_end_len) {
1436 const uint8_t *filedata = chunks_buffer;
1437 uint32_t filedata_len = chunks_buffer_len - expected_boundary_len;
1439 printf(
"FILEDATA (part) START: \n");
1441 printf(
"FILEDATA (part) END: \n");
1449 }
else if (result == -2) {
1457 SCLogDebug(
"chunk too small to already process in part");
1464 while (header_start != NULL && header_end != NULL &&
1465 header_end != form_end &&
1466 header_start < (chunks_buffer + chunks_buffer_len) &&
1467 header_end < (chunks_buffer + chunks_buffer_len) &&
1468 header_start < header_end)
1470 uint8_t *filename = NULL;
1471 uint16_t filename_len = 0;
1472 uint8_t *filetype = NULL;
1473 uint16_t filetype_len = 0;
1475 uint32_t header_len = header_end - header_start;
1477 uint8_t *header = (uint8_t *)header_start;
1480 if (expected_boundary_len == header_len) {
1482 }
else if ((expected_boundary_len + 2) <= header_len) {
1483 header_len -= (expected_boundary_len + 2);
1484 header = (uint8_t *)header_start + (expected_boundary_len + 2);
1487 HtpRequestBodyMultipartParseHeader(hstate, htud, header, header_len,
1488 &filename, &filename_len, &filetype, &filetype_len);
1490 if (filename != NULL) {
1491 const uint8_t *filedata = NULL;
1492 uint32_t filedata_len = 0;
1503 if (form_end != NULL) {
1506 filedata = header_end + 4;
1507 if (form_end == filedata) {
1511 }
else if (form_end < filedata) {
1517 filedata_len = form_end - (header_end + 4 + 2);
1518 SCLogDebug(
"filedata_len %"PRIuMAX, (uintmax_t)filedata_len);
1521 uint8_t *header_next =
Bs2bmSearch(filedata, filedata_len,
1522 boundary, expected_boundary_len);
1523 if (header_next != NULL) {
1524 filedata_len -= (form_end - header_next);
1527 if (filedata_len > chunks_buffer_len) {
1532 SCLogDebug(
"filedata_len %"PRIuMAX, (uintmax_t)filedata_len);
1534 printf(
"FILEDATA START: \n");
1536 printf(
"FILEDATA END: \n");
1539 result =
HTPFileOpen(hstate, filename, filename_len,
1540 filedata, filedata_len, HtpGetActiveRequestTxID(hstate),
1544 }
else if (result == -2) {
1556 SCLogDebug(
"chunk doesn't contain form end");
1558 filedata = header_end + 4;
1559 filedata_len = chunks_buffer_len - (filedata - chunks_buffer);
1560 SCLogDebug(
"filedata_len %u (chunks_buffer_len %u)", filedata_len, chunks_buffer_len);
1562 if (filedata_len > chunks_buffer_len) {
1569 printf(
"FILEDATA START: \n");
1571 printf(
"FILEDATA END: \n");
1575 uint8_t *header_next =
Bs2bmSearch(filedata, filedata_len,
1576 boundary, expected_boundary_len);
1578 if (header_next == NULL) {
1581 uint32_t
offset = (header_end + 4) - chunks_buffer;
1585 if (filedata_len >= (expected_boundary_len + 2)) {
1586 filedata_len -= (expected_boundary_len + 2 - 1);
1587 SCLogDebug(
"opening file with partial data");
1592 result =
HTPFileOpen(hstate, filename, filename_len,
1593 filedata, filedata_len, HtpGetActiveRequestTxID(hstate),
1597 }
else if (result == -2) {
1604 }
else if (header_next - filedata > 2) {
1605 filedata_len = header_next - filedata - 2;
1608 result =
HTPFileOpen(hstate, filename, filename_len,
1609 filedata, filedata_len, HtpGetActiveRequestTxID(hstate),
1613 }
else if (result == -2) {
1628 SCLogDebug(
"header_start %p, header_end %p, form_end %p",
1629 header_start, header_end, form_end);
1632 uint32_t cursizeread = header_end - chunks_buffer;
1634 chunks_buffer_len - (cursizeread + 4),
1635 boundary, expected_boundary_len);
1636 if (header_start != NULL) {
1638 chunks_buffer_len - (cursizeread + 4),
1639 (uint8_t *)
"\r\n\r\n", 4);
1646 if (chunks_buffer_len > expected_boundary_end_len) {
1647 uint32_t move = chunks_buffer_len - expected_boundary_end_len + 1;
1650 SCLogDebug(
"form not ready, file not set, parsing non-file "
1651 "record: moved %u", move);
1664 htp_tx_t *tx, uint8_t *data, uint32_t data_len)
1671 uint8_t *filename = NULL;
1672 size_t filename_len = 0;
1675 if (tx->parsed_uri != NULL && tx->parsed_uri->path != NULL) {
1676 filename = (uint8_t *)bstr_ptr(tx->parsed_uri->path);
1677 filename_len = bstr_len(tx->parsed_uri->path);
1680 if (filename != NULL) {
1681 result =
HTPFileOpen(hstate, filename, (uint32_t)filename_len, data, data_len,
1685 }
else if (result == -2) {
1702 }
else if (result == -2) {
1715 htp_tx_t *tx, uint8_t *data, uint32_t data_len)
1726 (tx->response_line != NULL || tx->is_protocol_0_9))
1730 uint8_t *filename = NULL;
1731 size_t filename_len = 0;
1734 htp_header_t *h = (htp_header_t *)htp_table_get_c(tx->response_headers,
1735 "Content-Disposition");
1736 if (h != NULL && bstr_len(h->value) > 0) {
1738 (void)HTTPParseContentDispositionHeader((uint8_t *)
"filename=", 9,
1739 (uint8_t *) bstr_ptr(h->value), bstr_len(h->value), &filename, &filename_len);
1743 if (filename == NULL) {
1745 if (tx->parsed_uri != NULL && tx->parsed_uri->path != NULL) {
1746 filename = (uint8_t *)bstr_ptr(tx->parsed_uri->path);
1747 filename_len = bstr_len(tx->parsed_uri->path);
1751 if (filename != NULL) {
1752 result =
HTPFileOpen(hstate, filename, (uint32_t)filename_len,
1757 }
else if (result == -2) {
1765 htp_header_t *h_content_range = htp_table_get_c(tx->response_headers,
"content-range");
1766 if (h_content_range != NULL) {
1771 else if (tx->response_line != NULL || tx->is_protocol_0_9)
1780 }
else if (result == -2) {
1798 static int HTPCallbackRequestBodyData(htp_tx_data_t *d)
1809 printf(
"HTPBODY START: \n");
1811 printf(
"HTPBODY END: \n");
1814 HtpState *hstate = htp_connp_get_user_data(d->tx->connp);
1815 if (hstate == NULL) {
1819 SCLogDebug(
"New request body data available at %p -> %p -> %p, bodylen "
1820 "%"PRIu32
"", hstate, d, d->data, (uint32_t)d->len);
1823 if (tx_ud == NULL) {
1829 if (d->tx->request_method_number == HTP_M_POST) {
1831 int r = HtpRequestBodySetupMultipart(d->tx, tx_ud);
1834 }
else if (r == 0) {
1838 }
else if (d->tx->request_method_number == HTP_M_PUT) {
1861 const uint8_t *chunks_buffer = NULL;
1862 uint32_t chunks_buffer_len = 0;
1870 HtpRequestBodyReassemble(tx_ud, &chunks_buffer, &chunks_buffer_len);
1871 if (chunks_buffer == NULL) {
1875 printf(
"REASSCHUNK START: \n");
1877 printf(
"REASSCHUNK END: \n");
1880 HtpRequestBodyHandleMultipart(hstate, tx_ud, d->tx, chunks_buffer, chunks_buffer_len);
1884 HtpRequestBodyHandlePOSTorPUT(hstate, tx_ud, d->tx, (uint8_t *)d->data,
len);
1889 SCLogDebug(
"closing file that was being stored");
1896 if (hstate->
conn != NULL) {
1897 SCLogDebug(
"checking body size %"PRIu64
" against inspect limit %u (cur %"PRIu64
", last %"PRIu64
")",
1930 static int HTPCallbackResponseBodyData(htp_tx_data_t *d)
1940 HtpState *hstate = htp_connp_get_user_data(d->tx->connp);
1941 if (hstate == NULL) {
1945 SCLogDebug(
"New response body data available at %p -> %p -> %p, bodylen "
1946 "%"PRIu32
"", hstate, d, d->data, (uint32_t)d->len);
1949 if (tx_ud == NULL) {
1974 HtpResponseBodyHandle(hstate, tx_ud, d->tx, (uint8_t *)d->data,
len);
1977 SCLogDebug(
"closing file that was being stored");
1983 if (hstate->
conn != NULL) {
1984 SCLogDebug(
"checking body size %"PRIu64
" against inspect limit %u (cur %"PRIu64
", last %"PRIu64
")",
2019 SCLogDebug(
"http_state_memcnt %"PRIu64
", http_state_memuse %"PRIu64
"",
2020 htp_state_memcnt, htp_state_memuse);
2040 htp_config_destroy(cfglist.
cfg);
2041 while (nextrec != NULL) {
2043 nextrec = nextrec->
next;
2045 htp_config_destroy(htprec->
cfg);
2051 static int HTPCallbackRequestHasTrailer(htp_tx_t *tx)
2060 static int HTPCallbackResponseHasTrailer(htp_tx_t *tx)
2073 static int HTPCallbackRequestStart(htp_tx_t *tx)
2075 HtpState *hstate = htp_connp_get_user_data(tx->connp);
2076 if (hstate == NULL) {
2085 if (tx_ud == NULL) {
2090 htp_tx_set_user_data(tx, tx_ud);
2099 static int HTPCallbackResponseStart(htp_tx_t *tx)
2101 HtpState *hstate = htp_connp_get_user_data(tx->connp);
2102 if (hstate == NULL) {
2111 if (tx_ud == NULL) {
2116 htp_tx_set_user_data(tx, tx_ud);
2128 static int HTPCallbackRequest(htp_tx_t *tx)
2136 HtpState *hstate = htp_connp_get_user_data(tx->connp);
2137 if (hstate == NULL) {
2141 SCLogDebug(
"transaction_cnt %"PRIu64
", list_size %"PRIu64,
2146 HTPErrorCheckTxRequestFlags(hstate, tx);
2151 SCLogDebug(
"closing file that was being stored");
2155 (uint32_t)hstate->
conn->in_data_counter);
2172 static int HTPCallbackResponse(htp_tx_t *tx)
2176 HtpState *hstate = htp_connp_get_user_data(tx->connp);
2177 if (hstate == NULL) {
2187 SCLogDebug(
"closing file that was being stored");
2198 if (tx->request_method_number == HTP_M_CONNECT) {
2201 if ((tx->response_status_number >= 200) &&
2202 (tx->response_status_number < 300) &&
2205 if (tx->request_port_number != -1) {
2206 dp = (uint16_t)tx->request_port_number;
2210 tx->request_progress = HTP_REQUEST_COMPLETE;
2211 tx->response_progress = HTP_RESPONSE_COMPLETE;
2219 static int HTPCallbackRequestLine(htp_tx_t *tx)
2222 bstr *request_uri_normalized;
2223 HtpState *hstate = htp_connp_get_user_data(tx->connp);
2227 if (request_uri_normalized == NULL)
2230 tx_ud = htp_tx_get_user_data(tx);
2231 if (
likely(tx_ud == NULL)) {
2234 bstr_free(request_uri_normalized);
2237 memset(tx_ud, 0,
sizeof(*tx_ud));
2238 htp_tx_set_user_data(tx, tx_ud);
2245 HTPErrorCheckTxRequestFlags(hstate, tx);
2250 static int HTPCallbackDoubleDecodeUriPart(htp_tx_t *tx, bstr *part)
2256 size_t prevlen = bstr_len(part);
2257 htp_status_t
res = htp_urldecode_inplace(tx->cfg, HTP_DECODER_URLENCODED, part, &
flags);
2259 if (
res == HTP_OK && prevlen > bstr_len(part)) {
2263 HtpState *s = htp_connp_get_user_data(tx->connp);
2273 static int HTPCallbackDoubleDecodeQuery(htp_tx_t *tx)
2275 if (tx->parsed_uri == NULL)
2278 return HTPCallbackDoubleDecodeUriPart(tx, tx->parsed_uri->query);
2281 static int HTPCallbackDoubleDecodePath(htp_tx_t *tx)
2283 if (tx->parsed_uri == NULL)
2286 return HTPCallbackDoubleDecodeUriPart(tx, tx->parsed_uri->path);
2289 static int HTPCallbackRequestHeaderData(htp_tx_data_t *tx_data)
2292 if (tx_data->len == 0 || tx_data->tx == NULL)
2296 if (tx_ud == NULL) {
2308 tx_data->data, tx_data->len);
2311 if (tx_data->tx && tx_data->tx->flags) {
2312 HtpState *hstate = htp_connp_get_user_data(tx_data->tx->connp);
2313 HTPErrorCheckTxRequestFlags(hstate, tx_data->tx);
2318 static int HTPCallbackResponseHeaderData(htp_tx_data_t *tx_data)
2321 if (tx_data->len == 0 || tx_data->tx == NULL)
2325 if (tx_ud == NULL) {
2337 tx_data->data, tx_data->len);
2346 static void HTPConfigSetDefaultsPhase1(
HTPCfgRec *cfg_prec)
2363 htp_config_register_request_header_data(cfg_prec->
cfg, HTPCallbackRequestHeaderData);
2364 htp_config_register_request_trailer_data(cfg_prec->
cfg, HTPCallbackRequestHeaderData);
2365 htp_config_register_response_header_data(cfg_prec->
cfg, HTPCallbackResponseHeaderData);
2366 htp_config_register_response_trailer_data(cfg_prec->
cfg, HTPCallbackResponseHeaderData);
2368 htp_config_register_request_trailer(cfg_prec->
cfg, HTPCallbackRequestHasTrailer);
2369 htp_config_register_response_trailer(cfg_prec->
cfg, HTPCallbackResponseHasTrailer);
2371 htp_config_register_request_body_data(cfg_prec->
cfg, HTPCallbackRequestBodyData);
2372 htp_config_register_response_body_data(cfg_prec->
cfg, HTPCallbackResponseBodyData);
2374 htp_config_register_request_start(cfg_prec->
cfg, HTPCallbackRequestStart);
2375 htp_config_register_request_complete(cfg_prec->
cfg, HTPCallbackRequest);
2377 htp_config_register_response_start(cfg_prec->
cfg, HTPCallbackResponseStart);
2378 htp_config_register_response_complete(cfg_prec->
cfg, HTPCallbackResponse);
2380 htp_config_set_parse_request_cookies(cfg_prec->
cfg, 0);
2383 htp_config_set_plusspace_decode(cfg_prec->
cfg, HTP_DECODER_URLENCODED, 0);
2384 #ifdef HAVE_HTP_CONFIG_SET_LZMA_LAYERS
2388 #ifdef HAVE_HTP_CONFIG_SET_LZMA_MEMLIMIT
2389 htp_config_set_lzma_memlimit(cfg_prec->
cfg,
2392 #ifdef HAVE_HTP_CONFIG_SET_COMPRESSION_BOMB_LIMIT
2393 htp_config_set_compression_bomb_limit(cfg_prec->
cfg,
2402 htp_config_set_field_limits(cfg_prec->
cfg,
2411 static int RandomGetWrap(
void)
2417 }
while(r >= ULONG_MAX - (ULONG_MAX % RAND_MAX));
2419 return r % RAND_MAX;
2428 static void HTPConfigSetDefaultsPhase2(
const char *name,
HTPCfgRec *cfg_prec)
2434 long int r = RandomGetWrap();
2437 (r * 1.0 / RAND_MAX - 0.5) * rdrange / 100);
2439 r = RandomGetWrap();
2442 (r * 1.0 / RAND_MAX - 0.5) * rdrange / 100);
2443 SCLogConfig(
"'%s' server has 'request-body-minimal-inspect-size' set to"
2444 " %d and 'request-body-inspect-window' set to %d after"
2451 r = RandomGetWrap();
2454 (r * 1.0 / RAND_MAX - 0.5) * rdrange / 100);
2456 r = RandomGetWrap();
2459 (r * 1.0 / RAND_MAX - 0.5) * rdrange / 100);
2461 SCLogConfig(
"'%s' server has 'response-body-minimal-inspect-size' set to"
2462 " %d and 'response-body-inspect-window' set to %d after"
2469 htp_config_register_request_line(cfg_prec->
cfg, HTPCallbackRequestLine);
2494 if (cfg_prec == NULL || s == NULL || tree == NULL)
2502 if (strcasecmp(
"address", p->
name) == 0) {
2510 if (strchr(pval->
val,
':') != NULL) {
2511 SCLogDebug(
"LIBHTP adding ipv6 server %s at %s: %p",
2515 "add ipv6 server %s, ignoring", pval->
val);
2518 SCLogDebug(
"LIBHTP adding ipv4 server %s at %s: %p",
2522 "to add ipv4 server %s, ignoring",
2528 }
else if (strcasecmp(
"personality", p->
name) == 0) {
2530 int personality = HTPLookupPersonality(p->
val);
2534 if (personality >= 0) {
2537 if (htp_config_set_server_personality(cfg_prec->
cfg, personality) == HTP_ERROR){
2539 "personality \"%s\", ignoring", p->
val);
2542 HTPLookupPersonalityString(personality));
2548 htp_config_set_convert_lowercase(cfg_prec->
cfg, HTP_DECODER_URL_PATH, 0);
2551 "\"%s\", ignoring", p->
val);
2555 }
else if (strcasecmp(
"request-body-limit", p->
name) == 0 ||
2556 strcasecmp(
"request_body_limit", p->
name) == 0) {
2559 "from conf file - %s. Killing engine", p->
val);
2563 }
else if (strcasecmp(
"response-body-limit", p->
name) == 0) {
2566 "from conf file - %s. Killing engine", p->
val);
2570 }
else if (strcasecmp(
"request-body-minimal-inspect-size", p->
name) == 0) {
2573 "from conf file - %s. Killing engine", p->
val);
2577 }
else if (strcasecmp(
"request-body-inspect-window", p->
name) == 0) {
2580 "from conf file - %s. Killing engine", p->
val);
2584 }
else if (strcasecmp(
"double-decode-query", p->
name) == 0) {
2586 htp_config_register_request_line(cfg_prec->
cfg,
2587 HTPCallbackDoubleDecodeQuery);
2590 }
else if (strcasecmp(
"double-decode-path", p->
name) == 0) {
2592 htp_config_register_request_line(cfg_prec->
cfg,
2593 HTPCallbackDoubleDecodePath);
2596 }
else if (strcasecmp(
"response-body-minimal-inspect-size", p->
name) == 0) {
2599 "from conf file - %s. Killing engine", p->
val);
2603 }
else if (strcasecmp(
"response-body-inspect-window", p->
name) == 0) {
2606 "from conf file - %s. Killing engine", p->
val);
2610 }
else if (strcasecmp(
"response-body-decompress-layer-limit", p->
name) == 0) {
2614 "from conf file - %s. Killing engine", p->
val);
2617 #ifdef HAVE_HTP_CONFIG_SET_RESPONSE_DECOMPRESSION_LAYER_LIMIT
2618 htp_config_set_response_decompression_layer_limit(cfg_prec->
cfg, value);
2621 "to %u, libhtp version too old", value);
2623 }
else if (strcasecmp(
"path-convert-backslash-separators", p->
name) == 0) {
2624 htp_config_set_backslash_convert_slashes(cfg_prec->
cfg,
2625 HTP_DECODER_URL_PATH,
2627 }
else if (strcasecmp(
"path-bestfit-replacement-char", p->
name) == 0) {
2628 if (strlen(p->
val) == 1) {
2629 htp_config_set_bestfit_replacement_byte(cfg_prec->
cfg,
2630 HTP_DECODER_URL_PATH,
2634 "for libhtp param path-bestfit-replacement-char");
2636 }
else if (strcasecmp(
"path-convert-lowercase", p->
name) == 0) {
2637 htp_config_set_convert_lowercase(cfg_prec->
cfg,
2638 HTP_DECODER_URL_PATH,
2640 }
else if (strcasecmp(
"path-nul-encoded-terminates", p->
name) == 0) {
2641 htp_config_set_nul_encoded_terminates(cfg_prec->
cfg,
2642 HTP_DECODER_URL_PATH,
2644 }
else if (strcasecmp(
"path-nul-raw-terminates", p->
name) == 0) {
2645 htp_config_set_nul_raw_terminates(cfg_prec->
cfg,
2646 HTP_DECODER_URL_PATH,
2648 }
else if (strcasecmp(
"path-separators-compress", p->
name) == 0) {
2649 htp_config_set_path_separators_compress(cfg_prec->
cfg,
2650 HTP_DECODER_URL_PATH,
2652 }
else if (strcasecmp(
"path-separators-decode", p->
name) == 0) {
2653 htp_config_set_path_separators_decode(cfg_prec->
cfg,
2654 HTP_DECODER_URL_PATH,
2656 }
else if (strcasecmp(
"path-u-encoding-decode", p->
name) == 0) {
2657 htp_config_set_u_encoding_decode(cfg_prec->
cfg,
2658 HTP_DECODER_URL_PATH,
2660 }
else if (strcasecmp(
"path-url-encoding-invalid-handling", p->
name) == 0) {
2661 enum htp_url_encoding_handling_t handling;
2662 if (strcasecmp(p->
val,
"preserve_percent") == 0) {
2663 handling = HTP_URL_DECODE_PRESERVE_PERCENT;
2664 }
else if (strcasecmp(p->
val,
"remove_percent") == 0) {
2665 handling = HTP_URL_DECODE_REMOVE_PERCENT;
2666 }
else if (strcasecmp(p->
val,
"decode_invalid") == 0) {
2667 handling = HTP_URL_DECODE_PROCESS_INVALID;
2670 "for libhtp param path-url-encoding-invalid-handling");
2673 htp_config_set_url_encoding_invalid_handling(cfg_prec->
cfg,
2674 HTP_DECODER_URL_PATH,
2676 }
else if (strcasecmp(
"path-utf8-convert-bestfit", p->
name) == 0) {
2677 htp_config_set_utf8_convert_bestfit(cfg_prec->
cfg,
2678 HTP_DECODER_URL_PATH,
2680 }
else if (strcasecmp(
"uri-include-all", p->
name) == 0) {
2684 }
else if (strcasecmp(
"query-plusspace-decode", p->
name) == 0) {
2685 htp_config_set_plusspace_decode(cfg_prec->
cfg,
2686 HTP_DECODER_URLENCODED,
2688 }
else if (strcasecmp(
"meta-field-limit", p->
name) == 0) {
2692 "from conf file - %s. Killing engine", p->
val);
2697 "from conf file cannot be 0. Killing engine");
2700 htp_config_set_field_limits(cfg_prec->
cfg,
2703 #ifdef HAVE_HTP_CONFIG_SET_LZMA_MEMLIMIT
2704 }
else if (strcasecmp(
"lzma-memlimit", p->
name) == 0) {
2708 "from conf file - %s.", p->
val);
2712 "from conf file cannot be 0.");
2715 SCLogConfig(
"Setting HTTP LZMA memory limit to %"PRIu32
" bytes", limit);
2716 htp_config_set_lzma_memlimit(cfg_prec->
cfg, (
size_t)limit);
2718 #ifdef HAVE_HTP_CONFIG_SET_LZMA_LAYERS
2719 }
else if (strcasecmp(
"lzma-enabled", p->
name) == 0) {
2721 htp_config_set_lzma_layers(cfg_prec->
cfg, 1);
2726 "failed to parse 'lzma-enabled' "
2727 "from conf file - %s.",
2730 SCLogConfig(
"Setting HTTP LZMA decompression layers to %" PRIu32
"", (
int)limit);
2731 htp_config_set_lzma_layers(cfg_prec->
cfg, limit);
2734 #ifdef HAVE_HTP_CONFIG_SET_COMPRESSION_BOMB_LIMIT
2735 }
else if (strcasecmp(
"compression-bomb-limit", p->
name) == 0) {
2739 "from conf file - %s.", p->
val);
2743 "from conf file cannot be 0.");
2746 SCLogConfig(
"Setting HTTP compression bomb limit to %"PRIu32
" bytes", limit);
2747 htp_config_set_compression_bomb_limit(cfg_prec->
cfg, (
size_t)limit);
2749 }
else if (strcasecmp(
"randomize-inspection-sizes", p->
name) == 0) {
2753 }
else if (strcasecmp(
"randomize-inspection-range", p->
name) == 0) {
2756 (
const char *)p->
val, 0, 100) < 0) {
2758 "-inspection-range setting from conf file - \"%s\"."
2759 " It should be a valid integer less than or equal to 100."
2765 }
else if (strcasecmp(
"http-body-inline", p->
name) == 0) {
2771 if (strcmp(
"auto", p->
val) != 0) {
2780 }
else if (strcasecmp(
"swf-decompression", p->
name) == 0) {
2784 if (strcasecmp(
"enabled", pval->
name) == 0) {
2792 }
else if (strcasecmp(
"type", pval->
name) == 0) {
2793 if (strcasecmp(
"no", pval->
val) == 0) {
2795 }
else if (strcasecmp(
"deflate", pval->
val) == 0) {
2797 }
else if (strcasecmp(
"lzma", pval->
val) == 0) {
2799 }
else if (strcasecmp(
"both", pval->
val) == 0) {
2803 "Invalid entry for "
2804 "swf-decompression.type: %s - "
2805 "Killing engine", pval->
val);
2808 }
else if (strcasecmp(
"compress-depth", pval->
name) == 0) {
2811 "Error parsing swf-decompression.compression-depth "
2812 "from conf file - %s. Killing engine", p->
val);
2815 }
else if (strcasecmp(
"decompress-depth", pval->
name) == 0) {
2818 "Error parsing swf-decompression.decompression-depth "
2819 "from conf file - %s. Killing engine", p->
val);
2828 "default config: %s", p->
name);
2839 cfglist.
next = NULL;
2842 if (NULL == cfgtree)
2846 cfglist.
cfg = htp_config_create();
2847 if (NULL == cfglist.
cfg) {
2851 HTPConfigSetDefaultsPhase1(&cfglist);
2852 if (
ConfGetNode(
"app-layer.protocols.http.libhtp") == NULL) {
2853 HTPConfigParseParameters(&cfglist,
ConfGetNode(
"libhtp.default-config"),
2856 HTPConfigParseParameters(&cfglist,
ConfGetNode(
"app-layer.protocols.http.libhtp.default-config"), cfgtree);
2858 HTPConfigSetDefaultsPhase2(
"default", &cfglist);
2864 if (server_config == NULL) {
2865 server_config =
ConfGetNode(
"libhtp.server-config");
2866 if (server_config == NULL) {
2867 SCLogDebug(
"LIBHTP Configuring %p", server_config);
2871 SCLogDebug(
"LIBHTP Configuring %p", server_config);
2889 memset(htprec, 0x00,
sizeof(*htprec));
2891 cfglist.
next = htprec;
2894 cfglist.
next->
cfg = htp_config_create();
2895 if (NULL == cfglist.
next->
cfg) {
2899 HTPConfigSetDefaultsPhase1(htprec);
2900 HTPConfigParseParameters(htprec, s, cfgtree);
2901 HTPConfigSetDefaultsPhase2(s->
name, htprec);
2911 SCLogPerf(
"htp memory %"PRIu64
" (%"PRIu64
")", htp_state_memuse, htp_state_memcnt);
2922 static FileContainer *HTPStateGetFiles(
void *state, uint8_t direction)
2936 static int HTPStateGetAlstateProgress(
void *tx, uint8_t direction)
2939 return ((htp_tx_t *)tx)->request_progress;
2941 return ((htp_tx_t *)tx)->response_progress;
2944 static uint64_t HTPStateGetTxCnt(
void *alstate)
2948 if (http_state != NULL && http_state->
conn != NULL) {
2949 const int64_t size = (int64_t)htp_list_size(http_state->
conn->transactions);
2953 return (uint64_t)size;
2959 static void *HTPStateGetTx(
void *alstate, uint64_t tx_id)
2963 if (http_state != NULL && http_state->
conn != NULL)
2964 return htp_list_get(http_state->
conn->transactions, tx_id);
2973 if (http_state != NULL && http_state->
conn != NULL) {
2974 size_t txid = htp_list_array_size(http_state->
conn->transactions);
2976 return htp_list_get(http_state->
conn->transactions, txid - 1);
2982 static int HTPStateGetEventInfo(
const char *event_name,
2986 if (*event_id == -1) {
2988 "http's enum map table.", event_name);
2998 static int HTPStateGetEventInfoById(
int event_id,
const char **event_name,
3002 if (*event_name == NULL) {
3004 "http's enum map table.", event_id);
3014 static void HTPStateTruncate(
void *state, uint8_t direction)
3024 htp_tx_t *tx = (htp_tx_t *)vtx;
3026 return tx_ud ? tx_ud->
de_state : NULL;
3031 htp_tx_t *tx = (htp_tx_t *)vtx;
3033 if (tx_ud == NULL) {
3040 static AppLayerTxData *HTPGetTxData(
void *vtx)
3042 htp_tx_t *tx = (htp_tx_t *)vtx;
3050 static int HTPRegisterPatternsForProtocolDetection(
void)
3052 const char *methods[] = {
"GET",
"PUT",
"POST",
"HEAD",
"TRACE",
"OPTIONS",
3053 "CONNECT",
"DELETE",
"PATCH",
"PROPFIND",
"PROPPATCH",
"MKCOL",
3054 "COPY",
"MOVE",
"LOCK",
"UNLOCK",
"CHECKOUT",
"UNCHECKOUT",
"CHECKIN",
3055 "UPDATE",
"LABEL",
"REPORT",
"MKWORKSPACE",
"MKACTIVITY",
"MERGE",
3056 "INVALID",
"VERSION-CONTROL",
"BASELINE-CONTROL", NULL};
3057 const char *spacings[] = {
"|20|",
"|09|", NULL };
3058 const char *versions[] = {
"HTTP/0.9",
"HTTP/1.0",
"HTTP/1.1", NULL };
3063 int register_result;
3064 char method_buffer[32] =
"";
3067 for (methods_pos = 0; methods[methods_pos]; methods_pos++) {
3068 for (spacings_pos = 0; spacings[spacings_pos]; spacings_pos++) {
3071 snprintf(method_buffer,
sizeof(method_buffer),
"%s%s", methods[methods_pos], spacings[spacings_pos]);
3079 if (register_result < 0) {
3086 for (versions_pos = 0; versions[versions_pos]; versions_pos++) {
3088 ALPROTO_HTTP, versions[versions_pos], strlen(versions[versions_pos]),
3090 if (register_result < 0) {
3106 const char *proto_name =
"http";
3111 if (HTPRegisterPatternsForProtocolDetection() < 0)
3114 SCLogInfo(
"Protocol detection and parser disabled for %s protocol",
3128 ALPROTO_HTTP, HTP_REQUEST_COMPLETE, HTP_RESPONSE_COMPLETE);
3135 HTPGetTxDetectState, HTPSetTxDetectState);
3139 AppLayerHtpSetStreamDepthFlag);
3142 HTPHandleRequestData);
3144 HTPHandleResponseData);
3153 SCLogInfo(
"Parsed disabled for %s protocol. Protocol detection"
3154 "still on.", proto_name);
3168 cfglist_backup = cfglist;
3175 cfglist = cfglist_backup;
3182 static int HTPParserTest01(
void)
3184 uint8_t httpbuf1[] =
"POST / HTTP/1.0\r\nUser-Agent: Victor/1.0\r\n\r\nPost"
3186 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3189 memset(&ssn, 0,
sizeof(ssn));
3197 f->
proto = IPPROTO_TCP;
3203 for (u = 0; u < httplen1; u++) {
3208 else if (u == (httplen1 - 1))
3221 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3224 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3227 FAIL_IF(strcmp(bstr_util_strdup_to_c(h->value),
"Victor/1.0"));
3228 FAIL_IF(tx->request_method_number != HTP_M_POST);
3229 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_0);
3238 static int HTPParserTest01b(
void)
3240 uint8_t httpbuf1[] =
"POST / HTTP/1.0\r\nUser-Agent:\r\n Victor/1.0\r\n\r\nPost"
3242 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3245 memset(&ssn, 0,
sizeof(ssn));
3253 f->
proto = IPPROTO_TCP;
3260 httpbuf1, httplen1);
3266 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3269 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3272 FAIL_IF(strcmp(bstr_util_strdup_to_c(h->value),
"Victor/1.0"));
3273 FAIL_IF(tx->request_method_number != HTP_M_POST);
3274 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_0);
3283 static int HTPParserTest01c(
void)
3285 uint8_t httpbuf1[] =
"POST / HTTP/1.0\r\nUser-Agent:\r\n Victor/1.0\r\n\r\nPost"
3287 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3290 memset(&ssn, 0,
sizeof(ssn));
3298 f->
proto = IPPROTO_TCP;
3304 for (u = 0; u < httplen1; u++) {
3309 else if (u == (httplen1 - 1))
3322 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3325 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3328 FAIL_IF(strcmp(bstr_util_strdup_to_c(h->value),
"Victor/1.0"));
3329 FAIL_IF(tx->request_method_number != HTP_M_POST);
3330 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_0);
3340 static int HTPParserTest01a(
void)
3344 uint8_t httpbuf1[] =
" POST / HTTP/1.0\r\nUser-Agent: Victor/1.0\r\n\r\nPost"
3346 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3352 memset(&ssn, 0,
sizeof(ssn));
3354 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
3358 f->
proto = IPPROTO_TCP;
3364 for (u = 0; u < httplen1; u++) {
3369 else if (u == (httplen1 - 1))
3378 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
3387 if (htp_state == NULL) {
3388 printf(
"no http state: ");
3392 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3393 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3394 if (strcmp(bstr_util_strdup_to_c(h->value),
"Victor/1.0")
3395 || tx->request_method_number != HTP_M_POST ||
3396 tx->request_protocol_number != HTP_PROTOCOL_1_0)
3398 printf(
"expected header value: Victor/1.0 and got %s: and expected"
3399 " method: POST and got %s, expected protocol number HTTP/1.0"
3400 " and got: %s \n", bstr_util_strdup_to_c(h->value),
3401 bstr_util_strdup_to_c(tx->request_method),
3402 bstr_util_strdup_to_c(tx->request_protocol));
3415 static int HTPParserTest02(
void)
3419 uint8_t httpbuf1[] =
"POST";
3420 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3425 memset(&ssn, 0,
sizeof(ssn));
3427 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
3431 f->
proto = IPPROTO_TCP;
3442 printf(
"toserver chunk 1 returned %" PRId32
", expected 0: ", r);
3449 if (http_state == NULL) {
3450 printf(
"no http state: ");
3454 htp_tx_t *tx = HTPStateGetTx(http_state, 0);
3456 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3460 char *method = bstr_util_strdup_to_c(tx->request_method);
3463 FAIL_IF(strcmp(method,
"POST") != 0);
3477 static int HTPParserTest03(
void)
3481 uint8_t httpbuf1[] =
"HELLO / HTTP/1.0\r\n";
3482 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3488 memset(&ssn, 0,
sizeof(ssn));
3490 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
3494 f->
proto = IPPROTO_TCP;
3500 for (u = 0; u < httplen1; u++) {
3511 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
3519 if (htp_state == NULL) {
3520 printf(
"no http state: ");
3524 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3526 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3527 if (tx->request_method_number != HTP_M_UNKNOWN ||
3528 h != NULL || tx->request_protocol_number != HTP_PROTOCOL_1_0)
3530 printf(
"expected method M_UNKNOWN and got %s: , expected protocol "
3531 "HTTP/1.0 and got %s \n", bstr_util_strdup_to_c(tx->request_method),
3532 bstr_util_strdup_to_c(tx->request_protocol));
3546 static int HTPParserTest04(
void)
3551 uint8_t httpbuf1[] =
"World!\r\n";
3552 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3557 memset(&ssn, 0,
sizeof(ssn));
3559 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
3563 f->
proto = IPPROTO_TCP;
3580 if (htp_state == NULL) {
3581 printf(
"no http state: ");
3585 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3586 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3587 if (tx->request_method_number != HTP_M_UNKNOWN ||
3588 h != NULL || tx->request_protocol_number != HTP_PROTOCOL_0_9)
3590 printf(
"expected method M_UNKNOWN and got %s: , expected protocol "
3591 "NULL and got %s \n", bstr_util_strdup_to_c(tx->request_method),
3592 bstr_util_strdup_to_c(tx->request_protocol));
3606 static int HTPParserTest05(
void)
3608 uint8_t httpbuf1[] =
"POST / HTTP/1.0\r\nUser-Agent: Victor/1.0\r\nContent-Length: 17\r\n\r\n";
3609 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3610 uint8_t httpbuf2[] =
"Post D";
3611 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
3612 uint8_t httpbuf3[] =
"ata is c0oL!";
3613 uint32_t httplen3 =
sizeof(httpbuf3) - 1;
3615 uint8_t httpbuf4[] =
"HTTP/1.0 200 OK\r\nServer: VictorServer/1.0\r\n\r\n";
3616 uint32_t httplen4 =
sizeof(httpbuf4) - 1;
3617 uint8_t httpbuf5[] =
"post R";
3618 uint32_t httplen5 =
sizeof(httpbuf5) - 1;
3619 uint8_t httpbuf6[] =
"esults are tha bomb!";
3620 uint32_t httplen6 =
sizeof(httpbuf6) - 1;
3623 memset(&ssn, 0,
sizeof(ssn));
3631 f->
proto = IPPROTO_TCP;
3647 httpbuf5, httplen5);
3651 httpbuf2, httplen2);
3665 htp_tx_t *tx = HTPStateGetTx(http_state, 0);
3667 FAIL_IF_NOT(tx->request_method_number == HTP_M_POST);
3668 FAIL_IF_NOT(tx->request_protocol_number == HTP_PROTOCOL_1_0);
3670 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3683 static int HTPParserTest06(
void)
3685 uint8_t httpbuf1[] =
"GET /ld/index.php?id=412784631&cid=0064&version=4&"
3686 "name=try HTTP/1.1\r\nAccept: */*\r\nUser-Agent: "
3687 "LD-agent\r\nHost: 209.205.196.16\r\n\r\n";
3688 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3689 uint8_t httpbuf2[] =
"HTTP/1.1 200 OK\r\nDate: Sat, 03 Oct 2009 10:16:02 "
3691 "Server: Apache/1.3.37 (Unix) mod_ssl/2.8.28 "
3692 "OpenSSL/0.9.7a PHP/4.4.7 mod_perl/1.29 "
3693 "FrontPage/5.0.2.2510\r\n"
3694 "X-Powered-By: PHP/4.4.7\r\nTransfer-Encoding: "
3696 "Content-Type: text/html\r\n\r\n"
3698 "W2dyb3VwMV0NCnBob25lMT1wMDB3ODgyMTMxMzAyMTINCmxvZ2lu"
3699 "MT0NCnBhc3N3b3JkMT0NCnBob25lMj1wMDB3ODgyMTMxMzAyMTIN"
3700 "CmxvZ2luMj0NCnBhc3N3b3JkMj0NCnBob25lMz0NCmxvZ2luMz0N"
3701 "CnBhc3N3b3JkMz0NCnBob25lND0NCmxvZ2luND0NCnBhc3N3b3Jk"
3702 "ND0NCnBob25lNT0NCmxvZ2luNT0NCnBhc3N3b3JkNT0NCnBob25l"
3703 "Nj0NCmxvZ2luNj0NCnBhc3N3b3JkNj0NCmNhbGxfdGltZTE9MzIN"
3704 "CmNhbGxfdGltZTI9MjMyDQpkYXlfbGltaXQ9NQ0KbW9udGhfbGlt"
3705 "aXQ9MTUNCltncm91cDJdDQpwaG9uZTE9DQpsb2dpbjE9DQpwYXNz"
3706 "d29yZDE9DQpwaG9uZTI9DQpsb2dpbjI9DQpwYXNzd29yZDI9DQpw"
3707 "aG9uZTM9DQpsb2dpbjM9DQpwYXNzd29yZDM9DQpwaG9uZTQ9DQps"
3708 "b2dpbjQ9DQpwYXNzd29yZDQ9DQpwaG9uZTU9DQpsb2dpbjU9DQpw"
3709 "YXNzd29yZDU9DQpwaG9uZTY9DQpsb2dpbjY9DQpwYXNzd29yZDY9"
3710 "DQpjYWxsX3RpbWUxPQ0KY2FsbF90aW1lMj0NCmRheV9saW1pdD0N"
3711 "Cm1vbnRoX2xpbWl0PQ0KW2dyb3VwM10NCnBob25lMT0NCmxvZ2lu"
3712 "MT0NCnBhc3N3b3JkMT0NCnBob25lMj0NCmxvZ2luMj0NCnBhc3N3"
3713 "b3JkMj0NCnBob25lMz0NCmxvZ2luMz0NCnBhc3N3b3JkMz0NCnBo"
3714 "b25lND0NCmxvZ2luND0NCnBhc3N3b3JkND0NCnBob25lNT0NCmxv"
3715 "Z2luNT0NCnBhc3N3b3JkNT0NCnBob25lNj0NCmxvZ2luNj0NCnBh"
3716 "c3N3b3JkNj0NCmNhbGxfdGltZTE9DQpjYWxsX3RpbWUyPQ0KZGF5"
3717 "X2xpbWl0PQ0KbW9udGhfbGltaXQ9DQpbZ3JvdXA0XQ0KcGhvbmUx"
3718 "PQ0KbG9naW4xPQ0KcGFzc3dvcmQxPQ0KcGhvbmUyPQ0KbG9naW4y"
3719 "PQ0KcGFzc3dvcmQyPQ0KcGhvbmUzPQ0KbG9naW4zPQ0KcGFzc3dv"
3720 "cmQzPQ0KcGhvbmU0PQ0KbG9naW40PQ0KcGFzc3dvcmQ0PQ0KcGhv"
3721 "bmU1PQ0KbG9naW41PQ0KcGFzc3dvcmQ1PQ0KcGhvbmU2PQ0KbG9n"
3722 "aW42PQ0KcGFzc3dvcmQ2PQ0KY2FsbF90aW1lMT0NCmNhbGxfdGlt"
3723 "ZTI9DQpkYXlfbGltaXQ9DQptb250aF9saW1pdD0NCltmaWxlc10N"
3724 "Cmxpbms9aHR0cDovLzIwOS4yMDUuMTk2LjE2L2xkL2dldGJvdC5w"
3725 "aHA=\r\n0\r\n\r\n";
3726 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
3732 memset(&ssn, 0,
sizeof(ssn));
3737 f->
proto = IPPROTO_TCP;
3754 htp_tx_t *tx = HTPStateGetTx(http_state, 0);
3757 FAIL_IF(tx->request_method_number != HTP_M_GET);
3758 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_1);
3760 FAIL_IF(tx->response_status_number != 200);
3761 FAIL_IF(tx->request_protocol_number != HTP_PROTOCOL_1_1);
3763 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
3774 static int HTPParserTest07(
void)
3778 uint8_t httpbuf1[] =
"GET /awstats.pl?/migratemigrate%20=%20| HTTP/1.0\r\n\r\n";
3779 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3785 memset(&ssn, 0,
sizeof(ssn));
3787 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
3791 f->
proto = IPPROTO_TCP;
3797 for (u = 0; u < httplen1; u++) {
3802 else if (u == (httplen1 - 1))
3811 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
3820 if (htp_state == NULL) {
3821 printf(
"no http state: ");
3825 uint8_t ref[] =
"/awstats.pl?/migratemigrate = |";
3826 size_t reflen =
sizeof(ref) - 1;
3828 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3834 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
3843 printf(
"normalized uri \"");
3865 static int HTPParserTest08(
void)
3869 uint8_t httpbuf1[] =
"GET /secondhouse/image/js/\%ce\%de\%ce\%fd_RentCity.js?v=2011.05.02 HTTP/1.0\r\n\r\n";
3870 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3892 memset(&ssn, 0,
sizeof(ssn));
3894 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
3898 f->
proto = IPPROTO_TCP;
3910 printf(
"toserver chunk returned %" PRId32
", expected"
3919 if (htp_state == NULL) {
3920 printf(
"no http state: ");
3925 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
3950 static int HTPParserTest09(
void)
3954 uint8_t httpbuf1[] =
"GET /secondhouse/image/js/\%ce\%de\%ce\%fd_RentCity.js?v=2011.05.02 HTTP/1.0\r\n\r\n";
3955 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
3965 personality: Apache_2_2\n\
3978 memset(&ssn, 0,
sizeof(ssn));
3980 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
3984 f->
proto = IPPROTO_TCP;
3996 printf(
"toserver chunk returned %" PRId32
", expected"
4004 if (htp_state == NULL) {
4005 printf(
"no http state: ");
4009 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4034 static int HTPParserTest10(
void)
4038 uint8_t httpbuf1[] =
"GET / HTTP/1.0\r\nHost:www.google.com\r\n\r\n";
4039 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4045 memset(&ssn, 0,
sizeof(ssn));
4047 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
4051 f->
proto = IPPROTO_TCP;
4057 for (u = 0; u < httplen1; u++) {
4062 else if (u == (httplen1 - 1))
4071 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
4080 if (htp_state == NULL) {
4081 printf(
"no http state: ");
4085 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4086 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
4091 char *name = bstr_util_strdup_to_c(h->name);
4096 if (strcmp(name,
"Host") != 0) {
4097 printf(
"header name not \"Host\", instead \"%s\": ", name);
4103 char *value = bstr_util_strdup_to_c(h->value);
4104 if (value == NULL) {
4108 if (strcmp(value,
"www.google.com") != 0) {
4109 printf(
"header value not \"www.google.com\", instead \"%s\": ", value);
4126 static int HTPParserTest11(
void)
4130 uint8_t httpbuf1[] =
"GET /%2500 HTTP/1.0\r\n\r\n";
4131 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4137 memset(&ssn, 0,
sizeof(ssn));
4139 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
4143 f->
proto = IPPROTO_TCP;
4149 for (u = 0; u < httplen1; u++) {
4154 else if (u == (httplen1 - 1))
4163 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
4172 if (htp_state == NULL) {
4173 printf(
"no http state: ");
4177 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4183 printf(
"normalized uri len should be 2, is %"PRIuMAX,
4193 printf(
"normalized uri \"");
4211 static int HTPParserTest12(
void)
4215 uint8_t httpbuf1[] =
"GET /?a=%2500 HTTP/1.0\r\n\r\n";
4216 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4222 memset(&ssn, 0,
sizeof(ssn));
4224 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
4228 f->
proto = IPPROTO_TCP;
4234 for (u = 0; u < httplen1; u++) {
4239 else if (u == (httplen1 - 1))
4248 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
4257 if (htp_state == NULL) {
4258 printf(
"no http state: ");
4262 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4268 printf(
"normalized uri len should be 5, is %"PRIuMAX,
4281 printf(
"normalized uri \"");
4299 static int HTPParserTest13(
void)
4303 uint8_t httpbuf1[] =
"GET / HTTP/1.0\r\nHost:www.google.com\rName: Value\r\n\r\n";
4304 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4310 memset(&ssn, 0,
sizeof(ssn));
4312 f =
UTHBuildFlow(AF_INET,
"1.2.3.4",
"1.2.3.5", 1024, 80);
4316 f->
proto = IPPROTO_TCP;
4322 for (u = 0; u < httplen1; u++) {
4327 else if (u == (httplen1 - 1))
4336 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
4345 if (htp_state == NULL) {
4346 printf(
"no http state: ");
4350 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4351 htp_header_t *h = htp_table_get_index(tx->request_headers, 0, NULL);
4356 char *name = bstr_util_strdup_to_c(h->name);
4361 if (strcmp(name,
"Host") != 0) {
4362 printf(
"header name not \"Host\", instead \"%s\": ", name);
4368 char *value = bstr_util_strdup_to_c(h->value);
4369 if (value == NULL) {
4373 if (strcmp(value,
"www.google.com\rName: Value") != 0) {
4374 printf(
"header value not \"www.google.com\", instead \"");
4392 static int HTPParserConfigTest01(
void)
4406 address: [192.168.1.0/24, 127.0.0.0/8, \"::1\"]\n\
4407 personality: Tomcat_6_0\n\
4412 - 192.168.10.0/24\n\
4413 personality: IIS_7_0\n\
4422 outputs =
ConfGetNode(
"libhtp.default-config.personality");
4423 if (outputs == NULL) {
4428 if (outputs == NULL) {
4436 if (strcmp(node->
name,
"0") != 0) {
4443 if (strcmp(node->
name,
"apache-tomcat") != 0) {
4451 if (node2 == NULL) {
4454 if (strcmp(node2->
val,
"Tomcat_6_0") != 0) {
4469 if (strcmp(n->
name,
"0") != 0) {
4472 if (strcmp(n->
val,
"192.168.1.0/24") != 0) {
4477 if (strcmp(n->
name,
"1") != 0) {
4480 if (strcmp(n->
val,
"127.0.0.0/8") != 0) {
4485 if (strcmp(n->
name,
"2") != 0) {
4488 if (strcmp(n->
val,
"::1") != 0) {
4499 if (outputs == NULL) {
4508 if (strcmp(node->
name,
"1") != 0) {
4515 if (strcmp(node->
name,
"iis7") != 0) {
4520 if (node2 == NULL) {
4523 if (strcmp(node2->
val,
"IIS_7_0") != 0) {
4540 if (strcmp(n->
name,
"0") != 0) {
4543 if (strcmp(n->
val,
"192.168.0.0/24") != 0) {
4548 if (strcmp(n->
name,
"1") != 0) {
4551 if (strcmp(n->
val,
"192.168.10.0/24") != 0) {
4571 static int HTPParserConfigTest02(
void)
4585 address: [192.168.1.0/24, 127.0.0.0/8, \"::1\"]\n\
4586 personality: Tomcat_6_0\n\
4591 - 192.168.10.0/24\n\
4592 personality: IIS_7_0\n\
4603 if (cfglist.
cfg == NULL) {
4604 printf(
"No default config created.\n");
4608 if (cfgtree == NULL) {
4609 printf(
"No config tree created.\n");
4613 htp_cfg_t *htp = cfglist.
cfg;
4616 void *user_data = NULL;
4618 addr =
"192.168.10.42";
4619 if (inet_pton(AF_INET, addr, buf) == 1) {
4621 if (user_data != NULL) {
4623 htp = htp_cfg_rec->
cfg;
4627 printf(
"Could not get config for: %s\n", addr);
4632 printf(
"Failed to parse address: %s\n", addr);
4638 if (inet_pton(AF_INET6, addr, buf) == 1) {
4640 if (user_data != NULL) {
4642 htp = htp_cfg_rec->
cfg;
4646 printf(
"Could not get config for: %s\n", addr);
4651 printf(
"Failed to parse address: %s\n", addr);
4667 static int HTPParserConfigTest03(
void)
4671 uint8_t httpbuf1[] =
"POST / HTTP/1.0\r\nUser-Agent: Victor/1.0\r\n\r\nPost"
4673 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4690 address: [192.168.1.0/24, 127.0.0.0/8, \"::1\"]\n\
4691 personality: Tomcat_6_0\n\
4696 - 192.168.10.0/24\n\
4697 personality: IIS_7_0\n\
4708 const char *addr =
"192.168.10.42";
4710 memset(&ssn, 0,
sizeof(ssn));
4716 f->
proto = IPPROTO_TCP;
4719 htp_cfg_t *htp = cfglist.
cfg;
4721 void *user_data = NULL;
4723 if (user_data != NULL) {
4725 htp = htp_cfg_rec->
cfg;
4729 printf(
"Could not get config for: %s\n", addr);
4736 for (u = 0; u < httplen1; u++) {
4747 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
4757 if (htp_state == NULL) {
4758 printf(
"no http state: ");
4763 if (HTPStateGetTxCnt(htp_state) != 2) {
4764 printf(
"HTPStateGetTxCnt(htp_state) failure\n");
4768 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4771 if (tx->cfg != htp) {
4772 printf(
"wrong HTP config (%p instead of %p - default=%p): ",
4773 tx->cfg, htp, cfglist.
cfg);
4776 tx = HTPStateGetTx(htp_state, 1);
4779 if (tx->cfg != htp) {
4780 printf(
"wrong HTP config (%p instead of %p - default=%p): ",
4781 tx->cfg, htp, cfglist.
cfg);
4800 static int HTPParserConfigTest04(
void)
4811 path-control-char-handling: status_400\n\
4812 path-convert-utf8: yes\n\
4813 path-invalid-encoding-handling: remove_percent\n\
4818 personality: Tomcat_6_0\n\
4819 path-invalid-utf8-handling: none\n\
4820 path-nul-encoded-handling: status_404\n\
4821 path-nul-raw-handling: status_400\n\
4824 personality: IIS_7_0\n\
4825 path-replacement-char: o\n\
4826 path-unicode-mapping: status_400\n\
4838 if (cfg_rec->
cfg->path_control_char_handling != STATUS_400 ||
4839 cfg_rec->
cfg->path_convert_utf8 != 1 ||
4840 cfg_rec->
cfg->path_invalid_encoding_handling != URL_DECODER_REMOVE_PERCENT) {
4841 printf(
"failed 1\n");
4845 cfg_rec = cfg_rec->
next;
4846 if (cfg_rec->
cfg->bestfit_replacement_char !=
'o' ||
4847 cfg_rec->
cfg->path_unicode_mapping != STATUS_400) {
4848 printf(
"failed 2\n");
4852 cfg_rec = cfg_rec->
next;
4853 if (cfg_rec->
cfg->path_invalid_utf8_handling != NONE ||
4854 cfg_rec->
cfg->path_nul_encoded_handling != STATUS_404 ||
4855 cfg_rec->
cfg->path_nul_raw_handling != STATUS_400) {
4856 printf(
"failed 3\n");
4878 static int HTPParserDecodingTest01(
void)
4882 uint8_t httpbuf1[] =
4883 "GET /abc%2fdef HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
4884 "GET /abc/def?ghi%2fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
4885 "GET /abc/def?ghi%252fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
4886 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
4898 personality: Apache_2\n\
4906 const char *addr =
"4.3.2.1";
4907 memset(&ssn, 0,
sizeof(ssn));
4913 f->
proto = IPPROTO_TCP;
4919 for (u = 0; u < httplen1; u++) {
4930 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
4939 if (htp_state == NULL) {
4940 printf(
"no http state: ");
4944 uint8_t ref1[] =
"/abc%2fdef";
4945 size_t reflen =
sizeof(ref1) - 1;
4947 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
4953 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
4962 printf(
"normalized uri \"");
4971 uint8_t ref2[] =
"/abc/def?ghi/jkl";
4972 reflen =
sizeof(ref2) - 1;
4974 tx = HTPStateGetTx(htp_state, 1);
4980 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
4989 printf(
"normalized uri \"");
4998 uint8_t ref3[] =
"/abc/def?ghi%2fjkl";
4999 reflen =
sizeof(ref3) - 1;
5000 tx = HTPStateGetTx(htp_state, 2);
5006 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5015 printf(
"normalized uri \"");
5045 static int HTPParserDecodingTest02(
void)
5049 uint8_t httpbuf1[] =
5050 "GET /abc%2fdef HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
5051 "GET /abc/def?ghi%2fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
5052 "GET /abc/def?ghi%252fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5053 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5066 double-decode-path: no\n\
5067 double-decode-query: no\n\
5075 const char *addr =
"4.3.2.1";
5076 memset(&ssn, 0,
sizeof(ssn));
5082 f->
proto = IPPROTO_TCP;
5088 for (u = 0; u < httplen1; u++) {
5099 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5108 if (htp_state == NULL) {
5109 printf(
"no http state: ");
5113 uint8_t ref1[] =
"/abc/def";
5114 size_t reflen =
sizeof(ref1) - 1;
5116 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5122 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5131 printf(
"normalized uri \"");
5140 uint8_t ref2[] =
"/abc/def?ghi/jkl";
5141 reflen =
sizeof(ref2) - 1;
5143 tx = HTPStateGetTx(htp_state, 1);
5149 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5158 printf(
"normalized uri \"");
5167 uint8_t ref3[] =
"/abc/def?ghi%2fjkl";
5168 reflen =
sizeof(ref3) - 1;
5169 tx = HTPStateGetTx(htp_state, 2);
5175 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX
" (3): ",
5184 printf(
"normalized uri \"");
5213 static int HTPParserDecodingTest03(
void)
5217 uint8_t httpbuf1[] =
5218 "GET /abc%252fdef HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n"
5219 "GET /abc/def?ghi%252fjkl HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5220 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5233 double-decode-path: yes\n\
5234 double-decode-query: yes\n\
5242 const char *addr =
"4.3.2.1";
5243 memset(&ssn, 0,
sizeof(ssn));
5249 f->
proto = IPPROTO_TCP;
5255 for (u = 0; u < httplen1; u++) {
5266 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5275 if (htp_state == NULL) {
5276 printf(
"no http state: ");
5280 uint8_t ref1[] =
"/abc/def";
5281 size_t reflen =
sizeof(ref1) - 1;
5283 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5289 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5298 printf(
"normalized uri \"");
5307 uint8_t ref2[] =
"/abc/def?ghi/jkl";
5308 reflen =
sizeof(ref2) - 1;
5310 tx = HTPStateGetTx(htp_state, 1);
5316 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5325 printf(
"normalized uri \"");
5351 static int HTPParserDecodingTest04(
void)
5355 uint8_t httpbuf1[] =
5356 "GET /abc/def?a=http://www.abc.com/ HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5357 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5370 double-decode-path: yes\n\
5371 double-decode-query: yes\n\
5379 const char *addr =
"4.3.2.1";
5380 memset(&ssn, 0,
sizeof(ssn));
5386 f->
proto = IPPROTO_TCP;
5392 for (u = 0; u < httplen1; u++) {
5403 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5412 if (htp_state == NULL) {
5413 printf(
"no http state: ");
5417 uint8_t ref1[] =
"/abc/def?a=http://www.abc.com/";
5418 size_t reflen =
sizeof(ref1) - 1;
5420 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5426 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5435 printf(
"normalized uri \"");
5461 static int HTPParserDecodingTest05(
void)
5465 uint8_t httpbuf1[] =
5466 "GET /index?id=\\\"<script>alert(document.cookie)</script> HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5467 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5480 double-decode-path: yes\n\
5481 double-decode-query: yes\n\
5489 const char *addr =
"4.3.2.1";
5490 memset(&ssn, 0,
sizeof(ssn));
5496 f->
proto = IPPROTO_TCP;
5502 for (u = 0; u < httplen1; u++) {
5513 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5522 if (htp_state == NULL) {
5523 printf(
"no http state: ");
5527 uint8_t ref1[] =
"/index?id=\\\"<script>alert(document.cookie)</script>";
5528 size_t reflen =
sizeof(ref1) - 1;
5530 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5536 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5545 printf(
"normalized uri \"");
5571 static int HTPParserDecodingTest06(
void)
5575 uint8_t httpbuf1[] =
5576 "GET /put.php?ip=1.2.3.4&port=+6000 HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5577 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5590 double-decode-path: yes\n\
5591 double-decode-query: yes\n\
5599 const char *addr =
"4.3.2.1";
5600 memset(&ssn, 0,
sizeof(ssn));
5606 f->
proto = IPPROTO_TCP;
5612 for (u = 0; u < httplen1; u++) {
5623 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5632 if (htp_state == NULL) {
5633 printf(
"no http state: ");
5637 uint8_t ref1[] =
"/put.php?ip=1.2.3.4&port=+6000";
5638 size_t reflen =
sizeof(ref1) - 1;
5640 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5646 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5655 printf(
"normalized uri \"");
5681 static int HTPParserDecodingTest07(
void)
5685 uint8_t httpbuf1[] =
5686 "GET /put.php?ip=1.2.3.4&port=+6000 HTTP/1.1\r\nHost: www.domain.ltd\r\n\r\n";
5687 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
5700 double-decode-path: yes\n\
5701 double-decode-query: yes\n\
5702 query-plusspace-decode: yes\n\
5710 const char *addr =
"4.3.2.1";
5711 memset(&ssn, 0,
sizeof(ssn));
5717 f->
proto = IPPROTO_TCP;
5723 for (u = 0; u < httplen1; u++) {
5734 printf(
"toserver chunk %" PRIu32
" returned %" PRId32
", expected"
5743 if (htp_state == NULL) {
5744 printf(
"no http state: ");
5748 uint8_t ref1[] =
"/put.php?ip=1.2.3.4&port= 6000";
5749 size_t reflen =
sizeof(ref1) - 1;
5751 htp_tx_t *tx = HTPStateGetTx(htp_state, 0);
5757 printf(
"normalized uri len should be %"PRIuMAX
", is %"PRIuMAX,
5766 printf(
"normalized uri \"");