Coverage Report

Created: 2025-07-11 06:42

/src/libhtp/htp/htp_response.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
53.8k
#define OUT_TEST_NEXT_BYTE_OR_RETURN(X) \
44
53.8k
if ((X)->out_current_read_offset >= (X)->out_current_len) { \
45
18.7k
    return HTP_DATA; \
46
18.7k
}
47
48
2.28M
#define OUT_PEEK_NEXT(X) \
49
2.28M
if ((X)->out_current_read_offset >= (X)->out_current_len) { \
50
26.5k
    (X)->out_next_byte = -1; \
51
2.25M
} else { \
52
2.25M
    (X)->out_next_byte = (X)->out_current_data[(X)->out_current_read_offset]; \
53
2.25M
}
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
49.1M
#define OUT_COPY_BYTE_OR_RETURN(X) \
76
49.1M
if ((X)->out_current_read_offset < (X)->out_current_len) { \
77
49.0M
    (X)->out_next_byte = (X)->out_current_data[(X)->out_current_read_offset]; \
78
49.0M
    (X)->out_current_read_offset++; \
79
49.0M
    (X)->out_stream_offset++; \
80
49.0M
} else { \
81
35.5k
    return HTP_DATA_BUFFER; \
82
35.5k
}
83
84
56.3k
#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
118k
static htp_status_t htp_connp_res_receiver_send_data(htp_connp_t *connp, int is_last) {
94
118k
    if (connp->out_data_receiver_hook == NULL) return HTP_OK;
95
96
73.8k
    htp_tx_data_t d;
97
73.8k
    d.tx = connp->out_tx;
98
73.8k
    d.data = connp->out_current_data + connp->out_current_receiver_offset;
99
73.8k
    d.len = connp->out_current_read_offset - connp->out_current_receiver_offset;
100
73.8k
    d.is_last = is_last;
101
102
73.8k
    htp_status_t rc = htp_hook_run_all(connp->out_data_receiver_hook, &d);
103
73.8k
    if (rc != HTP_OK) return rc;
104
105
73.8k
    connp->out_current_receiver_offset = connp->out_current_read_offset;
106
107
73.8k
    return HTP_OK;
108
73.8k
}
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
108k
htp_status_t htp_connp_res_receiver_finalize_clear(htp_connp_t *connp) {
118
108k
    if (connp->out_data_receiver_hook == NULL) return HTP_OK;
119
120
47.3k
    htp_status_t rc = htp_connp_res_receiver_send_data(connp, 1 /* last */);
121
122
47.3k
    connp->out_data_receiver_hook = NULL;
123
124
47.3k
    return rc;
125
108k
}
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
47.3k
static htp_status_t htp_connp_res_receiver_set(htp_connp_t *connp, htp_hook_t *data_receiver_hook) {
135
47.3k
    htp_status_t rc = htp_connp_res_receiver_finalize_clear(connp);
136
137
47.3k
    connp->out_data_receiver_hook = data_receiver_hook;
138
47.3k
    connp->out_current_receiver_offset = connp->out_current_read_offset;
139
140
47.3k
    return rc;
141
47.3k
}
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
1.72M
static htp_status_t htp_res_handle_state_change(htp_connp_t *connp) {
151
1.72M
    if (connp->out_state_previous == connp->out_state) return HTP_OK;
152
153
221k
    if (connp->out_state == htp_connp_RES_HEADERS) {
154
47.3k
        htp_status_t rc = HTP_OK;
155
156
47.3k
        switch (connp->out_tx->response_progress) {
157
47.3k
            case HTP_RESPONSE_HEADERS:
158
47.3k
                rc = htp_connp_res_receiver_set(connp, connp->out_tx->cfg->hook_response_header_data);
159
47.3k
                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
47.3k
        }
169
170
47.3k
        if (rc != HTP_OK) return rc;
171
47.3k
    }
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
221k
    connp->out_state_previous = connp->out_state;
183
184
221k
    return HTP_OK;
185
221k
}
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
74.6k
static htp_status_t htp_connp_res_buffer(htp_connp_t *connp) {
196
74.6k
    if (connp->out_current_data == NULL) return HTP_OK;
197
    
198
71.9k
    unsigned char *data = connp->out_current_data + connp->out_current_consume_offset;
199
71.9k
    size_t len = connp->out_current_read_offset - connp->out_current_consume_offset;
200
201
    // Check the hard (buffering) limit.
202
203
71.9k
    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
71.9k
    if (connp->out_header != NULL) {
208
5.73k
        newlen += bstr_len(connp->out_header);
209
5.73k
    }
210
211
71.9k
    if (newlen > connp->out_tx->cfg->field_limit_hard) {
212
29
        htp_log(connp, HTP_LOG_MARK, HTP_LOG_ERROR, 0, "Response the buffer limit: size %zd limit %zd.",
213
29
                newlen, connp->out_tx->cfg->field_limit_hard);
214
29
        return HTP_ERROR;
215
29
    }
216
217
    // Copy the data remaining in the buffer.
218
219
71.9k
    if (connp->out_buf == NULL) {
220
31.0k
        connp->out_buf = malloc(len);
221
31.0k
        if (connp->out_buf == NULL) return HTP_ERROR;
222
31.0k
        memcpy(connp->out_buf, data, len);
223
31.0k
        connp->out_buf_size = len;
224
40.8k
    } else {
225
40.8k
        size_t newsize = connp->out_buf_size + len;
226
40.8k
        unsigned char *newbuf = realloc(connp->out_buf, newsize);
227
40.8k
        if (newbuf == NULL) return HTP_ERROR;
228
40.8k
        connp->out_buf = newbuf;
229
40.8k
        memcpy(connp->out_buf + connp->out_buf_size, data, len);
230
40.8k
        connp->out_buf_size = newsize;
231
40.8k
    }
232
233
    // Reset the consumer position.
234
71.9k
    connp->out_current_consume_offset = connp->out_current_read_offset;
235
236
71.9k
    return HTP_OK;
237
71.9k
}
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.06M
static htp_status_t htp_connp_res_consolidate_data(htp_connp_t *connp, unsigned char **data, size_t *len) {    
250
2.06M
    if (connp->out_buf == NULL) {
251
        // We do not have any data buffered; point to the current data chunk.
252
2.03M
        *data = connp->out_current_data + connp->out_current_consume_offset;
253
2.03M
        *len = connp->out_current_read_offset - connp->out_current_consume_offset;
254
2.03M
    } else {
255
        // We do have data in the buffer. Add data from the current
256
        // chunk, and point to the consolidated buffer.
257
32.5k
        if (htp_connp_res_buffer(connp) != HTP_OK) {
258
13
            return HTP_ERROR;
259
13
        }
260
261
32.4k
        *data = connp->out_buf;
262
32.4k
        *len = connp->out_buf_size;
263
32.4k
    }
264
265
2.06M
    return HTP_OK;
266
2.06M
}
267
268
/**
269
 * Clears buffered outbound data and resets the consumer position to the reader position.
270
 *
271
 * @param[in] connp
272
 */
