Coverage Report

Created: 2025-11-09 06:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libhtp/htp/htp_response.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
65.3k
#define OUT_TEST_NEXT_BYTE_OR_RETURN(X) \
44
65.3k
if ((X)->out_current_read_offset >= (X)->out_current_len) { \
45
23.9k
    return HTP_DATA; \
46
23.9k
}
47
48
2.91M
#define OUT_PEEK_NEXT(X) \
49
2.91M
if ((X)->out_current_read_offset >= (X)->out_current_len) { \
50
18.7k
    (X)->out_next_byte = -1; \
51
2.89M
} else { \
52
2.89M
    (X)->out_next_byte = (X)->out_current_data[(X)->out_current_read_offset]; \
53
2.89M
}
54
55
#define OUT_NEXT_BYTE(X) \
56
if ((X)->out_current_read_offset < (X)->out_current_len) { \
57
    (X)->out_next_byte = (X)->out_current_data[(X)->out_current_read_offset]; \
58
    (X)->out_current_read_offset++; \
59
    (X)->out_current_consume_offset++; \
60
    (X)->out_stream_offset++; \
61
} else { \
62
    (X)->out_next_byte = -1; \
63
}
64
65
0
#define OUT_NEXT_BYTE_OR_RETURN(X) \
66
0
if ((X)->out_current_read_offset < (X)->out_current_len) { \
67
0
    (X)->out_next_byte = (X)->out_current_data[(X)->out_current_read_offset]; \
68
0
    (X)->out_current_read_offset++; \
69
0
    (X)->out_current_consume_offset++; \
70
0
    (X)->out_stream_offset++; \
71
0
} else { \
72
0
    return HTP_DATA; \
73
0
}
74
75
43.8M
#define OUT_COPY_BYTE_OR_RETURN(X) \
76
43.8M
if ((X)->out_current_read_offset < (X)->out_current_len) { \
77
43.8M
    (X)->out_next_byte = (X)->out_current_data[(X)->out_current_read_offset]; \
78
43.8M
    (X)->out_current_read_offset++; \
79
43.8M
    (X)->out_stream_offset++; \
80
43.8M
} else { \
81
13.1k
    return HTP_DATA_BUFFER; \
82
13.1k
}
83
84
62.1k
#define REQUEST_URI_NOT_SEEN "/libhtp::request_uri_not_seen"
85
86
/**
87
 * Sends outstanding connection data to the currently active data receiver hook.
88
 *
89
 * @param[in] connp
90
 * @param[in] is_last
91
 * @return HTP_OK, or a value returned from a callback.
92
 */
93
217k
static htp_status_t htp_connp_res_receiver_send_data(htp_connp_t *connp, int is_last) {
94
217k
    if (connp->out_data_receiver_hook == NULL) return HTP_OK;
95
96
169k
    htp_tx_data_t d;
97
169k
    d.tx = connp->out_tx;
98
169k
    d.data = connp->out_current_data + connp->out_current_receiver_offset;
99
169k
    d.len = connp->out_current_read_offset - connp->out_current_receiver_offset;
100
169k
    d.is_last = is_last;
101
102
169k
    htp_status_t rc = htp_hook_run_all(connp->out_data_receiver_hook, &d);
103
169k
    if (rc != HTP_OK) return rc;
104
105
169k
    connp->out_current_receiver_offset = connp->out_current_read_offset;
106
107
169k
    return HTP_OK;
108
169k
}
109
110
/**
111
 * Finalizes an existing data receiver hook by sending any outstanding data to it. The
112
 * hook is then removed so that it receives no more data.
113
 *
114
 * @param[in] connp
115
 * @return HTP_OK, or a value returned from a callback.
116
 */
117
238k
htp_status_t htp_connp_res_receiver_finalize_clear(htp_connp_t *connp) {
118
238k
    if (connp->out_data_receiver_hook == NULL) return HTP_OK;
119
120
165k
    htp_status_t rc = htp_connp_res_receiver_send_data(connp, 1 /* last */);
121
122
165k
    connp->out_data_receiver_hook = NULL;
123
124
165k
    return rc;
125
238k
}
126
127
/**
128
 * Configures the data receiver hook. If there is a previous hook, it will be finalized and cleared.
129
 *
130
 * @param[in] connp
131
 * @param[in] data_receiver_hook
132
 * @return HTP_OK, or a value returned from a callback.
133
 */
134
165k
static htp_status_t htp_connp_res_receiver_set(htp_connp_t *connp, htp_hook_t *data_receiver_hook) {
135
165k
    htp_status_t rc = htp_connp_res_receiver_finalize_clear(connp);
136
137
165k
    connp->out_data_receiver_hook = data_receiver_hook;
138
165k
    connp->out_current_receiver_offset = connp->out_current_read_offset;
139
140
165k
    return rc;
141
165k
}
142
143
/**
144
 * Handles request parser state changes. At the moment, this function is used only
145
 * to configure data receivers, which are sent raw connection data.
146
 *
147
 * @param[in] connp
148
 * @return HTP_OK, or a value returned from a callback.
149
 */
150
2.53M
static htp_status_t htp_res_handle_state_change(htp_connp_t *connp) {
151
2.53M
    if (connp->out_state_previous == connp->out_state) return HTP_OK;
152
153
591k
    if (connp->out_state == htp_connp_RES_HEADERS) {
154
165k
        htp_status_t rc = HTP_OK;
155
156
165k
        switch (connp->out_tx->response_progress) {
157
165k
            case HTP_RESPONSE_HEADERS:
158
165k
                rc = htp_connp_res_receiver_set(connp, connp->out_tx->cfg->hook_response_header_data);
159
165k
                break;
160
161
0
            case HTP_RESPONSE_TRAILER:
162
0
                rc = htp_connp_res_receiver_set(connp, connp->out_tx->cfg->hook_response_trailer_data);
163
0
                break;
164
165
0
            default:
166
                // Do nothing; receivers are currently used only for header blocks.
167
0
                break;
168
165k
        }
169
170
165k
        if (rc != HTP_OK) return rc;
171
165k
    }
172
173
    // Same comment as in htp_req_handle_state_change(). Below is a copy.
174
175
    // Initially, I had the finalization of raw data sending here, but that
176
    // caused the last REQUEST_HEADER_DATA hook to be invoked after the
177
    // REQUEST_HEADERS hook -- which I thought made no sense. For that reason,
178
    // the finalization is now initiated from the request header processing code,
179
    // which is less elegant but provides a better user experience. Having some
180
    // (or all) hooks to be invoked on state change might work better.
181
182
591k
    connp->out_state_previous = connp->out_state;
183
184
591k
    return HTP_OK;
185
591k
}
186
187
/**
188
 * If there is any data left in the outbound data chunk, this function will preserve
189
 * it for later consumption. The maximum amount accepted for buffering is controlled
190
 * by htp_config_t::field_limit_hard.
191
 *
192
 * @param[in] connp
193
 * @return HTP_OK, or HTP_ERROR on fatal failure.
194
 */
195
28.2k
static htp_status_t htp_connp_res_buffer(htp_connp_t *connp) {
196
28.2k
    if (connp->out_current_data == NULL) return HTP_OK;
197
    
198
25.4k
    unsigned char *data = connp->out_current_data + connp->out_current_consume_offset;
199
25.4k
    size_t len = connp->out_current_read_offset - connp->out_current_consume_offset;
200
201
    // Check the hard (buffering) limit.
202
203
25.4k
    size_t newlen = connp->out_buf_size + len;   
204
205
    // When calculating the size of the buffer, take into account the
206
    // space we're using for the response header buffer.
207
25.4k
    if (connp->out_header != NULL) {
208
3.18k
        newlen += bstr_len(connp->out_header);
209
3.18k
    }
210
211
25.4k
    if (newlen > connp->out_tx->cfg->field_limit_hard) {
212
35
        htp_log(connp, HTP_LOG_MARK, HTP_LOG_ERROR, 0, "Response the buffer limit: size %zd limit %zd.",
213
35
                newlen, connp->out_tx->cfg->field_limit_hard);
214
35
        return HTP_ERROR;
215
35
    }
216
217
    // Copy the data remaining in the buffer.
218
219
25.3k
    if (connp->out_buf == NULL) {
220
11.2k
        connp->out_buf = malloc(len);
221
11.2k
        if (connp->out_buf == NULL) return HTP_ERROR;
222
11.2k
        memcpy(connp->out_buf, data, len);
223
11.2k
        connp->out_buf_size = len;
224
14.1k
    } else {
225
14.1k
        size_t newsize = connp->out_buf_size + len;
226
14.1k
        unsigned char *newbuf = realloc(connp->out_buf, newsize);
227
14.1k
        if (newbuf == NULL) return HTP_ERROR;
228
14.1k
        connp->out_buf = newbuf;
229
14.1k
        memcpy(connp->out_buf + connp->out_buf_size, data, len);
230
14.1k
        connp->out_buf_size = newsize;
231
14.1k
    }
232
233
    // Reset the consumer position.
234
25.3k
    connp->out_current_consume_offset = connp->out_current_read_offset;
235
236
25.3k
    return HTP_OK;
237
25.3k
}
238
239
/**
240
 * Returns to the caller the memory region that should be processed next. This function
241
 * hides away the buffering process from the rest of the code, allowing it to work with
242
 * non-buffered data that's in the outbound chunk, or buffered data that's in our structures.
243
 *
244
 * @param[in] connp
245
 * @param[out] data
246
 * @param[out] len
247
 * @return HTP_OK
248
 */
