Coverage Report

Created: 2025-11-16 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata7/libhtp/htp/htp_connection_parser.c
Line
Count
Source
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
5.39k
void htp_connp_req_close(htp_connp_t *connp, const htp_time_t *timestamp) {
48
5.39k
    if (connp == NULL) return;
49
    
50
    // Update internal flags
51
5.39k
    if (connp->in_status != HTP_STREAM_ERROR)
52
5.19k
        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
5.39k
    htp_connp_req_data(connp, timestamp, NULL, 0);
57
5.39k
}
58
59
3.61k
void htp_connp_close(htp_connp_t *connp, const htp_time_t *timestamp) {
60
3.61k
    if (connp == NULL) return;
61
    
62
    // Close the underlying connection.
63
3.61k
    htp_conn_close(connp->conn, timestamp);
64
65
    // Update internal flags
66
3.61k
    if (connp->in_status != HTP_STREAM_ERROR)
67
3.60k
        connp->in_status = HTP_STREAM_CLOSED;
68
3.61k
    if (connp->out_status != HTP_STREAM_ERROR)
69
3.60k
        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
3.61k
    htp_connp_req_data(connp, timestamp, NULL, 0);
74
3.61k
    htp_connp_res_data(connp, timestamp, NULL, 0);   
75
3.61k
}
76
77
17.5k
htp_connp_t *htp_connp_create(htp_cfg_t *cfg) {
78
17.5k
    htp_connp_t *connp = calloc(1, sizeof (htp_connp_t));
79
17.5k
    if (connp == NULL) return NULL;
80
81
    // Use the supplied configuration structure
82
17.5k
    connp->cfg = cfg;
83
84
    // Create a new connection.
85
17.5k
    connp->conn = htp_conn_create();
86
17.5k
    if (connp->conn == NULL) {
87
0
        free(connp);
88
0
        return NULL;
89
0
    }
90
91
    // Request parsing
92
17.5k
    connp->in_state = htp_connp_REQ_IDLE;
93
17.5k
    connp->in_status = HTP_STREAM_NEW;
94
95
    // Response parsing
96
17.5k
    connp->out_state = htp_connp_RES_IDLE; 
97
17.5k
    connp->out_status = HTP_STREAM_NEW;
98
99
17.5k
    return connp;
100
17.5k
}
101
102
17.5k
void htp_connp_destroy(htp_connp_t *connp) {
103
17.5k
    if (connp == NULL) return;
104
    
105
17.5k
    if (connp->in_buf != NULL) {
106
3.22k
        free(connp->in_buf);
107
3.22k
    }
108
109
17.5k
    if (connp->out_buf != NULL) {
110
2.85k
        free(connp->out_buf);
111
2.85k
    }
112
113
17.5k
    htp_connp_destroy_decompressors(connp);
114
115
17.5k
    if (connp->put_file != NULL) {
116
5
        bstr_free(connp->put_file->filename);
117
5
        free(connp->put_file);
118
5
    }
119
120
17.5k
    if (connp->in_header) {
121
689
        bstr_free(connp->in_header);
122
689
        connp->in_header = NULL;
123
689
    }
124
17.5k
    if (connp->out_header) {
125
390
        bstr_free(connp->out_header);
126
390
        connp->out_header = NULL;
127
390
    }
128
17.5k
    free(connp);
129
17.5k
}
130
131
17.5k
void htp_connp_destroy_all(htp_connp_t *connp) {
132
17.5k
    if (connp == NULL) return;
133
134
    // Destroy connection
135
17.5k
    htp_conn_destroy(connp->conn);
136
17.5k
    connp->conn = NULL;
137
138
    // Destroy everything else
139
17.5k
    htp_connp_destroy(connp);
140
17.5k
}
141
142
17.5k
htp_conn_t *htp_connp_get_connection(const htp_connp_t *connp) {
143
17.5k
    if (connp == NULL) return NULL;
144
17.5k
    return connp->conn;
145
17.5k
}
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
915
htp_tx_t *htp_connp_get_out_tx(const htp_connp_t *connp) {
158
915
    if (connp == NULL) return NULL;
159
915
    return connp->out_tx;
160
915
}
161
162
2.40M
void *htp_connp_get_user_data(const htp_connp_t *connp) {
163
2.40M
    if (connp == NULL) return NULL;
164
2.40M
    return (void *)connp->user_data;
165
2.40M
}
166
167
248k
void htp_connp_in_reset(htp_connp_t *connp) {
168
248k
    if (connp == NULL) return;
169
248k
    connp->in_content_length = -1;
170
248k
    connp->in_body_data_left = -1;
171
248k
    connp->in_chunk_request_index = connp->in_chunk_count;
172
248k
}
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
17.5k
{
177
17.5k
    if (connp == NULL) return;
178
    
179
    // Check connection parser state first.
180
17.5k
    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
17.5k
    if (htp_conn_open(connp->conn, client_addr, client_port, server_addr, server_port, timestamp) != HTP_OK) {
186
0
        return;
187
0
    }
188
    
189
17.5k
    connp->in_status = HTP_STREAM_OPEN;
190
17.5k
    connp->out_status = HTP_STREAM_OPEN;
191
17.5k
}
192
193
17.5k
void htp_connp_set_user_data(htp_connp_t *connp, const void *user_data) {
194
17.5k
    if (connp == NULL) return;
195
17.5k
    connp->user_data = user_data;
196
17.5k
}
197
198
248k
htp_tx_t *htp_connp_tx_create(htp_connp_t *connp) {
199
248k
    if (connp == NULL) return NULL;
200
    
201
    // Detect pipelining.
202
248k
    if (htp_list_size(connp->conn->transactions) > connp->out_next_tx_index) {
203
168k
        connp->conn->flags |= HTP_CONN_PIPELINED;
204
168k
    }
205
248k
    if (connp->cfg->max_tx > 0 &&
206
248k
        htp_list_size(connp->conn->transactions) > connp->cfg->max_tx) {
207
47
        return NULL;
208
47
    }
209
210
248k
    htp_tx_t *tx = htp_tx_create(connp);
211
248k
    if (tx == NULL) return NULL;
212
213
248k
    connp->in_tx = tx;   
214
215
248k
    htp_connp_in_reset(connp);
216
217
248k
    return tx;
218
248k
}
219
220
/**
221
 * Removes references to the supplied transaction.
222
 *
223
 * @param[in] connp
224
 * @param[in] tx
225
 */
226
248k
void htp_connp_tx_remove(htp_connp_t *connp, htp_tx_t *tx) {
227
248k
    if (connp == NULL) return;
228
229
248k
    if (connp->in_tx == tx) {
230
8.43k
        connp->in_tx = NULL;
231
8.43k
    }
232
233
248k
    if (connp->out_tx == tx) {
234
5.74k
        connp->out_tx = NULL;
235
5.74k
    }
236
248k
}
237
238
/**
239
 * Removes all front NULL-ed transactions
240
 *
241
 * @param[in] connp
242
 * @return numbers of removed NULL transactions
243
 */
244
68.3k
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.3k
    size_t r = 0;
248
68.3k
    size_t nb = htp_list_size(connp->conn->transactions);
249
101k
    for (size_t i = 0; i < nb; i++) {
250
        // 0 and not i because at next iteration, we have removed the first
251
92.4k
        void * tx = htp_list_get(connp->conn->transactions, 0);
252
92.4k
        if (tx != NULL) {
253
58.8k
            break;
254
58.8k
        }
255
33.5k
        htp_list_shift(connp->conn->transactions);
256
33.5k
        r++;
257
33.5k
        connp->out_next_tx_index--;
258
33.5k
    }
259
68.3k
    return r;
260
68.3k
}