273
2.01M
static void htp_connp_res_clear_buffer(htp_connp_t *connp) {
274
2.01M
    connp->out_current_consume_offset = connp->out_current_read_offset;
275
276
2.01M
    if (connp->out_buf != NULL) {
277
30.5k
        free(connp->out_buf);
278
30.5k
        connp->out_buf = NULL;
279
30.5k
        connp->out_buf_size = 0;
280
30.5k
    }
281
2.01M
}
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
13.0k
htp_status_t htp_connp_RES_BODY_IDENTITY_STREAM_CLOSE(htp_connp_t *connp) {        
532
    // Consume all data from the input buffer.
533
13.0k
    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
13.0k
    if (bytes_to_consume != 0) {
539
10.4k
        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
10.4k
        if (rc != HTP_OK) return rc;
541
542
        // Adjust the counters.
543
10.4k
        connp->out_current_read_offset += bytes_to_consume;
544
10.4k
        connp->out_current_consume_offset += bytes_to_consume;
545
10.4k
        connp->out_stream_offset += bytes_to_consume;        
546
10.4k
    }
547
548
    // Have we seen the entire response body?
549
13.0k
    if (connp->out_status == HTP_STREAM_CLOSED) {
550
2.33k
        connp->out_state = htp_connp_RES_FINALIZE;
551
2.33k
        return HTP_OK;
552
2.33k
    }
553
   
554
10.7k
    return HTP_DATA;
555
13.0k
}
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
46.0k
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
46.0k
    if (connp->out_tx->request_method_number == HTP_M_CONNECT) {
568
2.25k
        if ((connp->out_tx->response_status_number >= 200)
569
2.25k
                && (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
1.70k
            connp->out_state = htp_connp_RES_FINALIZE;
576
577
            // we may have response headers
578
1.70k
            htp_status_t rc = htp_tx_state_response_headers(connp->out_tx);
579
1.70k
            return rc;
580
1.70k
        } else if (connp->out_tx->response_status_number == 407) {
581
            // proxy telling us to auth
582
1
            if (connp->in_status != HTP_STREAM_ERROR)
583
1
                connp->in_status = HTP_STREAM_DATA;
584
553
        } else {
585
            // This is a failed CONNECT stream, which means that
586
            // we can unblock request parsing
587
553
            if (connp->in_status != HTP_STREAM_ERROR)
588
552
                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
553
            connp->out_data_other_at_tx_end = 1;
594
553
        }
595
2.25k
    }
596
597
44.3k
    htp_header_t *cl = htp_table_get_c(connp->out_tx->response_headers, "content-length");
598
44.3k
    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
44.3k
    if (connp->out_tx->response_status_number == 101) {
607
39
        if (te == NULL && cl == NULL) {
608
39
            connp->out_state = htp_connp_RES_FINALIZE;
609
610
39
            if (connp->in_status != HTP_STREAM_ERROR)
611
39
                connp->in_status = HTP_STREAM_TUNNEL;
612
39
            connp->out_status = HTP_STREAM_TUNNEL;
613
614
            // we may have response headers
615
39
            htp_status_t rc = htp_tx_state_response_headers(connp->out_tx);
616
39
            return rc;
617
39
        } else {
618
0
            htp_log(connp, HTP_LOG_MARK, HTP_LOG_WARNING, 0, "Switching Protocol with Content-Length");
619
0
        }
620
39
    }
621
622
    // Check for an interim "100 Continue" response. Ignore it if found, and revert back to RES_LINE.
623
44.3k
    if (connp->out_tx->response_status_number == 100 && te == NULL) {
624
20.6k
        int is100continue = 1;
625
20.6k
        if (cl != NULL){
626
0
            if (htp_parse_content_length(cl->value, connp) > 0) {
627
0
                is100continue = 0;
628
0
            }
629
0
        }
630
20.6k
        if (is100continue) {
631
20.6k
            if (connp->out_tx->seen_100continue != 0) {
632
19.7k
                htp_log(connp, HTP_LOG_MARK, HTP_LOG_ERROR, 0, "Already seen 100-Continue.");
633
19.7k
            }
634
635
            // Ignore any response headers seen so far.
636
20.6k
            htp_header_t *h = NULL;
637
27.6k
            for (size_t i = 0, n = htp_table_size(connp->out_tx->response_headers); i < n; i++) {
638
6.96k
                h = htp_table_get_index(connp->out_tx->response_headers, i, NULL);
639
6.96k
                bstr_free(h->name);
640
6.96k
                bstr_free(h->value);
641
6.96k
                free(h);
642
6.96k
            }
643
644
20.6k
            htp_table_clear(connp->out_tx->response_headers);
645
646
            // Expecting to see another response line next.
647
20.6k
            connp->out_state = htp_connp_RES_LINE;
648
20.6k
            connp->out_tx->response_progress = HTP_RESPONSE_LINE;
649
20.6k
            connp->out_tx->seen_100continue++;
650
651
20.6k
            return HTP_OK;
652
20.6k
        }
653
20.6k
    }
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
23.6k
    if (connp->out_tx->response_status_number >= 400 &&
659
23.6k
        connp->out_tx->response_status_number <= 499 &&
660
23.6k
        connp->in_content_length > 0 &&
661
23.6k
        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
23.6k
    if (connp->out_tx->request_method_number == HTP_M_HEAD) {
674
        // There's no response body whatsoever
675
505
        connp->out_tx->response_transfer_coding = HTP_CODING_NO_BODY;
676
505
        connp->out_state = htp_connp_RES_FINALIZE;
677
505
    }
678
23.1k
    else if (((connp->out_tx->response_status_number >= 100) && (connp->out_tx->response_status_number <= 199))
679
23.1k
            || (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
20.8k
        if (te == NULL && cl == NULL) {
683
20.8k
            connp->out_tx->response_transfer_coding = HTP_CODING_NO_BODY;
684
20.8k
            connp->out_state = htp_connp_RES_FINALIZE;
685
20.8k
        } else {
686
0
            htp_log(connp, HTP_LOG_MARK, HTP_LOG_WARNING, 0, "Unexpected Response body");
687
0
        }
688
20.8k
    }
689
    // Hack condition to check that we do not assume "no body"
690
23.6k
    if (connp->out_state != htp_connp_RES_FINALIZE) {
691
        // We have a response body
692
2.29k
        htp_header_t *ct = htp_table_get_c(connp->out_tx->response_headers, "content-type");
693
2.29k
        if (ct != NULL) {
694
46
            connp->out_tx->response_content_type = bstr_dup_lower(ct->value);
695
46
            if (connp->out_tx->response_content_type == NULL) return HTP_ERROR;
696
697
            // Ignore parameters
698
46
            unsigned char *data = bstr_ptr(connp->out_tx->response_content_type);
699
46
            size_t len = bstr_len(ct->value);
700
46
            size_t newlen = 0;
701
19.9k
            while (newlen < len) {
702
                // TODO Some platforms may do things differently here.
703
19.9k
                if (htp_is_space(data[newlen]) || (data[newlen] == ';')) {
704
20
                    bstr_adjust_len(connp->out_tx->response_content_type, newlen);
705
20
                    break;
706
20
                }
707
708
19.9k
                newlen++;
709
19.9k
            }
710
46
        }
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
2.29k
        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
2.29k
        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
2.29k
        } 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
2.29k
            if (ct != NULL) {
775
                // TODO Handle multipart/byteranges
776
46
                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
46
            }
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
2.29k
            connp->out_state = htp_connp_RES_BODY_IDENTITY_STREAM_CLOSE;
787
2.29k
            connp->out_tx->response_transfer_coding = HTP_CODING_IDENTITY;
788
2.29k
            connp->out_tx->response_progress = HTP_RESPONSE_BODY;
789
2.29k
            connp->out_body_data_left = -1;
790
2.29k
        }
791
2.29k
    }
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
23.6k
    htp_status_t rc = htp_tx_state_response_headers(connp->out_tx);
797
23.6k
    if (rc != HTP_OK) return rc;
798
799
23.6k
    return HTP_OK;
800
23.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
68.8k
htp_status_t htp_connp_RES_HEADERS(htp_connp_t *connp) {
809
68.8k
    int endwithcr;
810
68.8k
    int lfcrending = 0;
811
812
21.5M
    for (;;) {
813
21.5M
        if (connp->out_status == HTP_STREAM_CLOSED) {
814
            // Finalize sending raw trailer data.
815
1.30k
            htp_status_t rc = htp_connp_res_receiver_finalize_clear(connp);
816
1.30k
            if (rc != HTP_OK) return rc;
817
818
            // Run hook response_TRAILER.
819
1.30k
            rc = htp_hook_run_all(connp->cfg->hook_response_trailer, connp->out_tx);
820
1.30k
            if (rc != HTP_OK) return rc;
821
822
1.30k
            connp->out_state = htp_connp_RES_FINALIZE;
823
1.30k
            return HTP_OK;
824
1.30k
        }
825
21.5M
        OUT_COPY_BYTE_OR_RETURN(connp);
826
827
        // Have we reached the end of the line?
828
21.5M
        if (connp->out_next_byte != LF && connp->out_next_byte != CR) {
829
20.8M
            lfcrending = 0;
830
20.8M
        } else {
831
642k
            endwithcr = 0;
832
642k
            if (connp->out_next_byte == CR) {
833
319k
                OUT_PEEK_NEXT(connp);
834
319k
                if (connp->out_next_byte == -1) {
835
2.55k
                    return HTP_DATA_BUFFER;
836
317k
                } else if (connp->out_next_byte == LF) {
837
77.8k
                    OUT_COPY_BYTE_OR_RETURN(connp);
838
77.8k
                    if (lfcrending) {
839
                        // Handling LFCRCRLFCRLF
840
                        // These 6 characters mean only 2 end of lines
841
44.2k
                        OUT_PEEK_NEXT(connp);
842
44.2k
                        if (connp->out_next_byte == CR) {
843
16.8k
                            OUT_COPY_BYTE_OR_RETURN(connp);
844
16.8k
                            connp->out_current_consume_offset++;
845
16.8k
                            OUT_PEEK_NEXT(connp);
846
16.8k
                            if (connp->out_next_byte == LF) {
847
315
                                OUT_COPY_BYTE_OR_RETURN(connp);
848
315
                                connp->out_current_consume_offset++;
849
315
                                htp_log(connp, HTP_LOG_MARK, HTP_LOG_WARNING, 0,
850
315
                                        "Weird response end of lines mix");
851
315
                            }
852
16.8k
                        }
853
44.2k
                    }
854
239k
                } else if (connp->out_next_byte == CR) {
855
159k
                    continue;
856
159k
                }
857
157k
                lfcrending = 0;
858
157k
                endwithcr = 1;
859
322k
            } else {
860
                // connp->out_next_byte == LF
861
322k
                OUT_PEEK_NEXT(connp);
862
322k
                lfcrending = 0;
863
322k
                if (connp->out_next_byte == CR) {
864
                    // hanldes LF-CR sequence as end of line
865
88.6k
                    OUT_COPY_BYTE_OR_RETURN(connp);
866
88.6k
                    lfcrending = 1;
867
88.6k
                }
868
322k
            }
869
870
480k
            unsigned char *data;
871
480k
            size_t len;
872
873
480k
            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
480k
            if (endwithcr && len < 2) {
879
27.1k
                continue;
880
27.1k
            }
881
882
            #ifdef HTP_DEBUG
883
            fprint_raw_data(stderr, __func__, data, len);
884
            #endif
885
886
453k
            int next_no_lf = 0;
887
453k
            if (connp->out_current_read_offset < connp->out_current_len &&
888
453k
                connp->out_current_data[connp->out_current_read_offset] != LF) {
889
411k
                next_no_lf = 1;
890
411k
            }
891
            // Should we terminate headers?
892
453k
            if (htp_connp_is_line_terminator(connp, data, len, next_no_lf)) {
893
                // Parse previous header, if any.
894
46.0k
                if (connp->out_header != NULL) {
895
3.49k
                    if (connp->cfg->process_response_header(connp, bstr_ptr(connp->out_header),
896
3.49k
                            bstr_len(connp->out_header)) != HTP_OK) return HTP_ERROR;
897
898
3.49k
                    bstr_free(connp->out_header);
899
3.49k
                    connp->out_header = NULL;
900
3.49k
                }
901
902
46.0k
                htp_connp_res_clear_buffer(connp);
903
904
                // We've seen all response headers.
905
46.0k
                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
46.0k
                    connp->out_state = htp_connp_RES_BODY_DETERMINE;
910
46.0k
                } 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
46.0k
                return HTP_OK;
926
46.0k
            }
927
928
406k
            htp_chomp(data, &len);
929
930
            // Check for header folding.
931
406k
            if (htp_connp_is_line_folded(data, len) == 0) {
932
                // New header line.
933
934
                // Parse previous header, if any.
935
235k
                if (connp->out_header != NULL) {
936
91.4k
                    if (connp->cfg->process_response_header(connp, bstr_ptr(connp->out_header),
937
91.4k
                            bstr_len(connp->out_header)) != HTP_OK) return HTP_ERROR;
938
939
91.4k
                    bstr_free(connp->out_header);
940
91.4k
                    connp->out_header = NULL;
941
91.4k
                }
942
943
235k
                OUT_PEEK_NEXT(connp);
944
945
235k
                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
211k
                    if (connp->cfg->process_response_header(connp, data, len) != HTP_OK) return HTP_ERROR;
948
211k
                } else {
949
                    // Keep the partial header data for parsing later.
950
24.3k
                    connp->out_header = bstr_dup_mem(data, len);
951
24.3k
                    if (connp->out_header == NULL) return HTP_ERROR;
952
24.3k
                }
953
235k
            } else {
954
                // Folding; check that there's a previous header line to add to.
955
171k
                if (connp->out_header == NULL) {
956
                    // Invalid folding.
957
958
                    // Warn only once per transaction.
959
70.9k
                    if (!(connp->out_tx->flags & HTP_INVALID_FOLDING)) {
960
2.76k
                        connp->out_tx->flags |= HTP_INVALID_FOLDING;
961
2.76k
                        htp_log(connp, HTP_LOG_MARK, HTP_LOG_WARNING, 0, "Invalid response field folding");
962
2.76k
                    }
963
964
                    // Keep the header data for parsing later.
965
70.9k
                    size_t trim = 0;
966
80.3k
                    while(trim < len) {
967
12.0k
                        if (!htp_is_folding_char(data[trim])) {
968
2.69k
                            break;
969
2.69k
                        }
970
9.39k
                        trim++;
971
9.39k
                    }
972
70.9k
                    connp->out_header = bstr_dup_mem(data + trim, len - trim);
973
70.9k
                    if (connp->out_header == NULL) return HTP_ERROR;
974
100k
                } else {
975
100k
                    size_t colon_pos = 0;
976
4.65M
                    while ((colon_pos < len) && (data[colon_pos] != ':')) colon_pos++;
977
978
100k
                    if (colon_pos < len &&
979
100k
                        bstr_chr(connp->out_header, ':') >= 0 &&
980
100k
                        connp->out_tx->response_protocol_number == HTP_PROTOCOL_1_1) {
981
                        // Warn only once per transaction.
982
495
                        if (!(connp->out_tx->flags & HTP_INVALID_FOLDING)) {
983
239
                            connp->out_tx->flags |= HTP_INVALID_FOLDING;
984
239
                            htp_log(connp, HTP_LOG_MARK, HTP_LOG_WARNING, 0, "Invalid response field folding");
985
239
                        }
986
495
                        if (connp->cfg->process_response_header(connp, bstr_ptr(connp->out_header),
987
495
                            bstr_len(connp->out_header)) != HTP_OK)
988
0
                            return HTP_ERROR;
989
495
                        bstr_free(connp->out_header);
990
495
                        connp->out_header = bstr_dup_mem(data+1, len-1);
991
495
                        if (connp->out_header == NULL)
992
0
                            return HTP_ERROR;
993
100k
                    } else {
994
                        // Add to the existing header.
995
100k
                        if (bstr_len(connp->out_header) < HTP_MAX_HEADER_FOLDED) {
996
99.8k
                            bstr *new_out_header = bstr_add_mem(connp->out_header, data, len);
997
99.8k
                            if (new_out_header == NULL)
998
0
                                return HTP_ERROR;
999
99.8k
                            connp->out_header = new_out_header;
1000
99.8k
                        } else {
1001
311
                            htp_log(connp, HTP_LOG_MARK, HTP_LOG_WARNING, 0, "Response field length exceeds folded maximum");
1002
311
                        }
1003
100k
                    }
1004
100k
                }
1005
171k
            }
1006
1007
406k
            htp_connp_res_clear_buffer(connp);
1008
406k
        }
1009
21.5M
    }