249
2.65M
static htp_status_t htp_connp_res_consolidate_data(htp_connp_t *connp, unsigned char **data, size_t *len) {    
250
2.65M
    if (connp->out_buf == NULL) {
251
        // We do not have any data buffered; point to the current data chunk.
252
2.64M
        *data = connp->out_current_data + connp->out_current_consume_offset;
253
2.64M
        *len = connp->out_current_read_offset - connp->out_current_consume_offset;
254
2.64M
    } else {
255
        // We do have data in the buffer. Add data from the current
256
        // chunk, and point to the consolidated buffer.
257
13.2k
        if (htp_connp_res_buffer(connp) != HTP_OK) {
258
11
            return HTP_ERROR;
259
11
        }
260
261
13.2k
        *data = connp->out_buf;
262
13.2k
        *len = connp->out_buf_size;
263
13.2k
    }
264
265
2.65M
    return HTP_OK;
266
2.65M
}
267
268
/**
269
 * Clears buffered outbound data and resets the consumer position to the reader position.
270
 *
271
 * @param[in] connp
272
 */
273
2.60M
static void htp_connp_res_clear_buffer(htp_connp_t *connp) {
274
2.60M
    connp->out_current_consume_offset = connp->out_current_read_offset;
275
276
2.60M
    if (connp->out_buf != NULL) {
277
10.5k
        free(connp->out_buf);
278
10.5k
        connp->out_buf = NULL;
279
10.5k
        connp->out_buf_size = 0;
280
10.5k
    }
281
2.60M
}
282
283
/**
284
 * Consumes bytes until the end of the current line.
285
 *
286
 * @param[in] connp
287
 * @returns HTP_OK on state change, HTP_ERROR on error, or HTP_DATA when more data is needed.
288
 */
289
0
htp_status_t htp_connp_RES_BODY_CHUNKED_DATA_END(htp_connp_t *connp) {
290
    // TODO We shouldn't really see anything apart from CR and LF,
291
    //      so we should warn about anything else.
292
0
    if (connp->out_status == HTP_STREAM_CLOSED) {
293
0
        connp->out_state = htp_connp_RES_FINALIZE;
294
        // Sends close signal to decompressors
295
0
        htp_status_t rc = htp_tx_res_process_body_data_ex(connp->out_tx, NULL, 0);
296
0
        return rc;
297
0
    }
298
299
0
    for (;;) {
300
0
        OUT_NEXT_BYTE_OR_RETURN(connp);
301
302
0
        connp->out_tx->response_message_len++;
303
304
0
        if (connp->out_next_byte == LF) {
305
0
            connp->out_state = htp_connp_RES_BODY_CHUNKED_LENGTH;
306
307
0
            return HTP_OK;
308
0
        }
309
0
    }
310
311
0
    return HTP_ERROR;
312
0
}
313
314
/**
315
 * Processes a chunk of data.
316
 *
317
 * @param[in] connp
318
 * @returns HTP_OK on state change, HTP_ERROR on error, or HTP_DATA when more data is needed.
319
 */
320
0
htp_status_t htp_connp_RES_BODY_CHUNKED_DATA(htp_connp_t *connp) {
321
0
    size_t bytes_to_consume;
322
323
    // Determine how many bytes we can consume.
324
0
    if (connp->out_current_len - connp->out_current_read_offset >= connp->out_chunked_length) {
325
0
        bytes_to_consume = connp->out_chunked_length;
326
0
    } else {
327
0
        bytes_to_consume = connp->out_current_len - connp->out_current_read_offset;
328
0
    }
329
330
0
    if (connp->out_status == HTP_STREAM_CLOSED) {
331
0
        connp->out_state = htp_connp_RES_FINALIZE;
332
        // Sends close signal to decompressors
333
0
        htp_status_t rc = htp_tx_res_process_body_data_ex(connp->out_tx, NULL, 0);
334
0
        return rc;
335
0
    }
336
0
    if (bytes_to_consume == 0) return HTP_DATA;
337
338
    // Consume the data.
339
0
    htp_status_t rc = htp_tx_res_process_body_data_ex(connp->out_tx, connp->out_current_data + connp->out_current_read_offset, bytes_to_consume);
340
0
    if (rc != HTP_OK) return rc;
341
342
    // Adjust the counters.
343
0
    connp->out_current_read_offset += bytes_to_consume;
344
0
    connp->out_current_consume_offset += bytes_to_consume;
345
0
    connp->out_stream_offset += bytes_to_consume;
346
0
    connp->out_chunked_length -= bytes_to_consume;
347
348
    // Have we seen the entire chunk?
349
0
    if (connp->out_chunked_length == 0) {
350
0
        connp->out_state = htp_connp_RES_BODY_CHUNKED_DATA_END;
351
0
        return HTP_OK;
352
0
    }
353
354
0
    return HTP_DATA;
355
0
}
356
357
0
static inline int is_chunked_ctl_char(const unsigned char c) {
358
0
    switch (c) {
359
0
        case 0x0d:
360
0
        case 0x0a:
361
0
        case 0x20:
362
0
        case 0x09:
363
0
        case 0x0b:
364
0
        case 0x0c:
365
0
            return 1;
366
0
        default:
367
0
            return 0;
368
0
    }
369
0
}
370
371
/**
372
 * Peeks ahead into the data to try to see if it starts with a valid Chunked
373
 * length field.
374
 *
375
 * @returns 1 if it looks valid, 0 if it looks invalid
376
 */
377
0
static inline int data_probe_chunk_length(htp_connp_t *connp) {
378
0
    unsigned char *data = connp->out_current_data + connp->out_current_consume_offset;
379
0
    size_t len = connp->out_current_read_offset - connp->out_current_consume_offset;
380
381
0
    size_t i = 0;
382
0
    while (i < len) {
383
0
        unsigned char c = data[i];
384
385
0
        if (is_chunked_ctl_char(c)) {
386
            // ctl char, still good.
387
0
        } else if (isdigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) {
388
            // real chunklen char
389
0
            return 1;
390
0
        } else {
391
            // leading junk, bad
392
0
            return 0;
393
0
        }
394
0
        i++;
395
0
    }
396
0
    return 1;
397
0
}
398
399
/**
400
 * Extracts chunk length.
401
 *
402
 * @param[in] connp
403
 * @returns HTP_OK on state change, HTP_ERROR on error, or HTP_DATA when more data is needed.
404
 */
