/src/suricata7/libhtp/htp/htp_connection_parser.c
Line | Count | Source (jump to first uncovered line) |
1 | | /*************************************************************************** |
2 | | * Copyright (c) 2009-2010 Open Information Security Foundation |
3 | | * Copyright (c) 2010-2013 Qualys, Inc. |
4 | | * All rights reserved. |
5 | | * |
6 | | * Redistribution and use in source and binary forms, with or without |
7 | | * modification, are permitted provided that the following conditions are |
8 | | * met: |
9 | | * |
10 | | * - Redistributions of source code must retain the above copyright |
11 | | * notice, this list of conditions and the following disclaimer. |
12 | | |
13 | | * - Redistributions in binary form must reproduce the above copyright |
14 | | * notice, this list of conditions and the following disclaimer in the |
15 | | * documentation and/or other materials provided with the distribution. |
16 | | |
17 | | * - Neither the name of the Qualys, Inc. nor the names of its |
18 | | * contributors may be used to endorse or promote products derived from |
19 | | * this software without specific prior written permission. |
20 | | * |
21 | | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
22 | | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
23 | | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
24 | | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
25 | | * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
26 | | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
27 | | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
28 | | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
29 | | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
30 | | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
31 | | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
32 | | ***************************************************************************/ |
33 | | |
34 | | /** |
35 | | * @file |
36 | | * @author Ivan Ristic <ivanr@webkreator.com> |
37 | | */ |
38 | | |
39 | | #include "htp_config_auto.h" |
40 | | |
41 | | #include "htp_private.h" |
42 | | |
43 | 0 | void htp_connp_clear_error(htp_connp_t *connp) { |
44 | 0 | connp->last_error = NULL; |
45 | 0 | } |
46 | | |
47 | 4.44k | void htp_connp_req_close(htp_connp_t *connp, const htp_time_t *timestamp) { |
48 | 4.44k | if (connp == NULL) return; |
49 | | |
50 | | // Update internal flags |
51 | 4.44k | if (connp->in_status != HTP_STREAM_ERROR) |
52 | 4.23k | connp->in_status = HTP_STREAM_CLOSED; |
53 | | |
54 | | // Call the parsers one last time, which will allow them |
55 | | // to process the events that depend on stream closure |
56 | 4.44k | htp_connp_req_data(connp, timestamp, NULL, 0); |
57 | 4.44k | } |
58 | | |
59 | 2.50k | void htp_connp_close(htp_connp_t *connp, const htp_time_t *timestamp) { |
60 | 2.50k | if (connp == NULL) return; |
61 | | |
62 | | // Close the underlying connection. |
63 | 2.50k | htp_conn_close(connp->conn, timestamp); |
64 | | |
65 | | // Update internal flags |
66 | 2.50k | if (connp->in_status != HTP_STREAM_ERROR) |
67 | 2.49k | connp->in_status = HTP_STREAM_CLOSED; |
68 | 2.50k | if (connp->out_status != HTP_STREAM_ERROR) |
69 | 2.49k | connp->out_status = HTP_STREAM_CLOSED; |
70 | | |
71 | | // Call the parsers one last time, which will allow them |
72 | | // to process the events that depend on stream closure |
73 | 2.50k | htp_connp_req_data(connp, timestamp, NULL, 0); |
74 | 2.50k | htp_connp_res_data(connp, timestamp, NULL, 0); |
75 | 2.50k | } |
76 | | |
77 | 16.4k | htp_connp_t *htp_connp_create(htp_cfg_t *cfg) { |
78 | 16.4k | htp_connp_t *connp = calloc(1, sizeof (htp_connp_t)); |
79 | 16.4k | if (connp == NULL) return NULL; |
80 | | |
81 | | // Use the supplied configuration structure |
82 | 16.4k | connp->cfg = cfg; |
83 | | |
84 | | // Create a new connection. |
85 | 16.4k | connp->conn = htp_conn_create(); |
86 | 16.4k | if (connp->conn == NULL) { |
87 | 0 | free(connp); |
88 | 0 | return NULL; |
89 | 0 | } |
90 | | |
91 | | // Request parsing |
92 | 16.4k | connp->in_state = htp_connp_REQ_IDLE; |
93 | 16.4k | connp->in_status = HTP_STREAM_NEW; |
94 | | |
95 | | // Response parsing |
96 | 16.4k | connp->out_state = htp_connp_RES_IDLE; |
97 | 16.4k | connp->out_status = HTP_STREAM_NEW; |
98 | | |
99 | 16.4k | return connp; |
100 | 16.4k | } |
101 | | |
102 | 16.4k | void htp_connp_destroy(htp_connp_t *connp) { |
103 | 16.4k | if (connp == NULL) return; |
104 | | |
105 | 16.4k | if (connp->in_buf != NULL) { |
106 | 3.24k | free(connp->in_buf); |
107 | 3.24k | } |
108 | | |
109 | 16.4k | if (connp->out_buf != NULL) { |
110 | 2.93k | free(connp->out_buf); |
111 | 2.93k | } |
112 | | |
113 | 16.4k | htp_connp_destroy_decompressors(connp); |
114 | | |
115 | 16.4k | if (connp->put_file != NULL) { |
116 | 5 | bstr_free(connp->put_file->filename); |
117 | 5 | free(connp->put_file); |
118 | 5 | } |
119 | | |
120 | 16.4k | if (connp->in_header) { |
121 | 712 | bstr_free(connp->in_header); |
122 | 712 | connp->in_header = NULL; |
123 | 712 | } |
124 | 16.4k | if (connp->out_header) { |
125 | 312 | bstr_free(connp->out_header); |
126 | 312 | connp->out_header = NULL; |
127 | 312 | } |
128 | 16.4k | free(connp); |
129 | 16.4k | } |
130 | | |
131 | 16.4k | void htp_connp_destroy_all(htp_connp_t *connp) { |
132 | 16.4k | if (connp == NULL) return; |
133 | | |
134 | | // Destroy connection |
135 | 16.4k | htp_conn_destroy(connp->conn); |
136 | 16.4k | connp->conn = NULL; |
137 | | |
138 | | // Destroy everything else |
139 | 16.4k | htp_connp_destroy(connp); |
140 | 16.4k | } |
141 | | |
142 | 16.4k | htp_conn_t *htp_connp_get_connection(const htp_connp_t *connp) { |
143 | 16.4k | if (connp == NULL) return NULL; |
144 | 16.4k | return connp->conn; |
145 | 16.4k | } |
146 | | |
147 | 0 | htp_tx_t *htp_connp_get_in_tx(const htp_connp_t *connp) { |
148 | 0 | if (connp == NULL) return NULL; |
149 | 0 | return connp->in_tx; |
150 | 0 | } |
151 | | |
152 | 0 | htp_log_t *htp_connp_get_last_error(const htp_connp_t *connp) { |
153 | 0 | if (connp == NULL) return NULL; |
154 | 0 | return connp->last_error; |
155 | 0 | } |
156 | | |
157 | 767 | htp_tx_t *htp_connp_get_out_tx(const htp_connp_t *connp) { |
158 | 767 | if (connp == NULL) return NULL; |
159 | 767 | return connp->out_tx; |
160 | 767 | } |
161 | | |
162 | 2.88M | void *htp_connp_get_user_data(const htp_connp_t *connp) { |
163 | 2.88M | if (connp == NULL) return NULL; |
164 | 2.88M | return (void *)connp->user_data; |
165 | 2.88M | } |
166 | | |
167 | 245k | void htp_connp_in_reset(htp_connp_t *connp) { |
168 | 245k | if (connp == NULL) return; |
169 | 245k | connp->in_content_length = -1; |
170 | 245k | connp->in_body_data_left = -1; |
171 | 245k | connp->in_chunk_request_index = connp->in_chunk_count; |
172 | 245k | } |
173 | | |
174 | | void htp_connp_open(htp_connp_t *connp, const char *client_addr, int client_port, const char *server_addr, |
175 | | int server_port, htp_time_t *timestamp) |
176 | 16.4k | { |
177 | 16.4k | if (connp == NULL) return; |
178 | | |
179 | | // Check connection parser state first. |
180 | 16.4k | if ((connp->in_status != HTP_STREAM_NEW) || (connp->out_status != HTP_STREAM_NEW)) { |
181 | 0 | htp_log(connp, HTP_LOG_MARK, HTP_LOG_ERROR, 0, "Connection is already open"); |
182 | 0 | return; |
183 | 0 | } |
184 | | |
185 | 16.4k | if (htp_conn_open(connp->conn, client_addr, client_port, server_addr, server_port, timestamp) != HTP_OK) { |
186 | 0 | return; |
187 | 0 | } |
188 | | |
189 | 16.4k | connp->in_status = HTP_STREAM_OPEN; |
190 | 16.4k | connp->out_status = HTP_STREAM_OPEN; |
191 | 16.4k | } |
192 | | |
193 | 16.4k | void htp_connp_set_user_data(htp_connp_t *connp, const void *user_data) { |
194 | 16.4k | if (connp == NULL) return; |
195 | 16.4k | connp->user_data = user_data; |
196 | 16.4k | } |
197 | | |
198 | 246k | htp_tx_t *htp_connp_tx_create(htp_connp_t *connp) { |
199 | 246k | if (connp == NULL) return NULL; |
200 | | |
201 | | // Detect pipelining. |
202 | 246k | if (htp_list_size(connp->conn->transactions) > connp->out_next_tx_index) { |
203 | 165k | connp->conn->flags |= HTP_CONN_PIPELINED; |
204 | 165k | } |
205 | 246k | if (connp->cfg->max_tx > 0 && |
206 | 246k | htp_list_size(connp->conn->transactions) > connp->cfg->max_tx) { |
207 | 48 | return NULL; |
208 | 48 | } |
209 | | |
210 | 245k | htp_tx_t *tx = htp_tx_create(connp); |
211 | 245k | if (tx == NULL) return NULL; |
212 | | |
213 | 245k | connp->in_tx = tx; |
214 | | |
215 | 245k | htp_connp_in_reset(connp); |
216 | | |
217 | 245k | return tx; |
218 | 245k | } |
219 | | |
220 | | /** |
221 | | * Removes references to the supplied transaction. |
222 | | * |
223 | | * @param[in] connp |
224 | | * @param[in] tx |
225 | | */ |
226 | 245k | void htp_connp_tx_remove(htp_connp_t *connp, htp_tx_t *tx) { |
227 | 245k | if (connp == NULL) return; |
228 | | |
229 | 245k | if (connp->in_tx == tx) { |
230 | 8.85k | connp->in_tx = NULL; |
231 | 8.85k | } |
232 | | |
233 | 245k | if (connp->out_tx == tx) { |
234 | 5.52k | connp->out_tx = NULL; |
235 | 5.52k | } |
236 | 245k | } |
237 | | |
238 | | /** |
239 | | * Removes all front NULL-ed transactions |
240 | | * |
241 | | * @param[in] connp |
242 | | * @return numbers of removed NULL transactions |
243 | | */ |
244 | 68.7k | size_t htp_connp_tx_freed(htp_connp_t *connp) { |
245 | | // Transactions first got freed and NULLed |
246 | | // Now, we can recycle the space that hold them by shifting the list |
247 | 68.7k | size_t r = 0; |
248 | 68.7k | size_t nb = htp_list_size(connp->conn->transactions); |
249 | 99.1k | for (size_t i = 0; i < nb; i++) { |
250 | | // 0 and not i because at next iteration, we have removed the first |
251 | 90.1k | void * tx = htp_list_get(connp->conn->transactions, 0); |
252 | 90.1k | if (tx != NULL) { |
253 | 59.7k | break; |
254 | 59.7k | } |
255 | 30.3k | htp_list_shift(connp->conn->transactions); |
256 | 30.3k | r++; |
257 | 30.3k | connp->out_next_tx_index--; |
258 | 30.3k | } |
259 | 68.7k | return r; |
260 | 68.7k | } |