1010
1011
0
    return HTP_ERROR;
1012
68.8k
}
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
294k
htp_status_t htp_connp_RES_LINE(htp_connp_t *connp) {
1021
17.5M
    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
17.5M
        if (connp->out_status != HTP_STREAM_CLOSED) {
1024
            // Get one byte
1025
17.5M
            OUT_COPY_BYTE_OR_RETURN(connp);
1026
17.5M
        }
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
17.5M
        if (connp->out_next_byte == CR) {
1032
27.7k
            OUT_PEEK_NEXT(connp);
1033
27.7k
            if (connp->out_next_byte == -1) {
1034
3.99k
                return HTP_DATA_BUFFER;
1035
23.7k
            } else if (connp->out_next_byte == LF) {
1036
5.17k
                continue;
1037
5.17k
            }
1038
18.5k
            connp->out_next_byte = LF;
1039
18.5k
        }
1040
17.5M
        if ((connp->out_next_byte == LF)||(connp->out_status == HTP_STREAM_CLOSED)) {
1041
279k
            unsigned char *data;
1042
279k
            size_t len;
1043
1044
279k
            if (htp_connp_res_consolidate_data(connp, &data, &len) != HTP_OK) {
1045
10
                return HTP_ERROR;
1046
10
            }
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
279k
            if (htp_connp_is_line_ignorable(connp, data, len)) {
1054
67.0k
                if (connp->out_status == HTP_STREAM_CLOSED) {
1055
31
                    connp->out_state = htp_connp_RES_FINALIZE;
1056
31
                }
1057
                // We have an empty/whitespace line, which we'll note, ignore and move on
1058
67.0k
                connp->out_tx->response_ignored_lines++;
1059
1060
                // TODO How many lines are we willing to accept?
1061
1062
                // Start again
1063
67.0k
                htp_connp_res_clear_buffer(connp);
1064
1065
67.0k
                return HTP_OK;
1066
67.0k
            }
1067
1068
            // Deallocate previous response line allocations, which we would have on a 100 response.
1069
1070
212k
            if (connp->out_tx->response_line != NULL) {
1071
20.6k
                bstr_free(connp->out_tx->response_line);
1072
20.6k
                connp->out_tx->response_line = NULL;
1073
20.6k
            }
1074
1075
212k
            if (connp->out_tx->response_protocol != NULL) {
1076
20.6k
                bstr_free(connp->out_tx->response_protocol);
1077
20.6k
                connp->out_tx->response_protocol = NULL;
1078
20.6k
            }
1079
1080
212k
            if (connp->out_tx->response_status != NULL) {
1081
20.6k
                bstr_free(connp->out_tx->response_status);
1082
20.6k
                connp->out_tx->response_status = NULL;
1083
20.6k
            }
1084
1085
212k
            if (connp->out_tx->response_message != NULL) {
1086
1.49k
                bstr_free(connp->out_tx->response_message);
1087
1.49k
                connp->out_tx->response_message = NULL;
1088
1.49k
            }
1089
1090
            // Process response line.           
1091
1092
212k
            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
212k
            if (htp_treat_response_line_as_body(data, len)) {
1099
                // if we have a next line beginning with H, skip this one
1100
165k
                if (connp->out_current_read_offset+1 < connp->out_current_len && (connp->out_current_data[connp->out_current_read_offset] == 'H' || len <= 2)) {
1101
59.0k
                    connp->out_tx->response_ignored_lines++;
1102
59.0k
                    htp_connp_res_clear_buffer(connp);
1103
59.0k
                    return HTP_OK;
1104
59.0k
                }
1105
105k
                connp->out_tx->response_content_encoding_processing = HTP_COMPRESSION_NONE;
1106
1107
105k
                connp->out_current_consume_offset = connp->out_current_read_offset;
1108
105k
                htp_status_t rc = htp_tx_res_process_body_data_ex(connp->out_tx, data, len + chomp_result);
1109
105k
                htp_connp_res_clear_buffer(connp);
1110
105k
                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
105k
                if (connp->out_current_len <= connp->out_current_read_offset) {
1118
8.28k
                    connp->out_tx->response_transfer_coding = HTP_CODING_IDENTITY;
1119
8.28k
                    connp->out_tx->response_progress = HTP_RESPONSE_BODY;
1120
8.28k
                    connp->out_body_data_left = -1;
1121
8.28k
                    connp->out_state = htp_connp_RES_FINALIZE;
1122
8.28k
                }
1123
1124
105k
                return HTP_OK;
1125
105k
            }
1126
1127
47.3k
            connp->out_tx->response_line = bstr_dup_mem(data, len);
1128
47.3k
            if (connp->out_tx->response_line == NULL) return HTP_ERROR;
1129
1130
47.3k
            if (connp->cfg->parse_response_line(connp) != HTP_OK) return HTP_ERROR;
1131
1132
47.3k
            htp_status_t rc = htp_tx_state_response_line(connp->out_tx);
1133
47.3k
            if (rc != HTP_OK) return rc;
1134
1135
47.3k
            htp_connp_res_clear_buffer(connp);
1136
1137
            // Move on to the next phase.
1138
47.3k
            connp->out_state = htp_connp_RES_HEADERS;
1139
47.3k
            connp->out_tx->response_progress = HTP_RESPONSE_HEADERS;
1140
1141
47.3k
            return HTP_OK;
1142
47.3k
        }
1143
17.5M
    }