405
0
htp_status_t htp_connp_RES_BODY_CHUNKED_LENGTH(htp_connp_t *connp) {
406
0
    if (connp->out_status == HTP_STREAM_CLOSED) {
407
0
        connp->out_state = htp_connp_RES_FINALIZE;
408
        // Sends close signal to decompressors
409
0
        htp_status_t rc = htp_tx_res_process_body_data_ex(connp->out_tx, NULL, 0);
410
0
        return rc;
411
0
    }
412
413
0
    for (;;) {
414
0
        OUT_COPY_BYTE_OR_RETURN(connp);
415
416
        // Have we reached the end of the line? Or is this not chunked after all?
417
0
        if (connp->out_next_byte == LF ||
418
0
                (!is_chunked_ctl_char((unsigned char) connp->out_next_byte) && !data_probe_chunk_length(connp) && connp->out_buf == NULL)) {
419
0
            unsigned char *data;
420
0
            size_t len;
421
422
0
            if (htp_connp_res_consolidate_data(connp, &data, &len) != HTP_OK) {
423
0
                return HTP_ERROR;
424
0
            }
425
426
0
            connp->out_tx->response_message_len += len;
427
428
            #ifdef HTP_DEBUG
429
            fprint_raw_data(stderr, "Chunk length line", data, len);
430
            #endif
431
432
0
            int chunk_ext = 0;
433
0
            connp->out_chunked_length = htp_parse_chunked_length(data, len, &chunk_ext);
434
0
            if (chunk_ext == 1) {
435
0
                htp_log(connp, HTP_LOG_MARK, HTP_LOG_WARNING, 0, "Request chunk extension");
436
0
            }
437
            // empty chunk length line, lets try to continue
438
0
            if (connp->out_chunked_length == -1004) {
439
0
                connp->out_current_consume_offset = connp->out_current_read_offset;
440
0
                continue;
441
0
            }
442
0
            if (connp->out_chunked_length < 0) {
443
                // reset out_current_read_offset so htp_connp_RES_BODY_IDENTITY_STREAM_CLOSE
444
                // doesn't miss the first bytes
445
446
0
                if (len > (size_t)connp->out_current_read_offset) {
447
0
                    connp->out_current_read_offset = 0;
448
0
                } else {
449
0
                    connp->out_current_read_offset -= len;
450
0
                }
451
452
0
                connp->out_state = htp_connp_RES_BODY_IDENTITY_STREAM_CLOSE;
453
0
                connp->out_tx->response_transfer_coding = HTP_CODING_IDENTITY;
454
455
0
                htp_log(connp, HTP_LOG_MARK, HTP_LOG_ERROR, 0,
456
0
                        "Response chunk encoding: Invalid chunk length: %"PRId64"",
457
0
                        connp->out_chunked_length);
458
0
                return HTP_OK;
459
0
            }
460
0
            htp_connp_res_clear_buffer(connp);
461
462
            // Handle chunk length
463
0
            if (connp->out_chunked_length > 0) {
464
                // More data available
465
0
                connp->out_state = htp_connp_RES_BODY_CHUNKED_DATA;
466
0
            } else if (connp->out_chunked_length == 0) {
467
                // End of data
468
0
                connp->out_state = htp_connp_RES_HEADERS;
469
0
                connp->out_tx->response_progress = HTP_RESPONSE_TRAILER;
470
0
            }
471
472
0
            return HTP_OK;
473
0
        }
474
0
    }
475
476
0
    return HTP_ERROR;
477
0
}
478
479
/**
480
 * Processes an identity response body of known length.
481
 *
482
 * @param[in] connp
483
 * @returns HTP_OK on state change, HTP_ERROR on error, or HTP_DATA when more data is needed.
484
 */
485
0
htp_status_t htp_connp_RES_BODY_IDENTITY_CL_KNOWN(htp_connp_t *connp) {
486
0
    size_t bytes_to_consume;   
487
        
488
    // Determine how many bytes we can consume.
489
0
    if (connp->out_current_len - connp->out_current_read_offset >= connp->out_body_data_left) {
490
0
        bytes_to_consume = connp->out_body_data_left;
491
0
    } else {
492
0
        bytes_to_consume = connp->out_current_len - connp->out_current_read_offset;
493
0
    }       
494
    
495
0
    if (connp->out_status == HTP_STREAM_CLOSED) {
496
0
        connp->out_state = htp_connp_RES_FINALIZE;
497
        // Sends close signal to decompressors
498
0
        htp_status_t rc = htp_tx_res_process_body_data_ex(connp->out_tx, NULL, 0);
499
0
        return rc;
500
0
    }
501
0
    if (bytes_to_consume == 0) return HTP_DATA;    
502
503
    // Consume the data.
504
0
    htp_status_t rc = htp_tx_res_process_body_data_ex(connp->out_tx, connp->out_current_data + connp->out_current_read_offset, bytes_to_consume);
505
0
    if (rc != HTP_OK) return rc;
506
507
    // Adjust the counters.
508
0
    connp->out_current_read_offset += bytes_to_consume;
509
0
    connp->out_current_consume_offset += bytes_to_consume;
510
0
    connp->out_stream_offset += bytes_to_consume;
511
0
    connp->out_body_data_left -= bytes_to_consume;
512
513
    // Have we seen the entire response body?
514
0
    if (connp->out_body_data_left == 0) {
515
0
        connp->out_state = htp_connp_RES_FINALIZE;
516
        // Tells decompressors to output partially decompressed data
517
0
        rc = htp_tx_res_process_body_data_ex(connp->out_tx, NULL, 0);
518
0
        return rc;
519
0
    }
520
521
0
    return HTP_DATA;
522
0
}
523
524
/**
525
 * Processes identity response body of unknown length. In this case, we assume the
526
 * response body consumes all data until the end of the stream.
527
 *
528
 * @param[in] connp
529
 * @returns HTP_OK on state change, HTP_ERROR on error, or HTP_DATA when more data is needed.
530
 */
531
18.5k
htp_status_t htp_connp_RES_BODY_IDENTITY_STREAM_CLOSE(htp_connp_t *connp) {        
532
    // Consume all data from the input buffer.
533
18.5k
    size_t bytes_to_consume = connp->out_current_len - connp->out_current_read_offset;
534
535
    #ifdef HTP_DEBUG
536
    fprintf(stderr, "bytes_to_consume %"PRIuMAX, (uintmax_t)bytes_to_consume);
537
    #endif
538
18.5k
    if (bytes_to_consume != 0) {
539
12.3k
        htp_status_t rc = htp_tx_res_process_body_data_ex(connp->out_tx, connp->out_current_data + connp->out_current_read_offset, bytes_to_consume);
540
12.3k
        if (rc != HTP_OK) return rc;
541
542
        // Adjust the counters.
543
12.3k
        connp->out_current_read_offset += bytes_to_consume;
544
12.3k
        connp->out_current_consume_offset += bytes_to_consume;
545
12.3k
        connp->out_stream_offset += bytes_to_consume;        
546
12.3k
    }
547
548
    // Have we seen the entire response body?
549
18.5k
    if (connp->out_status == HTP_STREAM_CLOSED) {
550
5.67k
        connp->out_state = htp_connp_RES_FINALIZE;
551
5.67k
        return HTP_OK;
552
5.67k
    }
553
   
554
12.8k
    return HTP_DATA;
555
18.5k
}
556
557
/**
558
 * Determines presence (and encoding) of a response body.
559
 *
560
 * @param[in] connp
561
 * @returns HTP_OK on state change, HTP_ERROR on error, or HTP_DATA when more data is needed.
562
 */
