Codebase list libhtp / 107e44a
New upstream version 0.5.32 Sascha Steinbiss 4 years ago
10 changed file(s) with 204 addition(s) and 46 deletion(s). Raw diff Collapse all Expand all
0 0.5.32 (13 December 2019)
1 --------------------------
2
3 - bug fixes around pipelining
4
05 0.5.31 (24 September 2019)
16 --------------------------
27
00 # This file is intended to be sourced by sh
1 PKG_VERSION=0.5.31
1 PKG_VERSION=0.5.32
4343 connp->last_error = NULL;
4444 }
4545
46 void htp_connp_req_close(htp_connp_t *connp, const htp_time_t *timestamp) {
47 if (connp == NULL) return;
48
49 // Update internal flags
50 if (connp->in_status != HTP_STREAM_ERROR)
51 connp->in_status = HTP_STREAM_CLOSED;
52
53 // Call the parsers one last time, which will allow them
54 // to process the events that depend on stream closure
55 htp_connp_req_data(connp, timestamp, NULL, 0);
56 }
57
4658 void htp_connp_close(htp_connp_t *connp, const htp_time_t *timestamp) {
4759 if (connp == NULL) return;
4860
5656 * @param[in] timestamp Optional.
5757 */
5858 void htp_connp_close(htp_connp_t *connp, const htp_time_t *timestamp);
59 void htp_connp_req_close(htp_connp_t *connp, const htp_time_t *timestamp);
5960
6061 /**
6162 * Creates a new connection parser using the provided configuration. Because
827827 }
828828
829829 htp_status_t htp_connp_REQ_FINALIZE(htp_connp_t *connp) {
830 size_t bytes_left = connp->in_current_len - connp->in_current_read_offset;
831
832 if (bytes_left > 0) {
833 // If we have more bytes
834 // Either it is request pipelining
835 // Or we interpret it as body data
836 int64_t pos = connp->in_current_read_offset;
837 int64_t mstart = 0;
838 // skip past leading whitespace. IIS allows this
839 while ((pos < connp->in_current_len) && htp_is_space(connp->in_current_data[pos]))
840 pos++;
841 if (pos < connp->in_current_len) {
842 mstart = pos;
843 // The request method starts at the beginning of the
844 // line and ends with the first whitespace character.
845 while ((pos < connp->in_current_len) && (!htp_is_space(connp->in_current_data[pos])))
846 pos++;
847
848 int methodi = HTP_M_UNKNOWN;
849 bstr *method = bstr_dup_mem(connp->in_current_data + mstart, pos - mstart);
850 if (method) {
851 methodi = htp_convert_method_to_number(method);
852 bstr_free(method);
853 }
854 if (methodi == HTP_M_UNKNOWN) {
855 // Interpret remaining bytes as body data
856 htp_log(connp, HTP_LOG_MARK, HTP_LOG_WARNING, 0, "Unexpected request body");
857 connp->in_tx->request_progress = HTP_REQUEST_BODY;
858 connp->in_state = htp_connp_REQ_BODY_IDENTITY;
859 connp->in_body_data_left = bytes_left;
860 return HTP_OK;
861 }
862 }
863 }
830 if (connp->in_status != HTP_STREAM_CLOSED) {
831 IN_PEEK_NEXT(connp);
832 if (connp->in_next_byte == -1) {
833 return htp_tx_state_request_complete(connp->in_tx);
834 }
835 if (connp->in_next_byte != LF || connp->in_current_consume_offset >= connp->in_current_read_offset) {
836 for (;;) {//;i < max_read; i++) {
837 IN_COPY_BYTE_OR_RETURN(connp);
838 // Have we reached the end of the line? For some reason
839 // we can't test after IN_COPY_BYTE_OR_RETURN */
840 if (connp->in_next_byte == LF)
841 break;
842 }
843 }
844 }
845
846 unsigned char *data;
847 size_t len;
848 if (htp_connp_req_consolidate_data(connp, &data, &len) != HTP_OK) {
849 return HTP_ERROR;
850 }
851 #ifdef HTP_DEBUG
852 fprint_raw_data(stderr, "PROBING request finalize", data, len);
853 #endif
854 if (len == 0) {
855 //closing
856 return htp_tx_state_request_complete(connp->in_tx);
857 }
858
859 size_t pos = 0;
860 size_t mstart = 0;
861 // skip past leading whitespace. IIS allows this
862 while ((pos < len) && htp_is_space(data[pos]))
863 pos++;
864 if (pos)
865 mstart = pos;
866 // The request method starts at the beginning of the
867 // line and ends with the first whitespace character.
868 while ((pos < len) && (!htp_is_space(data[pos])))
869 pos++;
870
871 if (pos > mstart) {
872 int methodi = HTP_M_UNKNOWN;
873 bstr *method = bstr_dup_mem(data + mstart, pos - mstart);
874 if (method) {
875 methodi = htp_convert_method_to_number(method);
876 bstr_free(method);
877 }
878 if (methodi == HTP_M_UNKNOWN) {
879 // Interpret remaining bytes as body data
880 htp_log(connp, HTP_LOG_MARK, HTP_LOG_WARNING, 0, "Unexpected request body");
881 htp_status_t rc = htp_tx_req_process_body_data_ex(connp->in_tx, data, len);
882 htp_connp_req_clear_buffer(connp);
883 return rc;
884 }
885 }
886 //else
887 //unread last end of line so that REQ_LINE works
888 if (connp->in_current_read_offset < (int64_t)len) {
889 connp->in_current_read_offset=0;
890 } else {
891 connp->in_current_read_offset-=len;
892 }
893 if (connp->in_current_read_offset < connp->in_current_consume_offset) {
894 connp->in_current_consume_offset=connp->in_current_read_offset;
895 }
896
864897 return htp_tx_state_request_complete(connp->in_tx);
865898 }
866899
10691069 }
10701070
10711071 htp_status_t htp_connp_RES_FINALIZE(htp_connp_t *connp) {
1072 int bytes_left = connp->out_current_len - connp->out_current_read_offset;
1073 unsigned char * data = connp->out_current_data + connp->out_current_read_offset;
1074
1075 if (bytes_left > 0 &&
1076 htp_treat_response_line_as_body(data, bytes_left)) {
1072 if (connp->out_status != HTP_STREAM_CLOSED) {
1073 OUT_PEEK_NEXT(connp);
1074 if (connp->out_next_byte == -1) {
1075 return htp_tx_state_response_complete_ex(connp->out_tx, 0);
1076 }
1077 if (connp->out_next_byte != LF || connp->out_current_consume_offset >= connp->out_current_read_offset) {
1078 for (;;) {//;i < max_read; i++) {
1079 OUT_COPY_BYTE_OR_RETURN(connp);
1080 // Have we reached the end of the line? For some reason
1081 // we can't test after IN_COPY_BYTE_OR_RETURN */
1082 if (connp->out_next_byte == LF)
1083 break;
1084 }
1085 }
1086 }
1087 size_t bytes_left;
1088 unsigned char * data;
1089
1090 if (htp_connp_res_consolidate_data(connp, &data, &bytes_left) != HTP_OK) {
1091 return HTP_ERROR;
1092 }
1093 #ifdef HTP_DEBUG
1094 fprint_raw_data(stderr, "PROBING response finalize", data, bytes_left);
1095 #endif
1096 if (bytes_left == 0) {
1097 //closing
1098 return htp_tx_state_response_complete_ex(connp->out_tx, 0);
1099 }
1100
1101 if (htp_treat_response_line_as_body(data, bytes_left)) {
10771102 // Interpret remaining bytes as body data
10781103 htp_log(connp, HTP_LOG_MARK, HTP_LOG_WARNING, 0, "Unexpected response body");
1079 connp->out_current_read_offset += bytes_left;
1080 connp->out_current_consume_offset += bytes_left;
1081 connp->out_stream_offset += bytes_left;
1082 connp->out_body_data_left -= bytes_left;
10831104 htp_status_t rc = htp_tx_res_process_body_data_ex(connp->out_tx, data, bytes_left);
1105 htp_connp_res_clear_buffer(connp);
10841106 return rc;
10851107 }
10861108
1109 //unread last end of line so that RES_LINE works
1110 if (connp->out_current_read_offset < (int64_t)bytes_left) {
1111 connp->out_current_read_offset=0;
1112 } else {
1113 connp->out_current_read_offset-=bytes_left;
1114 }
1115 if (connp->out_current_read_offset < connp->out_current_consume_offset) {
1116 connp->out_current_consume_offset=connp->out_current_read_offset;
1117 }
10871118 return htp_tx_state_response_complete_ex(connp->out_tx, 0 /* not hybrid mode */);
10881119 }
10891120
11111142 connp->out_tx = htp_list_get(connp->conn->transactions, connp->out_next_tx_index);
11121143 if (connp->out_tx == NULL) {
11131144 htp_log(connp, HTP_LOG_MARK, HTP_LOG_ERROR, 0, "Unable to match response to request");
1145 // finalize dangling request waiting for next request or body
1146 if (connp->in_state == htp_connp_REQ_FINALIZE) {
1147 htp_tx_state_request_complete(connp->in_tx);
1148 }
11141149 connp->out_tx = htp_connp_tx_create(connp);
11151150 if (connp->out_tx == NULL) {
11161151 return HTP_ERROR;
33 Content-Type: application/x-www-form-urlencoded
44
55 login=foo&password=bar
6
67 <<<
78 HTTP/1.1 200 OK
89 Content-Length: 0
0 >>>
1 GET /?p=%20 HTTP/1.1
2 User-Agent: Mozilla
3
4 G
5 >>>
6 ET /?p=%21 HTTP/1.1
7 User-Agent: Mozilla
8
0 >>>
1 GET /?p=%20 HTTP/1.1
2 User-Agent: Mozilla
3
4 GET /?p=%21 HTTP/1.1
5 User-Agent: Mozilla
6
7 <<<
8 HTTP/1.0 200 OK
9 Date: Mon, 31 Aug 2009 20:25:50 GMT
10 Server: Apache
11 Connection: close
12 Content-Type: text/html
13 Content-Length: 14
14
15 Hello World!
16 H
17 <<<
18 TTP/1.0 200 OK
19 Date: Mon, 31 Aug 2009 20:25:50 GMT
20 Server: Apache
21 Connection: close
22 Content-Type: text/html
23 Content-Length: 13
24
25 Hello People!
14821482 htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 1);
14831483 ASSERT_TRUE(tx != NULL);
14841484
1485 ASSERT_EQ(1, tx->request_ignored_lines);
1485 /*part of previous request body ASSERT_EQ(1, tx->request_ignored_lines);*/
14861486 }
14871487
14881488 TEST_F(ConnectionParsing, PostNoBody) {
15931593 htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0);
15941594 ASSERT_TRUE(tx != NULL);
15951595
1596 ASSERT_EQ(HTP_REQUEST_COMPLETE, tx->request_progress);
1596 //error first ASSERT_EQ(HTP_REQUEST_COMPLETE, tx->request_progress);
15971597 ASSERT_EQ(HTP_RESPONSE_HEADERS, tx->response_progress);
15981598 }
15991599
20312031 ASSERT_EQ(68, tx->response_entity_len);
20322032 }
20332033 #endif
2034
2035 TEST_F(ConnectionParsing, RequestsCut) {
2036 int rc = test_run(home, "97-requests-cut.t", cfg, &connp);
2037 ASSERT_GE(rc, 0);
2038
2039 ASSERT_EQ(2, htp_list_size(connp->conn->transactions));
2040 htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0);
2041 ASSERT_TRUE(tx != NULL);
2042 ASSERT_EQ(0, bstr_cmp_c(tx->request_method, "GET"));
2043 ASSERT_EQ(HTP_REQUEST_COMPLETE, tx->request_progress);
2044
2045 tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 1);
2046 ASSERT_TRUE(tx != NULL);
2047 ASSERT_EQ(0, bstr_cmp_c(tx->request_method, "GET"));
2048 ASSERT_EQ(HTP_REQUEST_COMPLETE, tx->request_progress);
2049 }
2050
2051 TEST_F(ConnectionParsing, ResponsesCut) {
2052 int rc = test_run(home, "98-responses-cut.t", cfg, &connp);
2053 ASSERT_GE(rc, 0);
2054
2055 ASSERT_EQ(2, htp_list_size(connp->conn->transactions));
2056 htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0);
2057 ASSERT_TRUE(tx != NULL);
2058 ASSERT_EQ(0, bstr_cmp_c(tx->request_method, "GET"));
2059 ASSERT_EQ(HTP_REQUEST_COMPLETE, tx->request_progress);
2060 ASSERT_EQ(200, tx->response_status_number);
2061 ASSERT_EQ(HTP_RESPONSE_COMPLETE, tx->response_progress);
2062
2063 tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 1);
2064 ASSERT_TRUE(tx != NULL);
2065 ASSERT_EQ(0, bstr_cmp_c(tx->request_method, "GET"));
2066 ASSERT_EQ(HTP_REQUEST_COMPLETE, tx->request_progress);
2067 ASSERT_EQ(200, tx->response_status_number);
2068 ASSERT_EQ(HTP_RESPONSE_COMPLETE, tx->response_progress);
2069 }