1144
1145
0
    return HTP_ERROR;
1146
294k
}
1147
1148
1.08k
size_t htp_connp_res_data_consumed(htp_connp_t *connp) {
1149
1.08k
    return connp->out_current_read_offset;
1150
1.08k
}
1151
1152
1.32M
htp_status_t htp_connp_RES_FINALIZE(htp_connp_t *connp) {
1153
1.32M
    if (connp->out_status != HTP_STREAM_CLOSED) {
1154
1.31M
        OUT_PEEK_NEXT(connp);
1155
1.31M
        if (connp->out_next_byte == -1) {
1156
9.87k
            return htp_tx_state_response_complete_ex(connp->out_tx, 0);
1157
9.87k
        }
1158
1.30M
        if (connp->out_next_byte != LF || connp->out_current_consume_offset >= connp->out_current_read_offset) {
1159
9.81M
            for (;;) {//;i < max_read; i++) {
1160
9.81M
                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
9.81M
                if (connp->out_next_byte == LF)
1164
1.30M
                    break;
1165
9.81M
            }
1166
1.30M
        }
1167
1.30M
    }
1168
1.30M
    size_t bytes_left;
1169
1.30M
    unsigned char * data;
1170
1171
1.30M
    if (htp_connp_res_consolidate_data(connp, &data, &bytes_left) != HTP_OK) {
1172
2
        return HTP_ERROR;
1173
2
    }
1174
#ifdef HTP_DEBUG
1175
    fprint_raw_data(stderr, "PROBING response finalize", data, bytes_left);
1176
#endif
1177
1.30M
    if (bytes_left == 0) {
1178
        //closing
1179
4.63k
        return htp_tx_state_response_complete_ex(connp->out_tx, 0);
1180
4.63k
    }
1181
1182
1.30M
    if (htp_treat_response_line_as_body(data, bytes_left)) {
1183
        // Interpret remaining bytes as body data
1184
1.28M
        htp_log(connp, HTP_LOG_MARK, HTP_LOG_WARNING, 0, "Unexpected response body");
1185
1.28M
        htp_status_t rc = htp_tx_res_process_body_data_ex(connp->out_tx, data, bytes_left);
1186
1.28M
        htp_connp_res_clear_buffer(connp);
1187
1.28M
        return rc;
1188
1.28M
    }
1189
1190
    //unread last end of line so that RES_LINE works
1191
21.5k
    if (connp->out_current_read_offset < (int64_t)bytes_left) {
1192
1.14k
        connp->out_current_read_offset=0;
1193
20.3k
    } else {
1194
20.3k
        connp->out_current_read_offset-=bytes_left;
1195
20.3k
    }
1196
21.5k
    if (connp->out_current_read_offset < connp->out_current_consume_offset) {
1197
1.09k
        connp->out_current_consume_offset=connp->out_current_read_offset;
1198
1.09k
    }
1199
21.5k
    return htp_tx_state_response_complete_ex(connp->out_tx, 0 /* not hybrid mode */);
1200
1.30M
}
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
53.8k
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
53.8k
    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