563
163k
htp_status_t htp_connp_RES_BODY_DETERMINE(htp_connp_t *connp) {
564
    // If the request uses the CONNECT method, then not only are we
565
    // to assume there's no body, but we need to ignore all
566
    // subsequent data in the stream.
567
163k
    if (connp->out_tx->request_method_number == HTP_M_CONNECT) {
568
3.42k
        if ((connp->out_tx->response_status_number >= 200)
569
2.93k
                && (connp->out_tx->response_status_number <= 299)) {
570
            // This is a successful CONNECT stream, which means
571
            // we need to switch into tunneling mode: on the
572
            // request side we'll now probe the tunnel data to see
573
            // if we need to parse or ignore it. So on the response
574
            // side we wrap up the tx and wait.
575
2.54k
            connp->out_state = htp_connp_RES_FINALIZE;
576
577
            // we may have response headers
578
2.54k
            htp_status_t rc = htp_tx_state_response_headers(connp->out_tx);
579
2.54k
            return rc;
580
2.54k
        } else if (connp->out_tx->response_status_number == 407) {
581
            // proxy telling us to auth
582
2
            if (connp->in_status != HTP_STREAM_ERROR)
583
1
                connp->in_status = HTP_STREAM_DATA;
584
877
        } else {
585
            // This is a failed CONNECT stream, which means that
586
            // we can unblock request parsing
587
877
            if (connp->in_status != HTP_STREAM_ERROR)
588
839
                connp->in_status = HTP_STREAM_DATA;
589
590
            // We are going to continue processing this transaction,
591
            // adding a note for ourselves to stop at the end (because
592
            // we don't want to see the beginning of a new transaction).
593
877
            connp->out_data_other_at_tx_end = 1;
594
877
        }
595
3.42k
    }
596
597
161k
    htp_header_t *cl = htp_table_get_c(connp->out_tx->response_headers, "content-length");
598
161k
    htp_header_t *te = htp_table_get_c(connp->out_tx->response_headers, "transfer-encoding");
599
600
    // Check for "101 Switching Protocol" response.
601
    // If it's seen, it means that traffic after empty line following headers
602
    // is no longer HTTP. We can treat it similarly to CONNECT.
603
    // Unlike CONNECT, however, upgrades from HTTP to HTTP seem
604
    // rather unlikely, so don't try to probe tunnel for nested HTTP,
605
    // and switch to tunnel mode right away.
606
161k
    if (connp->out_tx->response_status_number == 101) {
607
18
        if (te == NULL && cl == NULL) {
608
18
            connp->out_state = htp_connp_RES_FINALIZE;
609
610
18
            if (connp->in_status != HTP_STREAM_ERROR)
611
17
                connp->in_status = HTP_STREAM_TUNNEL;
612
18
            connp->out_status = HTP_STREAM_TUNNEL;
613
614
            // we may have response headers
615
18
            htp_status_t rc = htp_tx_state_response_headers(connp->out_tx);
616
18
            return rc;
617
18
        } else {
618
0
            htp_log(connp, HTP_LOG_MARK, HTP_LOG_WARNING, 0, "Switching Protocol with Content-Length");
619
0
        }
620
18
    }
621
622
    // Check for an interim "100 Continue" response. Ignore it if found, and revert back to RES_LINE.
623
161k
    if (connp->out_tx->response_status_number == 100 && te == NULL) {
624
133k
        int is100continue = 1;
625
133k
        if (cl != NULL){
626
0
            if (htp_parse_content_length(cl->value, connp) > 0) {
627
0
                is100continue = 0;
628
0
            }
629
0
        }
630
133k
        if (is100continue) {
631
133k
            if (connp->out_tx->seen_100continue != 0) {
632
132k
                htp_log(connp, HTP_LOG_MARK, HTP_LOG_ERROR, 0, "Already seen 100-Continue.");
633
132k
            }
634
635
            // Ignore any response headers seen so far.
636
133k
            htp_header_t *h = NULL;
637
148k
            for (size_t i = 0, n = htp_table_size(connp->out_tx->response_headers); i < n; i++) {
638
14.6k
                h = htp_table_get_index(connp->out_tx->response_headers, i, NULL);
639
14.6k
                bstr_free(h->name);
640
14.6k
                bstr_free(h->value);
641
14.6k
                free(h);
642
14.6k
            }
643
644
133k
            htp_table_clear(connp->out_tx->response_headers);
645
646
            // Expecting to see another response line next.
647
133k
            connp->out_state = htp_connp_RES_LINE;
648
133k
            connp->out_tx->response_progress = HTP_RESPONSE_LINE;
649
133k
            connp->out_tx->seen_100continue++;
650
651
133k
            return HTP_OK;
652
133k
        }
653
133k
    }
654
655
    // A request can indicate it waits for headers validation
656
    // before sending its body cf
657
    // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Expect
658
27.6k
    if (connp->out_tx->response_status_number >= 400 &&
659
443
        connp->out_tx->response_status_number <= 499 &&
660
213
        connp->in_content_length > 0 &&
661
0
        connp->in_body_data_left == connp->in_content_length) {
662
0
        htp_header_t *exp = htp_table_get_c(connp->out_tx->request_headers, "expect");
663
0
        if ((exp != NULL) && (bstr_cmp_c_nocase(exp->value, "100-continue") == 0)) {
664
0
            connp->in_state = htp_connp_REQ_FINALIZE;
665
0
        }
666
0
    }
667
668
    // 1. Any response message which MUST NOT include a message-body
669
    //  (such as the 1xx, 204, and 304 responses and any response to a HEAD
670
    //  request) is always terminated by the first empty line after the
671
    //  header fields, regardless of the entity-header fields present in the
672
    //  message.
673
27.6k
    if (connp->out_tx->request_method_number == HTP_M_HEAD) {
674
        // There's no response body whatsoever
675
2.18k
        connp->out_tx->response_transfer_coding = HTP_CODING_NO_BODY;
676
2.18k
        connp->out_state = htp_connp_RES_FINALIZE;
677
2.18k
    }
678
25.4k
    else if (((connp->out_tx->response_status_number >= 100) && (connp->out_tx->response_status_number <= 199))
679
19.8k
            || (connp->out_tx->response_status_number == 204) || (connp->out_tx->response_status_number == 304)) {
680
        // There should be no response body
681
        // but browsers interpret content sent by the server as such
682
19.8k
        if (te == NULL && cl == NULL) {
683
19.8k
            connp->out_tx->response_transfer_coding = HTP_CODING_NO_BODY;
684
19.8k
            connp->out_state = htp_connp_RES_FINALIZE;
685
19.8k
        } else {
686
0
            htp_log(connp, HTP_LOG_MARK, HTP_LOG_WARNING, 0, "Unexpected Response body");
687
0
        }
688
19.8k
    }
689
    // Hack condition to check that we do not assume "no body"
690
27.6k
    if (connp->out_state != htp_connp_RES_FINALIZE) {
691
        // We have a response body
692
5.64k
        htp_header_t *ct = htp_table_get_c(connp->out_tx->response_headers, "content-type");
693
5.64k
        if (ct != NULL) {
694
50
            connp->out_tx->response_content_type = bstr_dup_lower(ct->value);
695
50
            if (connp->out_tx->response_content_type == NULL) return HTP_ERROR;
696
697
            // Ignore parameters
698
50
            unsigned char *data = bstr_ptr(connp->out_tx->response_content_type);
699
50
            size_t len = bstr_len(ct->value);
700
50
            size_t newlen = 0;
701
40.4k
            while (newlen < len) {
702
                // TODO Some platforms may do things differently here.
703
40.3k
                if (htp_is_space(data[newlen]) || (data[newlen] == ';')) {
704
10
                    bstr_adjust_len(connp->out_tx->response_content_type, newlen);
705
10
                    break;
706
10
                }
707
708
40.3k
                newlen++;
709
40.3k
            }
710
50
        }
711
712
        // 2. If a Transfer-Encoding header field (section 14.40) is present and
713
        //   indicates that the "chunked" transfer coding has been applied, then
714
        //   the length is defined by the chunked encoding (section 3.6).
715
5.64k
        if ((te != NULL) && (bstr_index_of_c_nocasenorzero(te->value, "chunked") != -1)) {
716
0
            if (bstr_cmp_c_nocase(te->value, "chunked") != 0) {
717
0
                htp_log(connp, HTP_LOG_MARK, HTP_LOG_WARNING, 0,
718
0
                        "Transfer-encoding has abnormal chunked value");
719
0
            }
720
721
            // spec says chunked is HTTP/1.1 only, but some browsers accept it
722
            // with 1.0 as well
723
0
            if (connp->out_tx->response_protocol_number < HTP_PROTOCOL_1_1) {
724
0
                htp_log(connp, HTP_LOG_MARK, HTP_LOG_WARNING, 0,
725
0
                        "Chunked transfer-encoding on HTTP/0.9 or HTTP/1.0");
726
0
            }
727
728
            // If the T-E header is present we are going to use it.
729
0
            connp->out_tx->response_transfer_coding = HTP_CODING_CHUNKED;
730
731
            // We are still going to check for the presence of C-L
732
0
            if (cl != NULL) {
733
                // This is a violation of the RFC
734
0
                connp->out_tx->flags |= HTP_REQUEST_SMUGGLING;
735
0
            }
736
737
0
            connp->out_state = htp_connp_RES_BODY_CHUNKED_LENGTH;
738
0
            connp->out_tx->response_progress = HTP_RESPONSE_BODY;
739
0
        }// 3. If a Content-Length header field (section 14.14) is present, its
740
            //   value in bytes represents the length of the message-body.
741
5.64k
        else if (cl != NULL) {
742
            // We know the exact length
743
0
            connp->out_tx->response_transfer_coding = HTP_CODING_IDENTITY;
744
745
            // Check for multiple C-L headers
746
0
            if (cl->flags & HTP_FIELD_REPEATED) {
747
0
                connp->out_tx->flags |= HTP_REQUEST_SMUGGLING;
748
0
            }
749
750
            // Get body length
751
0
            connp->out_tx->response_content_length = htp_parse_content_length(cl->value, connp);
752
0
            if (connp->out_tx->response_content_length < 0) {
753
0
                htp_log(connp, HTP_LOG_MARK, HTP_LOG_ERROR, 0, "Invalid C-L field in response: %"PRId64"",
754
0
                        connp->out_tx->response_content_length);
755
0
                return HTP_ERROR;
756
0
            } else {
757
0
                connp->out_content_length = connp->out_tx->response_content_length;
758
0
                connp->out_body_data_left = connp->out_content_length;
759
760
0
                if (connp->out_content_length != 0) {
761
0
                    connp->out_state = htp_connp_RES_BODY_IDENTITY_CL_KNOWN;
762
0
                    connp->out_tx->response_progress = HTP_RESPONSE_BODY;
763
0
                } else {                    
764
0
                    connp->out_state = htp_connp_RES_FINALIZE;
765
0
                }
766
0
            }
767
5.64k
        } else {
768
            // 4. If the message uses the media type "multipart/byteranges", which is
769
            //   self-delimiting, then that defines the length. This media type MUST
770
            //   NOT be used unless the sender knows that the recipient can parse it;
771
            //   the presence in a request of a Range header with multiple byte-range
772
            //   specifiers implies that the client can parse multipart/byteranges
773
            //   responses.
774
5.64k
            if (ct != NULL) {
775
                // TODO Handle multipart/byteranges
776
50
                if (bstr_index_of_c_nocase(ct->value, "multipart/byteranges") != -1) {
777
0
                    htp_log(connp, HTP_LOG_MARK, HTP_LOG_ERROR, 0,
778
0
                            "C-T multipart/byteranges in responses not supported");
779
0
                    return HTP_ERROR;
780
0
                }
781
50
            }
782
783
            // 5. By the server closing the connection. (Closing the connection
784
            //   cannot be used to indicate the end of a request body, since that
785
            //   would leave no possibility for the server to send back a response.)
786
5.64k
            connp->out_state = htp_connp_RES_BODY_IDENTITY_STREAM_CLOSE;
787
5.64k
            connp->out_tx->response_transfer_coding = HTP_CODING_IDENTITY;
788
5.64k
            connp->out_tx->response_progress = HTP_RESPONSE_BODY;
789
5.64k
            connp->out_body_data_left = -1;
790
5.64k
        }
791
5.64k
    }
792
793
    // NOTE We do not need to check for short-style HTTP/0.9 requests here because
794
    //      that is done earlier, before response line parsing begins
795
796
27.6k
    htp_status_t rc = htp_tx_state_response_headers(connp->out_tx);
797
27.6k
    if (rc != HTP_OK) return rc;
798
799
27.6k
    return HTP_OK;
800
27.6k
}
801
802
/**
803
 * Parses response headers.
804
 *
805
 * @param[in] connp
806
 * @returns HTP_OK on state change, HTP_ERROR on error, or HTP_DATA when more data is needed.
807
 */