35.1k
    connp->out_tx = htp_list_get(connp->conn->transactions, connp->out_next_tx_index);
1224
35.1k
    if (connp->out_tx == NULL) {
1225
28.1k
        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
28.1k
        if (connp->in_state == htp_connp_REQ_FINALIZE) {
1228
21.8k
            htp_tx_state_request_complete(connp->in_tx);
1229
21.8k
        }
1230
28.1k
        connp->out_tx = htp_connp_tx_create(connp);
1231
28.1k
        if (connp->out_tx == NULL) {
1232
1
            return HTP_ERROR;
1233
1
        }
1234
28.1k
        connp->out_tx->parsed_uri = htp_uri_alloc();
1235
28.1k
        if (connp->out_tx->parsed_uri == NULL) {
1236
0
            return HTP_ERROR;
1237
0
        }
1238
28.1k
        connp->out_tx->parsed_uri->path = bstr_dup_c(REQUEST_URI_NOT_SEEN);
1239
28.1k
        if (connp->out_tx->parsed_uri->path == NULL) {
1240
0
            return HTP_ERROR;
1241
0
        }
1242
28.1k
        connp->out_tx->request_uri = bstr_dup_c(REQUEST_URI_NOT_SEEN);
1243
28.1k
        if (connp->out_tx->request_uri == NULL) {
1244
0
            return HTP_ERROR;
1245
0
        }
1246
1247
28.1k
        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
28.1k
        connp->out_next_tx_index++;
1253
28.1k
    } else {
1254
        // We've used one transaction
1255
6.91k
        connp->out_next_tx_index++;
1256
1257
        // TODO Detect state mismatch
1258
1259
6.91k
        connp->out_content_length = -1;
1260
6.91k
        connp->out_body_data_left = -1;
1261
6.91k
    }
1262
1263
35.1k
    htp_status_t rc = htp_tx_state_response_start(connp->out_tx);
1264
35.1k
    if (rc != HTP_OK) return rc;
1265
1266
35.1k
    return HTP_OK;
1267
35.1k
}
1268
1269
76.2k
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
76.2k
    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
76.2k
    if (connp->out_status == HTP_STREAM_ERROR) {
1284
35
        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
35
        return HTP_STREAM_ERROR;
1291
35
    }
1292
1293
    // Sanity check: we must have a transaction pointer if the state is not IDLE (no outbound transaction)
1294
76.2k
    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
76.2k
    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
76.2k
    if (timestamp != NULL) {
1318
0
        memcpy(&connp->out_timestamp, timestamp, sizeof (*timestamp));
1319
0
    }
1320
1321
    // Store the current chunk information
1322
76.2k
    connp->out_current_data = (unsigned char *) data;
1323
76.2k
    connp->out_current_len = len;
1324
76.2k
    connp->out_current_read_offset = 0;
1325
76.2k
    connp->out_current_consume_offset = 0;
1326
76.2k
    connp->out_current_receiver_offset = 0;
1327
1328
76.2k
    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
76.2k
    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
682
        return HTP_STREAM_TUNNEL;
1338
682
    }
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
1.80M
    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