808
169k
htp_status_t htp_connp_RES_HEADERS(htp_connp_t *connp) {
809
169k
    int endwithcr;
810
169k
    int lfcrending = 0;
811
812
18.1M
    for (;;) {
813
18.1M
        if (connp->out_status == HTP_STREAM_CLOSED) {
814
            // Finalize sending raw trailer data.
815
1.49k
            htp_status_t rc = htp_connp_res_receiver_finalize_clear(connp);
816
1.49k
            if (rc != HTP_OK) return rc;
817
818
            // Run hook response_TRAILER.
819
1.49k
            rc = htp_hook_run_all(connp->cfg->hook_response_trailer, connp->out_tx);
820
1.49k
            if (rc != HTP_OK) return rc;
821
822
1.49k
            connp->out_state = htp_connp_RES_FINALIZE;
823
1.49k
            return HTP_OK;
824
1.49k
        }
825
18.1M
        OUT_COPY_BYTE_OR_RETURN(connp);
826
827
        // Have we reached the end of the line?
828
18.0M
        if (connp->out_next_byte != LF && connp->out_next_byte != CR) {
829
17.3M
            lfcrending = 0;
830
17.3M
        } else {
831
706k
            endwithcr = 0;
832
706k
            if (connp->out_next_byte == CR) {
833
371k
                OUT_PEEK_NEXT(connp);
834
371k
                if (connp->out_next_byte == -1) {
835
509
                    return HTP_DATA_BUFFER;
836
370k
                } else if (connp->out_next_byte == LF) {
837
58.9k
                    OUT_COPY_BYTE_OR_RETURN(connp);
838
58.9k
                    if (lfcrending) {
839
                        // Handling LFCRCRLFCRLF
840
                        // These 6 characters mean only 2 end of lines
841
30.9k
                        OUT_PEEK_NEXT(connp);
842
30.9k
                        if (connp->out_next_byte == CR) {
843
23.9k
                            OUT_COPY_BYTE_OR_RETURN(connp);
844
23.9k
                            connp->out_current_consume_offset++;
845
23.9k
                            OUT_PEEK_NEXT(connp);
846
23.9k
                            if (connp->out_next_byte == LF) {
847
702
                                OUT_COPY_BYTE_OR_RETURN(connp);
848
702
                                connp->out_current_consume_offset++;
849
702
                                htp_log(connp, HTP_LOG_MARK, HTP_LOG_WARNING, 0,
850
702
                                        "Weird response end of lines mix");
851
702
                            }
852
23.9k
                        }
853
30.9k
                    }
854
311k
                } else if (connp->out_next_byte == CR) {
855
204k
                    continue;
856
204k
                }
857
166k
                lfcrending = 0;
858
166k
                endwithcr = 1;
859
335k
            } else {
860
                // connp->out_next_byte == LF
861
335k
                OUT_PEEK_NEXT(connp);
862
335k
                lfcrending = 0;
863
335k
                if (connp->out_next_byte == CR) {
864
                    // hanldes LF-CR sequence as end of line
865
63.8k
                    OUT_COPY_BYTE_OR_RETURN(connp);
866
63.8k
                    lfcrending = 1;
867
63.8k
                }
868
335k
            }
869
870
501k
            unsigned char *data;
871
501k
            size_t len;
872
873
501k
            if (htp_connp_res_consolidate_data(connp, &data, &len) != HTP_OK) {
874
1
                return HTP_ERROR;
875
1
            }
876
877
            // CRCRLF is not an empty line
878
501k
            if (endwithcr && len < 2) {
879
21.4k
                continue;
880
21.4k
            }
881
882
            #ifdef HTP_DEBUG
883
            fprint_raw_data(stderr, __func__, data, len);
884
            #endif
885
886
480k
            int next_no_lf = 0;
887
480k
            if (connp->out_current_read_offset < connp->out_current_len &&
888
476k
                connp->out_current_data[connp->out_current_read_offset] != LF) {
889
420k
                next_no_lf = 1;
890
420k
            }
891
            // Should we terminate headers?
892
480k
            if (htp_connp_is_line_terminator(connp, data, len, next_no_lf)) {
893
                // Parse previous header, if any.
894
163k
                if (connp->out_header != NULL) {
895
1.74k
                    if (connp->cfg->process_response_header(connp, bstr_ptr(connp->out_header),
896
1.74k
                            bstr_len(connp->out_header)) != HTP_OK) return HTP_ERROR;
897
898
1.74k
                    bstr_free(connp->out_header);
899
1.74k
                    connp->out_header = NULL;
900
1.74k
                }
901
902
163k
                htp_connp_res_clear_buffer(connp);
903
904
                // We've seen all response headers.
905
163k
                if (connp->out_tx->response_progress == HTP_RESPONSE_HEADERS) {
906
                    // Response headers.
907
908
                    // The next step is to determine if this response has a body.
909
163k
                    connp->out_state = htp_connp_RES_BODY_DETERMINE;
910
163k
                } else {
911
                    // Response trailer.
912
913
                    // Finalize sending raw trailer data.
914
0
                    htp_status_t rc = htp_connp_res_receiver_finalize_clear(connp);
915
0
                    if (rc != HTP_OK) return rc;
916
917
                    // Run hook response_TRAILER.
918
0
                    rc = htp_hook_run_all(connp->cfg->hook_response_trailer, connp->out_tx);
919
0
                    if (rc != HTP_OK) return rc;
920
921
                    // The next step is to finalize this response.
922
0
                    connp->out_state = htp_connp_RES_FINALIZE;
923
0
                }
924
925
163k
                return HTP_OK;
926
163k
            }
927
928
316k
            htp_chomp(data, &len);
929
930
            // Check for header folding.
931
316k
            if (htp_connp_is_line_folded(data, len) == 0) {
932
                // New header line.
933
934
                // Parse previous header, if any.
935
208k
                if (connp->out_header != NULL) {
936
83.6k
                    if (connp->cfg->process_response_header(connp, bstr_ptr(connp->out_header),
937
83.6k
                            bstr_len(connp->out_header)) != HTP_OK) return HTP_ERROR;
938
939
83.6k
                    bstr_free(connp->out_header);
940
83.6k
                    connp->out_header = NULL;
941
83.6k
                }
942
943
208k
                OUT_PEEK_NEXT(connp);
944
945
208k
                if (htp_is_folding_char(connp->out_next_byte) == 0) {
946
                    // Because we know this header is not folded, we can process the buffer straight away.
947
197k
                    if (connp->cfg->process_response_header(connp, data, len) != HTP_OK) return HTP_ERROR;
948
197k
                } else {
949
                    // Keep the partial header data for parsing later.
950
11.3k
                    connp->out_header = bstr_dup_mem(data, len);
951
11.3k
                    if (connp->out_header == NULL) return HTP_ERROR;
952
11.3k
                }
953
208k
            } else {
954
                // Folding; check that there's a previous header line to add to.
955
108k
                if (connp->out_header == NULL) {
956
                    // Invalid folding.
957
958
                    // Warn only once per transaction.
959
74.2k
                    if (!(connp->out_tx->flags & HTP_INVALID_FOLDING)) {
960
2.10k
                        connp->out_tx->flags |= HTP_INVALID_FOLDING;
961
2.10k
                        htp_log(connp, HTP_LOG_MARK, HTP_LOG_WARNING, 0, "Invalid response field folding");
962
2.10k
                    }
963
964
                    // Keep the header data for parsing later.
965
74.2k
                    size_t trim = 0;
966
77.5k
                    while(trim < len) {
967
4.32k
                        if (!htp_is_folding_char(data[trim])) {
968
1.07k
                            break;
969
1.07k
                        }
970
3.24k
                        trim++;
971
3.24k
                    }
972
74.2k
                    connp->out_header = bstr_dup_mem(data + trim, len - trim);
973
74.2k
                    if (connp->out_header == NULL) return HTP_ERROR;
974
74.2k
                } else {
975
33.8k
                    size_t colon_pos = 0;
976
5.03M
                    while ((colon_pos < len) && (data[colon_pos] != ':')) colon_pos++;
977
978
33.8k
                    if (colon_pos < len &&
979
2.21k
                        bstr_chr(connp->out_header, ':') >= 0 &&
980
1.68k
                        connp->out_tx->response_protocol_number == HTP_PROTOCOL_1_1) {
981
                        // Warn only once per transaction.
982
405
                        if (!(connp->out_tx->flags & HTP_INVALID_FOLDING)) {
983
198
                            connp->out_tx->flags |= HTP_INVALID_FOLDING;
984
198
                            htp_log(connp, HTP_LOG_MARK, HTP_LOG_WARNING, 0, "Invalid response field folding");
985
198
                        }
986
405
                        if (connp->cfg->process_response_header(connp, bstr_ptr(connp->out_header),
987
405
                            bstr_len(connp->out_header)) != HTP_OK)
988
0
                            return HTP_ERROR;
989
405
                        bstr_free(connp->out_header);
990
405
                        connp->out_header = bstr_dup_mem(data+1, len-1);
991
405
                        if (connp->out_header == NULL)
992
0
                            return HTP_ERROR;
993
33.4k
                    } else {
994
                        // Add to the existing header.
995
33.4k
                        if (bstr_len(connp->out_header) < HTP_MAX_HEADER_FOLDED) {
996
33.2k
                            bstr *new_out_header = bstr_add_mem(connp->out_header, data, len);
997
33.2k
                            if (new_out_header == NULL)
998
0
                                return HTP_ERROR;
999
33.2k
                            connp->out_header = new_out_header;
1000
33.2k
                        } else {
1001
257
                            htp_log(connp, HTP_LOG_MARK, HTP_LOG_WARNING, 0, "Response field length exceeds folded maximum");
1002
257
                        }
1003
33.4k
                    }
1004
33.8k
                }
1005
108k
            }
1006
1007
316k
            htp_connp_res_clear_buffer(connp);
1008
316k
        }
1009
18.0M
    }
1010
1011
0
    return HTP_ERROR;
1012
169k
}
1013
1014
/**
1015
 * Parses response line.
1016
 *
1017
 * @param[in] connp
1018
 * @returns HTP_OK on state change, HTP_ERROR on error, or HTP_DATA when more data is needed.
1019
 */
1020
231k
htp_status_t htp_connp_RES_LINE(htp_connp_t *connp) {
1021
15.4M
    for (;;) {
1022
        // Don't try to get more data if the stream is closed. If we do, we'll return, asking for more data.
1023
15.4M
        if (connp->out_status != HTP_STREAM_CLOSED) {
1024
            // Get one byte
1025
15.4M
            OUT_COPY_BYTE_OR_RETURN(connp);
1026
15.4M
        }
1027
1028
        // Have we reached the end of the line? We treat stream closure as end of line in
1029
        // order to handle the case when the first line of the response is actually response body
1030
        // (and we wish it processed as such).
1031
15.4M
        if (connp->out_next_byte == CR) {
1032
6.86k
            OUT_PEEK_NEXT(connp);
1033
6.86k
            if (connp->out_next_byte == -1) {
1034
1.34k
                return HTP_DATA_BUFFER;
1035
5.52k
            } else if (connp->out_next_byte == LF) {
1036
1.33k
                continue;
1037
1.33k
            }
1038
4.19k
            connp->out_next_byte = LF;
1039
4.19k
        }
1040
15.4M
        if ((connp->out_next_byte == LF)||(connp->out_status == HTP_STREAM_CLOSED)) {
1041
226k
            unsigned char *data;
1042
226k
            size_t len;
1043
1044
226k
            if (htp_connp_res_consolidate_data(connp, &data, &len) != HTP_OK) {
1045
7
                return HTP_ERROR;
1046
7
            }
1047
1048
            #ifdef HTP_DEBUG
1049
            fprint_raw_data(stderr, __func__, data, len);
1050
            #endif
1051
1052
            // Is this a line that should be ignored?
1053
226k
            if (htp_connp_is_line_ignorable(connp, data, len)) {
1054
20.8k
                if (connp->out_status == HTP_STREAM_CLOSED) {
1055
32
                    connp->out_state = htp_connp_RES_FINALIZE;
1056
32
                }
1057
                // We have an empty/whitespace line, which we'll note, ignore and move on
1058
20.8k
                connp->out_tx->response_ignored_lines++;
1059
1060
                // TODO How many lines are we willing to accept?
1061
1062
                // Start again
1063
20.8k
                htp_connp_res_clear_buffer(connp);
1064
1065
20.8k
                return HTP_OK;
1066
20.8k
            }
1067
1068
            // Deallocate previous response line allocations, which we would have on a 100 response.
1069
1070
205k
            if (connp->out_tx->response_line != NULL) {
1071
133k
                bstr_free(connp->out_tx->response_line);
1072
133k
                connp->out_tx->response_line = NULL;
1073
133k
            }
1074
1075
205k
            if (connp->out_tx->response_protocol != NULL) {
1076
133k
                bstr_free(connp->out_tx->response_protocol);
1077
133k
                connp->out_tx->response_protocol = NULL;
1078
133k
            }
1079
1080
205k
            if (connp->out_tx->response_status != NULL) {
1081
133k
                bstr_free(connp->out_tx->response_status);
1082
133k
                connp->out_tx->response_status = NULL;
1083
133k
            }
1084
1085
205k
            if (connp->out_tx->response_message != NULL) {
1086
129k
                bstr_free(connp->out_tx->response_message);
1087
129k
                connp->out_tx->response_message = NULL;
1088
129k
            }
1089
1090
            // Process response line.           
1091
1092
205k
            int chomp_result = htp_chomp(data, &len);
1093
1094
            // If the response line is invalid, determine if it _looks_ like
1095
            // a response line. If it does not look like a line, process the
1096
            // data as a response body because that is what browsers do.
1097
           
1098
205k
            if (htp_treat_response_line_as_body(data, len)) {
1099
                // if we have a next line beginning with H, skip this one
1100
40.3k
                if (connp->out_current_read_offset+1 < connp->out_current_len && (connp->out_current_data[connp->out_current_read_offset] == 'H' || len <= 2)) {
1101
16.0k
                    connp->out_tx->response_ignored_lines++;
1102
16.0k
                    htp_connp_res_clear_buffer(connp);
1103
16.0k
                    return HTP_OK;
1104
16.0k
                }
1105
24.2k
                connp->out_tx->response_content_encoding_processing = HTP_COMPRESSION_NONE;
1106
1107
24.2k
                connp->out_current_consume_offset = connp->out_current_read_offset;
1108
24.2k
                htp_status_t rc = htp_tx_res_process_body_data_ex(connp->out_tx, data, len + chomp_result);
1109
24.2k
                htp_connp_res_clear_buffer(connp);
1110
24.2k
                if (rc != HTP_OK) return rc;
1111
1112
                // Continue to process response body. Because we don't have
1113
                // any headers to parse, we assume the body continues until
1114
                // the end of the stream.
1115
1116
                // Have we seen the entire response body?
1117
24.2k
                if (connp->out_current_len <= connp->out_current_read_offset) {
1118
9.52k
                    connp->out_tx->response_transfer_coding = HTP_CODING_IDENTITY;
1119
9.52k
                    connp->out_tx->response_progress = HTP_RESPONSE_BODY;
1120
9.52k
                    connp->out_body_data_left = -1;
1121
9.52k
                    connp->out_state = htp_connp_RES_FINALIZE;
1122
9.52k
                }
1123
1124
24.2k
                return HTP_OK;
1125
24.2k
            }
1126
1127
165k
            connp->out_tx->response_line = bstr_dup_mem(data, len);
1128
165k
            if (connp->out_tx->response_line == NULL) return HTP_ERROR;
1129
1130
165k
            if (connp->cfg->parse_response_line(connp) != HTP_OK) return HTP_ERROR;
1131
1132
165k
            htp_status_t rc = htp_tx_state_response_line(connp->out_tx);
1133
165k
            if (rc != HTP_OK) return rc;
1134
1135
165k
            htp_connp_res_clear_buffer(connp);
1136
1137
            // Move on to the next phase.
1138
165k
            connp->out_state = htp_connp_RES_HEADERS;
1139
165k
            connp->out_tx->response_progress = HTP_RESPONSE_HEADERS;
1140
1141
165k
            return HTP_OK;
1142
165k
        }
1143
15.4M
    }
1144
1145
0
    return HTP_ERROR;
1146
231k
}
1147
1148
1.79k
size_t htp_connp_res_data_consumed(htp_connp_t *connp) {
1149
1.79k
    return connp->out_current_read_offset;
1150
1.79k
}
1151
1152
1.94M
htp_status_t htp_connp_RES_FINALIZE(htp_connp_t *connp) {
1153
1.94M
    if (connp->out_status != HTP_STREAM_CLOSED) {
1154
1.93M
        OUT_PEEK_NEXT(connp);
1155
1.93M
        if (connp->out_next_byte == -1) {
1156
11.8k
            return htp_tx_state_response_complete_ex(connp->out_tx, 0);
1157
11.8k
        }
1158
1.92M
        if (connp->out_next_byte != LF || connp->out_current_consume_offset >= connp->out_current_read_offset) {
1159
10.1M
            for (;;) {//;i < max_read; i++) {
1160
10.1M
                OUT_COPY_BYTE_OR_RETURN(connp);
1161
                // Have we reached the end of the line? For some reason
1162
                // we can't test after IN_COPY_BYTE_OR_RETURN */
1163
10.1M
                if (connp->out_next_byte == LF)
1164
1.91M
                    break;
1165
10.1M
            }
1166
1.92M
        }
1167
1.92M
    }
1168
1.92M
    size_t bytes_left;
1169
1.92M
    unsigned char * data;
1170
1171
1.92M
    if (htp_connp_res_consolidate_data(connp, &data, &bytes_left) != HTP_OK) {
1172
3
        return HTP_ERROR;
1173
3
    }
1174
#ifdef HTP_DEBUG
1175
    fprint_raw_data(stderr, "PROBING response finalize", data, bytes_left);
1176
#endif
1177
1.92M
    if (bytes_left == 0) {
1178
        //closing
1179
8.33k
        return htp_tx_state_response_complete_ex(connp->out_tx, 0);
1180
8.33k
    }
1181
1182
1.91M
    if (htp_treat_response_line_as_body(data, bytes_left)) {
1183
        // Interpret remaining bytes as body data
1184
1.89M
        htp_log(connp, HTP_LOG_MARK, HTP_LOG_WARNING, 0, "Unexpected response body");
1185
1.89M
        htp_status_t rc = htp_tx_res_process_body_data_ex(connp->out_tx, data, bytes_left);
1186
1.89M
        htp_connp_res_clear_buffer(connp);
1187
1.89M
        return rc;
1188
1.89M
    }
1189
1190
    //unread last end of line so that RES_LINE works
1191
24.8k
    if (connp->out_current_read_offset < (int64_t)bytes_left) {
1192
1.91k
        connp->out_current_read_offset=0;
1193
22.8k
    } else {
1194
22.8k
        connp->out_current_read_offset-=bytes_left;
1195
22.8k
    }
1196
24.8k
    if (connp->out_current_read_offset < connp->out_current_consume_offset) {
1197
1.87k
        connp->out_current_consume_offset=connp->out_current_read_offset;
1198
1.87k
    }
1199
24.8k
    return htp_tx_state_response_complete_ex(connp->out_tx, 0 /* not hybrid mode */);
1200
1.91M
}
1201
1202
/**
1203
 * The response idle state will initialize response processing, as well as
1204
 * finalize each transactions after we are done with it.
1205
 *
1206
 * @param[in] connp
1207
 * @returns HTP_OK on state change, HTP_ERROR on error, or HTP_DATA when more data is needed.
1208
 */