1.80M
        htp_status_t rc;
1356
1357
        //handle gap
1358
1.80M
        if (data == NULL && len > 0) {
1359
2.92k
            if (connp->out_state == htp_connp_RES_BODY_IDENTITY_CL_KNOWN ||
1360
2.92k
                connp->out_state == htp_connp_RES_BODY_IDENTITY_STREAM_CLOSE) {
1361
827
                rc = connp->out_state(connp);
1362
2.09k
            } else if (connp->out_state == htp_connp_RES_FINALIZE) {
1363
1.07k
                rc = htp_tx_state_response_complete_ex(connp->out_tx, 0);
1364
1.07k
            } else {
1365
1.02k
                htp_log(connp, HTP_LOG_MARK, HTP_LOG_ERROR, 0, "Gaps are not allowed during this state");
1366
1.02k
                return HTP_STREAM_CLOSED;
1367
1.02k
            }
1368
1.79M
        } else {
1369
1.79M
            rc = connp->out_state(connp);
1370
1.79M
        }
1371
1.80M
        if (rc == HTP_OK) {
1372
1.72M
            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
39
                return HTP_STREAM_TUNNEL;
1378
39
            }
1379
1380
1.72M
            rc = htp_res_handle_state_change(connp);
1381
1.72M
        }
1382
1383
1.80M
        if (rc != HTP_OK) {
1384
            // Do we need more data?
1385
74.5k
            if ((rc == HTP_DATA) || (rc == HTP_DATA_BUFFER)) {
1386
71.5k
                htp_connp_res_receiver_send_data(connp, 0 /* not last */);
1387
1388
71.5k
                if (rc == HTP_DATA_BUFFER) {
1389
42.1k
                    if (htp_connp_res_buffer(connp) != HTP_OK) {
1390
16
                        connp->out_status = HTP_STREAM_ERROR;
1391
16
                        return HTP_STREAM_ERROR;
1392
16
                    }
1393
42.1k
                }
1394
1395
                #ifdef HTP_DEBUG
1396
                fprintf(stderr, "htp_connp_res_data: returning HTP_STREAM_DATA\n");
1397
                #endif
1398
1399
71.5k
                connp->out_status = HTP_STREAM_DATA;
1400
1401
71.5k
                return HTP_STREAM_DATA;
1402
71.5k
            }
1403
1404
            // Check for stop
1405
2.91k
            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
2.91k
            if (rc == HTP_DATA_OTHER) {
1417
                // We might have actually consumed the entire data chunk?
1418
2.48k
                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
571
                    connp->out_status = HTP_STREAM_DATA;
1424
1425
                    // Do not send STREAM_DATE_DATA_OTHER if we've
1426
                    // consumed the entire chunk
1427
571
                    return HTP_STREAM_DATA;
1428
1.91k
                } else {
1429
                    #ifdef HTP_DEBUG
1430
                    fprintf(stderr, "htp_connp_res_data: returning HTP_STREAM_DATA_OTHER\n");
1431
                    #endif
1432
1433
1.91k
                    connp->out_status = HTP_STREAM_DATA_OTHER;
1434
1435
                    // Partial chunk consumption
1436
1.91k
                    return HTP_STREAM_DATA_OTHER;
1437
1.91k
                }
1438
2.48k
            }
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
430
            connp->out_status = HTP_STREAM_ERROR;
1446
1447
430
            return HTP_STREAM_ERROR;
1448
2.91k
        }
1449
1.80M
    }
1450
75.5k
}