1209
65.3k
htp_status_t htp_connp_RES_IDLE(htp_connp_t *connp) {
1210
1211
    // We want to start parsing the next response (and change
1212
    // the state from IDLE) only if there's at least one
1213
    // byte of data available. Otherwise we could be creating
1214
    // new structures even if there's no more data on the
1215
    // connection.
1216
65.3k
    OUT_TEST_NEXT_BYTE_OR_RETURN(connp);
1217
1218
    // Parsing a new response
1219
1220
    // Find the next outgoing transaction
1221
    // If there is none, we just create one so that responses without
1222
    // request can still be processed.
1223
41.3k
    connp->out_tx = htp_list_get(connp->conn->transactions, connp->out_next_tx_index);
1224
41.3k
    if (connp->out_tx == NULL) {
1225
31.0k
        htp_log(connp, HTP_LOG_MARK, HTP_LOG_ERROR, 0, "Unable to match response to request");
1226
        // finalize dangling request waiting for next request or body
1227
31.0k
        if (connp->in_state == htp_connp_REQ_FINALIZE) {
1228
21.2k
            htp_tx_state_request_complete(connp->in_tx);
1229
21.2k
        }
1230
31.0k
        connp->out_tx = htp_connp_tx_create(connp);
1231
31.0k
        if (connp->out_tx == NULL) {
1232
3
            return HTP_ERROR;
1233
3
        }
1234
31.0k
        connp->out_tx->parsed_uri = htp_uri_alloc();
1235
31.0k
        if (connp->out_tx->parsed_uri == NULL) {
1236
0
            return HTP_ERROR;
1237
0
        }
1238
31.0k
        connp->out_tx->parsed_uri->path = bstr_dup_c(REQUEST_URI_NOT_SEEN);
1239
31.0k
        if (connp->out_tx->parsed_uri->path == NULL) {
1240
0
            return HTP_ERROR;
1241
0
        }
1242
31.0k
        connp->out_tx->request_uri = bstr_dup_c(REQUEST_URI_NOT_SEEN);
1243
31.0k
        if (connp->out_tx->request_uri == NULL) {
1244
0
            return HTP_ERROR;
1245
0
        }
1246
1247
31.0k
        connp->in_state = htp_connp_REQ_FINALIZE;
1248
#ifdef HTP_DEBUG
1249
        fprintf(stderr, "picked up response w/o request");
1250
#endif
1251
        // We've used one transaction
1252
31.0k
        connp->out_next_tx_index++;
1253
31.0k
    } else {
1254
        // We've used one transaction
1255
10.2k
        connp->out_next_tx_index++;
1256
1257
        // TODO Detect state mismatch
1258
1259
10.2k
        connp->out_content_length = -1;
1260
10.2k
        connp->out_body_data_left = -1;
1261
10.2k
    }
1262
1263
41.3k
    htp_status_t rc = htp_tx_state_response_start(connp->out_tx);
1264
41.3k
    if (rc != HTP_OK) return rc;
1265
1266
41.3k
    return HTP_OK;
1267
41.3k
}
1268
1269
57.6k
int htp_connp_res_data(htp_connp_t *connp, const htp_time_t *timestamp, const void *data, size_t len) {
1270
    #ifdef HTP_DEBUG
1271
    fprintf(stderr, "htp_connp_res_data(connp->out_status %x)\n", connp->out_status);
1272
    fprint_raw_data(stderr, __func__, data, len);
1273
    #endif
1274
1275
    // Return if the connection is in stop state
1276
57.6k
    if (connp->out_status == HTP_STREAM_STOP) {
1277
0
        htp_log(connp, HTP_LOG_MARK, HTP_LOG_INFO, 0, "Outbound parser is in HTP_STREAM_STOP");
1278
1279
0
        return HTP_STREAM_STOP;
1280
0
    }
1281
1282
    // Return if the connection has had a fatal error
1283
57.6k
    if (connp->out_status == HTP_STREAM_ERROR) {
1284
40
        htp_log(connp, HTP_LOG_MARK, HTP_LOG_ERROR, 0, "Outbound parser is in HTP_STREAM_ERROR");
1285
1286
        #ifdef HTP_DEBUG
1287
        fprintf(stderr, "htp_connp_res_data: returning HTP_STREAM_DATA (previous error)\n");
1288
        #endif
1289
1290
40
        return HTP_STREAM_ERROR;
1291
40
    }
1292
1293
    // Sanity check: we must have a transaction pointer if the state is not IDLE (no outbound transaction)
1294
57.6k
    if ((connp->out_tx == NULL)&&(connp->out_state != htp_connp_RES_IDLE)) {
1295
0
        connp->out_status = HTP_STREAM_ERROR;
1296
1297
0
        htp_log(connp, HTP_LOG_MARK, HTP_LOG_ERROR, 0, "Missing outbound transaction data");
1298
1299
0
        return HTP_STREAM_ERROR;
1300
0
    }
1301
1302
    // If the length of the supplied data chunk is zero, proceed
1303
    // only if the stream has been closed. We do not allow zero-sized
1304
    // chunks in the API, but we use it internally to force the parsers
1305
    // to finalize parsing.
1306
57.6k
    if (len == 0 && connp->out_status != HTP_STREAM_CLOSED) {
1307
0
        htp_log(connp, HTP_LOG_MARK, HTP_LOG_ERROR, 0, "Zero-length data chunks are not allowed");
1308
1309
        #ifdef HTP_DEBUG
1310
        fprintf(stderr, "htp_connp_res_data: returning HTP_STREAM_DATA (zero-length chunk)\n");
1311
        #endif
1312
1313
0
        return HTP_STREAM_CLOSED;
1314
0
    }
1315
1316
    // Remember the timestamp of the current response data chunk
1317
57.6k
    if (timestamp != NULL) {
1318
0
        memcpy(&connp->out_timestamp, timestamp, sizeof (*timestamp));
1319
0
    }
1320
1321
    // Store the current chunk information
1322
57.6k
    connp->out_current_data = (unsigned char *) data;
1323
57.6k
    connp->out_current_len = len;
1324
57.6k
    connp->out_current_read_offset = 0;
1325
57.6k
    connp->out_current_consume_offset = 0;
1326
57.6k
    connp->out_current_receiver_offset = 0;
1327
1328
57.6k
    htp_conn_track_outbound_data(connp->conn, len, timestamp);
1329
1330
    // Return without processing any data if the stream is in tunneling
1331
    // mode (which it would be after an initial CONNECT transaction.
1332
57.6k
    if (connp->out_status == HTP_STREAM_TUNNEL) {
1333
        #ifdef HTP_DEBUG
1334
        fprintf(stderr, "htp_connp_res_data: returning HTP_STREAM_TUNNEL\n");
1335
        #endif
1336
1337
197
        return HTP_STREAM_TUNNEL;
1338
197
    }
1339
1340
    // Invoke a processor, in a loop, until an error
1341
    // occurs or until we run out of data. Many processors
1342
    // will process a request, each pointing to the next
1343
    // processor that needs to run.
1344
2.59M
    for (;;) {
1345
        #ifdef HTP_DEBUG
1346
        fprintf(stderr, "htp_connp_res_data: out state=%s, progress=%s\n",
1347
                htp_connp_out_state_as_string(connp),
1348
                htp_tx_response_progress_as_string(connp->out_tx));
1349
        #endif
1350
1351
        // Return if there's been an error
1352
        // or if we've run out of data. We are relying
1353
        // on processors to add error messages, so we'll
1354
        // keep quiet here.
1355
2.59M
        htp_status_t rc;
1356
1357
        //handle gap
1358
2.59M
        if (data == NULL && len > 0) {
1359
3.89k
            if (connp->out_state == htp_connp_RES_BODY_IDENTITY_CL_KNOWN ||
1360
3.89k
                connp->out_state == htp_connp_RES_BODY_IDENTITY_STREAM_CLOSE) {
1361
2.55k
                rc = connp->out_state(connp);
1362
2.55k
            } else if (connp->out_state == htp_connp_RES_FINALIZE) {
1363
802
                rc = htp_tx_state_response_complete_ex(connp->out_tx, 0);
1364
802
            } else {
1365
540
                htp_log(connp, HTP_LOG_MARK, HTP_LOG_ERROR, 0, "Gaps are not allowed during this state");
1366
540
                return HTP_STREAM_CLOSED;
1367
540
            }
1368
2.59M
        } else {
1369
2.59M
            rc = connp->out_state(connp);
1370
2.59M
        }
1371
2.59M
        if (rc == HTP_OK) {
1372
2.53M
            if (connp->out_status == HTP_STREAM_TUNNEL) {
1373
                #ifdef HTP_DEBUG
1374
                fprintf(stderr, "htp_connp_res_data: returning HTP_STREAM_TUNNEL\n");
1375
                #endif
1376
1377
18
                return HTP_STREAM_TUNNEL;
1378
18
            }
1379
1380
2.53M
            rc = htp_res_handle_state_change(connp);
1381
2.53M
        }
1382
1383
2.59M
        if (rc != HTP_OK) {
1384
            // Do we need more data?
1385
56.8k
            if ((rc == HTP_DATA) || (rc == HTP_DATA_BUFFER)) {
1386
51.8k
                htp_connp_res_receiver_send_data(connp, 0 /* not last */);
1387
1388
51.8k
                if (rc == HTP_DATA_BUFFER) {
1389
15.0k
                    if (htp_connp_res_buffer(connp) != HTP_OK) {
1390
24
                        connp->out_status = HTP_STREAM_ERROR;
1391
24
                        return HTP_STREAM_ERROR;
1392
24
                    }
1393
15.0k
                }
1394
1395
                #ifdef HTP_DEBUG
1396
                fprintf(stderr, "htp_connp_res_data: returning HTP_STREAM_DATA\n");
1397
                #endif
1398
1399
51.8k
                connp->out_status = HTP_STREAM_DATA;
1400
1401
51.8k
                return HTP_STREAM_DATA;
1402
51.8k
            }
1403
1404
            // Check for stop
1405
4.98k
            if (rc == HTP_STOP) {
1406
                #ifdef HTP_DEBUG
1407
                fprintf(stderr, "htp_connp_res_data: returning HTP_STREAM_STOP\n");
1408
                #endif
1409
1410
0
                connp->out_status = HTP_STREAM_STOP;
1411
1412
0
                return HTP_STREAM_STOP;
1413
0
            }
1414
1415
            // Check for suspended parsing
1416
4.98k
            if (rc == HTP_DATA_OTHER) {
1417
                // We might have actually consumed the entire data chunk?
1418
4.75k
                if (connp->out_current_read_offset >= connp->out_current_len) {
1419
                    #ifdef HTP_DEBUG
1420
                    fprintf(stderr, "htp_connp_res_data: returning HTP_STREAM_DATA (suspended parsing)\n");
1421
                    #endif
1422
1423
1.73k
                    connp->out_status = HTP_STREAM_DATA;
1424
1425
                    // Do not send STREAM_DATE_DATA_OTHER if we've
1426
                    // consumed the entire chunk
1427
1.73k
                    return HTP_STREAM_DATA;
1428
3.02k
                } else {
1429
                    #ifdef HTP_DEBUG
1430
                    fprintf(stderr, "htp_connp_res_data: returning HTP_STREAM_DATA_OTHER\n");
1431
                    #endif
1432
1433
3.02k
                    connp->out_status = HTP_STREAM_DATA_OTHER;
1434
1435
                    // Partial chunk consumption
1436
3.02k
                    return HTP_STREAM_DATA_OTHER;
1437
3.02k
                }
1438
4.75k
            }
1439
1440
            #ifdef HTP_DEBUG
1441
            fprintf(stderr, "htp_connp_res_data: returning HTP_STREAM_ERROR\n");
1442
            #endif
1443
1444
            // Permanent stream error.
1445
232
            connp->out_status = HTP_STREAM_ERROR;
1446
1447
232
            return HTP_STREAM_ERROR;
1448
4.98k
        }
1449
2.59M
    }
1450
57.4k
}