Coverage Report

Created: 2026-11-12 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata/rust/htp/src/response.rs
Line
Count
Source
1
use crate::{
2
    bstr::Bstr,
3
    connection_parser::{ConnectionParser, HtpStreamState, ParserData, State},
4
    decompressors::{Decompressor, HtpContentEncoding},
5
    error::Result,
6
    headers::HeaderFlags,
7
    hook::DataHook,
8
    parsers::{parse_chunked_length, parse_content_length, parse_protocol, parse_status},
9
    request::HtpMethod,
10
    transaction::{
11
        Data, Header, HtpProtocol, HtpRequestProgress, HtpResponseNumber, HtpResponseProgress,
12
        HtpTransferCoding,
13
    },
14
    uri::Uri,
15
    util::{
16
        chomp, is_chunked_ctl_line, is_line_ignorable, is_space, is_valid_chunked_length_data,
17
        take_ascii_whitespace, take_is_space, take_is_space_or_null, take_not_is_space,
18
        take_till_eol, take_till_lf, treat_response_line_as_body, FlagOperations, HtpFlags,
19
    },
20
    HtpStatus,
21
};
22
use nom::{bytes::streaming::take_till as streaming_take_till, error::ErrorKind, Parser as _};
23
use std::{
24
    cmp::{min, Ordering},
25
    mem::take,
26
};
27
use time::OffsetDateTime;
28
29
impl ConnectionParser {
30
    /// Sends outstanding connection data to the currently active data receiver hook.
31
892k
    fn response_receiver_send_data(&mut self, data: &mut ParserData) -> Result<()> {
32
892k
        let data = ParserData::from(data.callback_data());
33
892k
        let resp = self.response_mut();
34
892k
        if resp.is_none() {
35
3
            return Err(HtpStatus::ERROR);
36
892k
        }
37
892k
        let mut tx_data = Data::new(resp.unwrap(), &data);
38
892k
        if let Some(hook) = &self.response_data_receiver_hook {
39
244k
            hook.run_all(self, &mut tx_data)?;
40
        } else {
41
648k
            return Ok(());
42
        };
43
244k
        Ok(())
44
892k
    }
45
46
    /// Finalizes an existing data receiver hook by sending any outstanding data to it. The
47
    /// hook is then removed so that it receives no more data.
48
499k
    pub(crate) fn response_receiver_finalize_clear(
49
499k
        &mut self, input: &mut ParserData,
50
499k
    ) -> Result<()> {
51
499k
        if self.response_data_receiver_hook.is_none() {
52
337k
            return Ok(());
53
161k
        }
54
161k
        let rc = self.response_receiver_send_data(input);
55
161k
        self.response_data_receiver_hook = None;
56
161k
        rc
57
499k
    }
58
59
    /// Configures the data receiver hook.
60
168k
    fn response_receiver_set(&mut self, data_receiver_hook: Option<DataHook>) -> Result<()> {
61
168k
        self.response_data_receiver_hook = data_receiver_hook;
62
168k
        Ok(())
63
168k
    }
64
65
    /// Handles response parser state changes. At the moment, this function is used only
66
    /// to configure data receivers, which are sent raw connection data.
67
3.20M
    fn response_handle_state_change(&mut self, input: &mut ParserData) -> Result<()> {
68
3.20M
        if self.response_state_previous == self.response_state {
69
1.77M
            return Ok(());
70
1.43M
        }
71
72
1.43M
        if self.response_state == State::Headers {
73
168k
            let resp = self.response_mut();
74
168k
            if resp.is_none() {
75
0
                return Err(HtpStatus::ERROR);
76
168k
            }
77
168k
            let resp = resp.unwrap();
78
168k
            let header_fn = Some(resp.cfg.hook_response_header_data.clone());
79
168k
            let trailer_fn = Some(resp.cfg.hook_response_trailer_data.clone());
80
168k
            input.reset_callback_start();
81
82
168k
            match resp.response_progress {
83
7.21k
                HtpResponseProgress::TRAILER => self.response_receiver_set(trailer_fn),
84
                // response_state == State::Headers can have progress LINE after a 100 continue
85
161k
                _ => self.response_receiver_set(header_fn),
86
0
            }?;
87
1.26M
        }
88
        // Same comment as in request_handle_state_change(). Below is a copy.
89
        // Initially, I had the finalization of raw data sending here, but that
90
        // caused the last REQUEST_HEADER_DATA hook to be invoked after the
91
        // REQUEST_HEADERS hook -- which I thought made no sense. For that reason,
92
        // the finalization is now initiated from the request header processing code,
93
        // which is less elegant but provides a better user experience. Having some
94
        // (or all) hooks to be invoked on state change might work better.
95
1.43M
        self.response_state_previous = self.response_state;
96
1.43M
        Ok(())
97
3.20M
    }
98
99
    /// The maximum amount accepted for buffering is controlled
100
    /// by htp_config_t::field_limit.
101
2.02M
    fn check_response_buffer_limit(&mut self, len: usize) -> Result<()> {
102
2.02M
        if len == 0 {
103
22.4k
            return Ok(());
104
1.99M
        }
105
        // Check the hard (buffering) limit.
106
1.99M
        let mut newlen: usize = self.response_buf.len().wrapping_add(len);
107
        // When calculating the size of the buffer, take into account the
108
        // space we're using for the response header buffer.
109
1.99M
        if let Some(response_header) = &self.response_header {
110
76.6k
            newlen = newlen.wrapping_add(response_header.len());
111
1.92M
        }
112
1.99M
        let field_limit = self.cfg.field_limit;
113
1.99M
        if newlen > field_limit {
114
23
            htp_error!(
115
23
                self.logger,
116
23
                HtpLogCode::RESPONSE_FIELD_TOO_LONG,
117
23
                format!(
118
23
                    "Response the buffer limit: size {} limit {}.",
119
23
                    newlen, field_limit
120
23
                )
121
23
            );
122
23
            return Err(HtpStatus::ERROR);
123
1.99M
        }
124
1.99M
        Ok(())
125
2.02M
    }
126
127
    /// Consumes bytes until the end of the current line.
128
    ///
129
    /// Returns HtpStatus::OK on state change, HtpStatus::Error on error, or HtpStatus::DATA
130
    /// when more data is needed.
131
14.5k
    pub(crate) fn response_body_chunked_data_end(&mut self, input: &ParserData) -> Result<()> {
132
        // TODO We shouldn't really see anything apart from CR and LF,
133
        //      so we should warn about anything else.
134
14.5k
        let resp = self.response_mut();
135
14.5k
        if resp.is_none() {
136
0
            return Err(HtpStatus::ERROR);
137
14.5k
        }
138
14.5k
        let resp = resp.unwrap();
139
140
14.5k
        if let Ok((_, line)) = take_till_lf(input.as_slice()) {
141
13.2k
            let len = line.len();
142
13.2k
            self.response_data_consume(input, len);
143
13.2k
            let resp = self.response_mut().unwrap();
144
13.2k
            resp.response_message_len = resp.response_message_len.wrapping_add(len as u64);
145
13.2k
            self.response_state = State::BodyChunkedLength;
146
13.2k
            Ok(())
147
        } else {
148
            // Advance to end. Dont need to buffer
149
1.34k
            resp.response_message_len = resp.response_message_len.wrapping_add(input.len() as u64);
150
1.34k
            self.response_data_consume(input, input.len());
151
1.34k
            Err(HtpStatus::DATA_BUFFER)
152
        }
153
14.5k
    }
154
155
    /// Processes a chunk of data.
156
    ///
157
    /// Returns HtpStatus::OK on state change, HtpStatus::Error on error, or
158
    /// HtpStatus::DATA when more data is needed.
159
20.6k
    pub(crate) fn response_body_chunked_data(&mut self, input: &ParserData) -> Result<()> {
160
20.6k
        if self.response_status == HtpStreamState::CLOSED {
161
27
            self.response_state = State::Finalize;
162
            // Sends close signal to decompressors
163
27
            return self.response_body_data(input.data());
164
20.6k
        }
165
20.6k
        let bytes_to_consume = min(
166
20.6k
            input.len(),
167
20.6k
            self.response_chunked_length.unwrap_or(0) as usize,
168
        );
169
20.6k
        if bytes_to_consume == 0 {
170
730
            return Err(HtpStatus::DATA);
171
19.8k
        }
172
        // Consume the data.
173
19.8k
        self.response_body_data(Some(&input.as_slice()[0..bytes_to_consume]))?;
174
        // Adjust the counters.
175
19.8k
        self.response_data_consume(input, bytes_to_consume);
176
19.8k
        if let Some(len) = &mut self.response_chunked_length {
177
19.8k
            *len -= bytes_to_consume as u64;
178
            // Have we seen the entire chunk?
179
19.8k
            if *len == 0 {
180
13.2k
                self.response_state = State::BodyChunkedDataEnd;
181
13.2k
                return Ok(());
182
6.60k
            }
183
0
        }
184
185
6.60k
        Err(HtpStatus::DATA)
186
20.6k
    }
187
188
    /// Extracts chunk length.
189
    ///
190
    /// Returns Ok(()) on success, Err(HTP_ERROR) on error, or Err(HTP_DATA) when more data is needed.
191
25.4k
    pub(crate) fn response_body_chunked_length(&mut self, input: &mut ParserData) -> Result<()> {
192
25.4k
        let mut data = input.as_slice();
193
        loop {
194
28.8k
            let buf_empty = self.response_buf.is_empty();
195
28.8k
            let resp = self.response_mut();
196
28.8k
            if resp.is_none() {
197
0
                return Err(HtpStatus::ERROR);
198
28.8k
            }
199
28.8k
            let resp = resp.unwrap();
200
201
28.8k
            match take_till_lf(data) {
202
24.4k
                Ok((remaining, line)) => {
203
24.4k
                    self.response_data_consume(input, line.len());
204
24.4k
                    if !buf_empty {
205
480
                        self.check_response_buffer_limit(line.len())?;
206
23.9k
                    }
207
24.4k
                    let mut data2 = take(&mut self.response_buf);
208
24.4k
                    data2.add(line);
209
24.4k
                    if is_chunked_ctl_line(&data2) {
210
3.37k
                        let resp = self.response_mut().unwrap();
211
3.37k
                        resp.response_message_len =
212
3.37k
                            (resp.response_message_len).wrapping_add(data2.len() as u64);
213
                        //Empty chunk len. Try to continue parsing.
214
3.37k
                        data = remaining;
215
3.37k
                        continue;
216
21.0k
                    }
217
21.0k
                    let resp = self.response_mut().unwrap();
218
21.0k
                    resp.response_message_len =
219
21.0k
                        (resp.response_message_len).wrapping_add(data2.len() as u64);
220
221
21.0k
                    match parse_chunked_length(&data2) {
222
20.9k
                        Ok((len, ext)) => {
223
20.9k
                            self.response_chunked_length = len;
224
20.9k
                            if ext {
225
3.28k
                                let mut flags = 0; // unused but needed by macro
226
3.28k
                                htp_warn_once!(
227
102
                                    self.logger,
228
102
                                    HtpLogCode::RESPONSE_CHUNK_EXTENSION,
229
102
                                    "Response chunk extension",
230
3.28k
                                    self.response_mut().unwrap().flags,
231
3.28k
                                    flags,
232
                                    HtpFlags::FIELD_RESP_CHUNK_EXTENSION
233
                                );
234
17.6k
                            }
235
                            // Handle chunk length
236
20.9k
                            if let Some(len) = len {
237
20.6k
                                match len.cmp(&0) {
238
                                    Ordering::Equal => {
239
                                        // End of data
240
7.21k
                                        self.response_state = State::Headers;
241
7.21k
                                        self.response_mut().unwrap().response_progress =
242
7.21k
                                            HtpResponseProgress::TRAILER
243
                                    }
244
                                    Ordering::Greater => {
245
                                        // More data available.
246
13.4k
                                        self.response_state = State::BodyChunkedData
247
                                    }
248
0
                                    _ => {}
249
                                }
250
                            } else {
251
277
                                return Ok(()); // empty chunk length line, lets try to continue
252
                            }
253
                        }
254
135
                        Err(_) => {
255
135
                            // unconsume so response_body_identity_stream_close doesn't miss the first bytes
256
135
                            self.response_data_unconsume(input, line.len());
257
135
                            self.response_state = State::BodyIdentityStreamClose;
258
135
                            self.response_mut().unwrap().response_transfer_coding =
259
135
                                HtpTransferCoding::Identity;
260
135
                            htp_error!(
261
135
                                self.logger,
262
135
                                HtpLogCode::INVALID_RESPONSE_CHUNK_LEN,
263
135
                                "Response chunk encoding: Invalid chunk length"
264
135
                            );
265
135
                        }
266
                    }
267
268
20.7k
                    return Ok(());
269
                }
270
                _ => {
271
                    // Check if the data we have seen so far is invalid
272
4.38k
                    if buf_empty && !is_valid_chunked_length_data(data) {
273
                        // Contains leading junk non hex_ascii data
274
46
                        resp.response_transfer_coding = HtpTransferCoding::Identity;
275
46
                        self.response_state = State::BodyIdentityStreamClose;
276
46
                        htp_error!(
277
46
                            self.logger,
278
46
                            HtpLogCode::INVALID_RESPONSE_CHUNK_LEN,
279
46
                            "Response chunk encoding: Invalid chunk length"
280
46
                        );
281
46
                        return Ok(());
282
                    } else {
283
4.34k
                        return self.handle_response_absent_lf(input);
284
                    }
285
                }
286
            }
287
        }
288
25.4k
    }
289
290
    /// Processes an identity response body of known length.
291
    ///
292
    /// Returns HtpStatus::OK on state change, HtpStatus::ERROR on error, or
293
    /// HtpStatus::DATA when more data is needed.
294
47.5k
    pub(crate) fn response_body_identity_cl_known(&mut self, data: &mut ParserData) -> Result<()> {
295
47.5k
        if self.response_status == HtpStreamState::CLOSED {
296
494
            self.response_state = State::Finalize;
297
            // Sends close signal to decompressors
298
494
            return self.response_body_data(data.data());
299
47.0k
        }
300
47.0k
        let left = self.response_body_data_left.ok_or(HtpStatus::ERROR)?;
301
47.0k
        let bytes_to_consume = std::cmp::min(data.len() as u64, left);
302
47.0k
        if bytes_to_consume == 0 {
303
3.43k
            return Err(HtpStatus::DATA);
304
43.6k
        }
305
43.6k
        if data.is_gap() {
306
739
            let resp = self.response_mut();
307
739
            if resp.is_none() {
308
0
                return Err(HtpStatus::ERROR);
309
739
            }
310
739
            let resp = resp.unwrap();
311
312
739
            if resp.response_content_encoding_processing == HtpContentEncoding::None {
313
725
                resp.response_message_len =
314
725
                    resp.response_message_len.wrapping_add(bytes_to_consume);
315
                // Create a new gap of the appropriate length
316
725
                let parser_data = ParserData::from(bytes_to_consume as usize);
317
                // Send the gap to the data hooks
318
725
                let mut tx_data = Data::new(resp, &parser_data);
319
725
                self.response_run_hook_body_data(&mut tx_data)?;
320
            } else {
321
                // end decompression on gap
322
14
                self.response_body_data(None)?;
323
            }
324
        } else {
325
            // Consume the data.
326
42.9k
            self.response_body_data(Some(&data.as_slice()[0..bytes_to_consume as usize]))?;
327
        }
328
        // Adjust the counters.
329
43.6k
        self.response_data_consume(data, bytes_to_consume as usize);
330
43.6k
        self.response_body_data_left = Some(left - bytes_to_consume);
331
        // Have we seen the entire response body?
332
43.6k
        if self.response_body_data_left > Some(0) {
333
23.4k
            return Err(HtpStatus::DATA);
334
20.1k
        }
335
        // End of response body.
336
20.1k
        self.response_state = State::Finalize;
337
        // Sends close signal to decompressors, outputting any partially decompressed data
338
20.1k
        self.response_body_data(None)
339
47.5k
    }
340
341
    /// Processes identity response body of unknown length. In this case, we assume the
342
    /// response body consumes all data until the end of the stream.
343
    ///
344
    /// Returns HtpStatus::OK on state change, HtpStatus::ERROR on error, or HtpStatus::DATA
345
    /// when more data is needed.
346
107k
    pub(crate) fn response_body_identity_stream_close(&mut self, data: &ParserData) -> Result<()> {
347
107k
        if !data.is_empty() {
348
            // Consume all data from the input buffer.
349
102k
            self.response_body_data(data.data())?;
350
            // Adjust the counters.
351
102k
            self.response_data_consume(data, data.len());
352
5.11k
        }
353
        // Have we seen the entire response body?
354
107k
        if self.response_status == HtpStreamState::CLOSED {
355
3.05k
            self.response_state = State::Finalize;
356
3.05k
            return Ok(());
357
104k
        }
358
359
104k
        Err(HtpStatus::DATA)
360
107k
    }
361
362
    /// Determines presence (and encoding) of a response body.
363
158k
    pub(crate) fn response_body_determine(&mut self, input: &mut ParserData) -> Result<()> {
364
        // If the request uses the CONNECT method, then not only are we
365
        // to assume there's no body, but we need to ignore all
366
        // subsequent data in the stream.
367
158k
        let response_tx = self.response_mut();
368
158k
        if response_tx.is_none() {
369
0
            return Err(HtpStatus::ERROR);
370
158k
        }
371
158k
        let response_tx = response_tx.unwrap();
372
373
158k
        if response_tx.request_method_number == HtpMethod::CONNECT {
374
1.85k
            if response_tx.response_status_number.in_range(200, 299) {
375
                // This is a successful CONNECT stream, which means
376
                // we need to switch into tunneling mode: on the
377
                // request side we'll now probe the tunnel data to see
378
                // if we need to parse or ignore it. So on the response
379
                // side we wrap up the tx and wait.
380
1.76k
                self.response_state = State::Finalize;
381
                // we may have response headers
382
1.76k
                return self.state_response_headers(input);
383
95
            } else if response_tx.response_status_number.eq_num(407) {
384
                // proxy telling us to auth
385
0
                if self.request_status != HtpStreamState::ERROR {
386
0
                    self.request_status = HtpStreamState::DATA
387
0
                }
388
            } else {
389
                // This is a failed CONNECT stream, which means that
390
                // we can unblock request parsing
391
95
                if self.request_status != HtpStreamState::ERROR {
392
95
                    self.request_status = HtpStreamState::DATA
393
0
                }
394
                // We are going to continue processing this transaction,
395
                // adding a note for ourselves to stop at the end (because
396
                // we don't want to see the beginning of a new transaction).
397
95
                self.response_data_other_at_tx_end = true
398
            }
399
156k
        }
400
156k
        let response_tx = self.response_mut().unwrap();
401
156k
        let cl_opt = response_tx
402
156k
            .response_headers
403
156k
            .get_nocase_nozero("content-length")
404
156k
            .cloned();
405
156k
        let te_opt = response_tx
406
156k
            .response_headers
407
156k
            .get_nocase_nozero("transfer-encoding")
408
156k
            .cloned();
409
        // Check for "101 Switching Protocol" response.
410
        // If it's seen, it means that traffic after empty line following headers
411
        // is no longer HTTP. We can treat it similarly to CONNECT.
412
        // Unlike CONNECT, however, upgrades from HTTP to HTTP seem
413
        // rather unlikely, so don't try to probe tunnel for nested HTTP,
414
        // and switch to tunnel mode right away.
415
156k
        if response_tx.response_status_number.eq_num(101) {
416
3.26k
            if response_tx
417
3.26k
                .response_headers
418
3.26k
                .get_nocase_nozero("upgrade")
419
3.26k
                .map(|upgrade| upgrade.value.index_of_nocase_nozero("h2c").is_some())
420
3.26k
                .unwrap_or(false)
421
1.46k
            {
422
1.46k
                response_tx.is_http_2_upgrade = true;
423
1.80k
            }
424
3.26k
            if te_opt.is_none() && cl_opt.is_none() {
425
2.69k
                self.response_state = State::Finalize;
426
2.69k
                if self.request_status != HtpStreamState::ERROR {
427
2.69k
                    self.request_status = HtpStreamState::TUNNEL
428
1
                }
429
2.69k
                self.response_status = HtpStreamState::TUNNEL;
430
                // we may have response headers
431
2.69k
                return self.state_response_headers(input);
432
566
            } else {
433
566
                htp_warn!(
434
566
                    self.logger,
435
566
                    HtpLogCode::SWITCHING_PROTO_WITH_CONTENT_LENGTH,
436
566
                    "Switching Protocol with Content-Length"
437
566
                );
438
566
            }
439
        }
440
        // Check for an interim "100 Continue" response. Ignore it if found, and revert back to RES_LINE.
441
153k
        else if response_tx.response_status_number.eq_num(100) && te_opt.is_none() {
442
8.84k
            match cl_opt
443
8.84k
                .as_ref()
444
8.84k
                .and_then(|cl| parse_content_length(cl.value.as_slice(), Some(&mut self.logger)))
445
            {
446
                // 100 Continue with a Content-Length > 0 isn't treated as a 100 Continue,
447
                // so we do nothing here.
448
1.25k
                Some(x) if x > 0 => (),
449
                // Otherwise we treat it as a continue and prep for the next response
450
                _ => {
451
7.72k
                    let response_tx = self.response_mut().unwrap();
452
7.72k
                    if response_tx.seen_100continue {
453
4.68k
                        let mut flags = 0; // unused but needed by macro
454
4.68k
                        htp_warn_once!(
455
1.37k
                            self.logger,
456
1.37k
                            HtpLogCode::CONTINUE_ALREADY_SEEN,
457
1.37k
                            "Already seen 100-Continue.",
458
4.68k
                            self.response_mut().unwrap().flags,
459
4.68k
                            flags,
460
                            HtpFlags::FIELD_100_CONTINUE
461
                        );
462
3.04k
                    }
463
                    // Expecting to see another response line next.
464
7.72k
                    self.response_state = State::Line;
465
7.72k
                    let response_tx = self.response_mut().unwrap();
466
                    // Ignore any response headers seen so far.
467
7.72k
                    response_tx.response_headers.elements.clear();
468
7.72k
                    response_tx.seen_100continue = true;
469
7.72k
                    return Ok(());
470
                }
471
            }
472
        }
473
        // A request can indicate it waits for headers validation
474
        // before sending its body cf
475
        // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Expect
476
144k
        else if response_tx.response_status_number.in_range(400, 499)
477
7.85k
            && self.request_content_length > Some(0)
478
2.18k
            && self.request_body_data_left == self.request_content_length
479
        {
480
313
            let response_tx = self.response_mut().unwrap();
481
313
            if let Some(expect) = response_tx.request_headers.get_nocase("expect") {
482
0
                if expect.value.eq_slice("100-continue") {
483
0
                    self.request_state = State::Finalize;
484
0
                }
485
313
            }
486
144k
        }
487
488
        // 1. Any response message which MUST NOT include a message-body
489
        //  (such as the 1xx, 204, and 304 responses and any response to a HEAD
490
        //  request) is always terminated by the first empty line after the
491
        //  header fields, regardless of the entity-header fields present in the
492
        //  message.
493
146k
        let response_tx = self.response_mut().unwrap();
494
146k
        if response_tx.request_method_number == HtpMethod::HEAD {
495
            // There's no response body whatsoever
496
1.29k
            response_tx.response_transfer_coding = HtpTransferCoding::NoBody;
497
1.29k
            self.response_state = State::Finalize
498
144k
        } else if response_tx.response_status_number.in_range(100, 199)
499
125k
            || response_tx.response_status_number.eq_num(204)
500
121k
            || response_tx.response_status_number.eq_num(304)
501
        {
502
            // There should be no response body
503
            // but browsers interpret content sent by the server as such
504
95.9k
            if te_opt.is_none() && cl_opt.is_none() {
505
91.1k
                response_tx.response_transfer_coding = HtpTransferCoding::NoBody;
506
91.1k
                self.response_state = State::Finalize
507
4.82k
            } else {
508
4.82k
                htp_warn!(
509
4.82k
                    self.logger,
510
4.82k
                    HtpLogCode::RESPONSE_BODY_UNEXPECTED,
511
4.82k
                    "Unexpected Response body"
512
4.82k
                );
513
4.82k
            }
514
48.8k
        }
515
        // Hack condition to check that we do not assume "no body"
516
146k
        let mut multipart_byteranges = false;
517
146k
        if self.response_state != State::Finalize {
518
            // We have a response body
519
53.6k
            let response_tx = self.response_mut().unwrap();
520
53.6k
            let response_content_type = if let Some(ct) = response_tx
521
53.6k
                .response_headers
522
53.6k
                .get_nocase_nozero("content-type")
523
            {
524
                // TODO Some platforms may do things differently here.
525
25.4k
                let response_content_type = if let Ok((_, ct)) =
526
592k
                    streaming_take_till::<_, _, (&[u8], ErrorKind)>(|c| c == b';' || is_space(c))(
527
25.4k
                        &ct.value,
528
                    ) {
529
10.4k
                    ct
530
                } else {
531
14.9k
                    &ct.value
532
                };
533
534
25.4k
                let mut response_content_type = Bstr::from(response_content_type);
535
25.4k
                response_content_type.make_ascii_lowercase();
536
25.4k
                if response_content_type
537
25.4k
                    .index_of_nocase("multipart/byteranges")
538
25.4k
                    .is_some()
539
0
                {
540
0
                    multipart_byteranges = true;
541
25.4k
                }
542
25.4k
                Some(response_content_type)
543
            } else {
544
28.2k
                None
545
            };
546
547
53.6k
            if response_content_type.is_some() {
548
25.4k
                response_tx.response_content_type = response_content_type;
549
28.2k
            }
550
            // 2. If a Transfer-Encoding header field (section 14.40) is present and
551
            //   indicates that the "chunked" transfer coding has been applied, then
552
            //   the length is defined by the chunked encoding (section 3.6).
553
7.62k
            if let Some(te) =
554
53.6k
                te_opt.and_then(|te| te.value.index_of_nocase_nozero("chunked").and(Some(te)))
555
            {
556
7.62k
                if !te.value.cmp_nocase("chunked") {
557
1.93k
                    htp_warn!(
558
1.93k
                        self.logger,
559
1.93k
                        HtpLogCode::RESPONSE_ABNORMAL_TRANSFER_ENCODING,
560
1.93k
                        "Transfer-encoding has abnormal chunked value"
561
1.93k
                    );
562
5.69k
                }
563
                // 3. If a Content-Length header field (section 14.14) is present, its
564
                // spec says chunked is HTTP/1.1 only, but some browsers accept it
565
                // with 1.0 as well
566
7.62k
                let response_tx = self.response_mut().unwrap();
567
7.62k
                if response_tx.response_protocol_number < HtpProtocol::V1_1 {
568
3.66k
                    htp_warn!(
569
3.66k
                        self.logger,
570
3.66k
                        HtpLogCode::RESPONSE_CHUNKED_OLD_PROTO,
571
3.66k
                        "Chunked transfer-encoding on HTTP/0.9 or HTTP/1.0"
572
3.66k
                    );
573
3.96k
                }
574
                // If the T-E header is present we are going to use it.
575
7.62k
                let response_tx = self.response_mut().unwrap();
576
7.62k
                response_tx.response_transfer_coding = HtpTransferCoding::Chunked;
577
                // We are still going to check for the presence of C-L
578
7.62k
                if cl_opt.is_some() {
579
                    // This is a violation of the RFC
580
1.68k
                    response_tx.flags.set(HtpFlags::REQUEST_SMUGGLING)
581
5.94k
                }
582
7.62k
                response_tx.response_progress = HtpResponseProgress::BODY;
583
7.62k
                self.response_state = State::BodyChunkedLength
584
46.0k
            } else if let Some(cl) = cl_opt {
585
                //   value in bytes represents the length of the message-body.
586
                // We know the exact length
587
41.9k
                response_tx.response_transfer_coding = HtpTransferCoding::Identity;
588
                // Check for multiple C-L headers
589
41.9k
                if cl.flags.is_set(HtpFlags::FIELD_REPEATED) {
590
6.62k
                    response_tx.flags.set(HtpFlags::REQUEST_SMUGGLING)
591
35.3k
                }
592
                // Get body length
593
41.9k
                let response_content_length =
594
41.9k
                    parse_content_length((*cl.value).as_slice(), Some(&mut self.logger));
595
41.9k
                self.response_mut().unwrap().response_content_length = response_content_length;
596
41.9k
                self.response_content_length = response_content_length;
597
41.9k
                self.response_body_data_left = response_content_length;
598
41.9k
                if let Some(len) = response_content_length {
599
41.9k
                    if len != 0 {
600
21.8k
                        self.response_state = State::BodyIdentityCLKnown;
601
21.8k
                        self.response_mut().unwrap().response_progress = HtpResponseProgress::BODY
602
                    } else {
603
20.1k
                        self.response_state = State::Finalize
604
                    }
605
                } else {
606
23
                    htp_error!(
607
23
                        self.logger,
608
23
                        HtpLogCode::INVALID_CONTENT_LENGTH_FIELD_IN_RESPONSE,
609
23
                        "Invalid C-L field in response"
610
23
                    );
611
23
                    return Err(HtpStatus::ERROR);
612
                }
613
            } else {
614
                // 4. If the message uses the media type "multipart/byteranges", which is
615
                //   self-delimiting, then that defines the length. This media type MUST
616
                //   NOT be used unless the sender knows that the recipient can parse it;
617
                //   the presence in a request of a Range header with multiple byte-range
618
                //   specifiers implies that the client can parse multipart/byteranges
619
                //   responses.
620
                // TODO Handle multipart/byteranges
621
4.00k
                if multipart_byteranges {
622
0
                    htp_error!(
623
0
                        self.logger,
624
0
                        HtpLogCode::RESPONSE_MULTIPART_BYTERANGES,
625
0
                        "C-T multipart/byteranges in responses not supported"
626
0
                    );
627
0
                    return Err(HtpStatus::ERROR);
628
4.00k
                }
629
                // 5. By the server closing the connection. (Closing the connection
630
                //   cannot be used to indicate the end of a request body, since that
631
                //   would leave no possibility for the server to send back a response.)
632
4.00k
                response_tx.response_transfer_coding = HtpTransferCoding::Identity;
633
4.00k
                response_tx.response_progress = HtpResponseProgress::BODY;
634
4.00k
                self.response_state = State::BodyIdentityStreamClose;
635
4.00k
                self.response_body_data_left = None
636
            }
637
92.4k
        }
638
        // NOTE We do not need to check for short-style HTTP/0.9 requests here because
639
        //      that is done earlier, before response line parsing begins
640
146k
        self.state_response_headers(input)
641
158k
    }
642
643
    /// Parses response line.
644
    ///
645
    /// Returns HtpStatus::OK on state change, HtpStatus::ERROR on error, or HtpStatus::DATA
646
    /// when more data is needed.
647
1.83M
    pub(crate) fn response_line(&mut self, input: &ParserData) -> Result<()> {
648
1.83M
        match take_till_eol(input.as_slice()) {
649
1.60M
            Ok((_, (line, _))) => {
650
                // We have a line ending, so consume the input
651
                // and grab any buffered data.
652
1.60M
                let mut data = take(&mut self.response_buf);
653
1.60M
                data.add(line);
654
1.60M
                self.response_data_consume(input, line.len());
655
1.60M
                self.response_line_complete(data.as_slice(), input)
656
            }
657
            _ => {
658
231k
                if self.response_status == HtpStreamState::CLOSED {
659
1.10k
                    let mut data = take(&mut self.response_buf);
660
1.10k
                    data.add(input.as_slice());
661
1.10k
                    self.response_data_consume(input, input.len());
662
1.10k
                    self.response_line_complete(data.as_slice(), input)
663
                } else {
664
230k
                    self.handle_response_absent_lf(input)
665
                }
666
            }
667
        }
668
1.83M
    }
669
670
    /// Parse the complete response line.
671
    ///
672
    /// Returns OK on state change, ERROR on error, or HtpStatus::DATA_BUFFER
673
    /// when more data is needed.
674
1.60M
    fn response_line_complete(&mut self, line: &[u8], input: &ParserData) -> Result<()> {
675
1.60M
        self.check_response_buffer_limit(line.len())?;
676
1.60M
        if line.is_empty() {
677
31
            return Err(HtpStatus::DATA);
678
1.60M
        }
679
1.60M
        let response_tx = self.response_mut();
680
1.60M
        if response_tx.is_none() {
681
0
            return Err(HtpStatus::ERROR);
682
1.60M
        }
683
1.60M
        if is_line_ignorable(self.cfg.server_personality, line) {
684
320k
            if self.response_status == HtpStreamState::CLOSED {
685
21
                self.response_state = State::Finalize
686
320k
            }
687
            // We have an empty/whitespace line, which we'll note, ignore and move on
688
320k
            let response_tx = self.response_mut().unwrap();
689
320k
            response_tx.response_ignored_lines = response_tx.response_ignored_lines.wrapping_add(1);
690
            // TODO How many lines are we willing to accept?
691
            // Start again
692
320k
            return Ok(());
693
1.28M
        }
694
        // Deallocate previous response line allocations, which we would have on a 100 response.
695
1.28M
        let response_tx = self.response_mut().unwrap();
696
1.28M
        response_tx.response_line = None;
697
1.28M
        response_tx.response_protocol = None;
698
1.28M
        response_tx.response_status = None;
699
1.28M
        response_tx.response_message = None;
700
701
        // Process response line.
702
        // If the response line is invalid, determine if it _looks_ like
703
        // a response line. If it does not look like a line, process the
704
        // data as a response body because that is what browsers do.
705
1.28M
        if treat_response_line_as_body(line) {
706
            // if we have a next line beginning with H, skip this one
707
1.12M
            if input.len() > 1 && (input.as_slice()[0] == b'H' || chomp(line).len() <= 2) {
708
138k
                response_tx.response_ignored_lines =
709
138k
                    response_tx.response_ignored_lines.wrapping_add(1);
710
138k
                return Ok(());
711
982k
            }
712
982k
            response_tx.response_content_encoding_processing = HtpContentEncoding::None;
713
982k
            self.response_body_data(Some(line))?;
714
            // Continue to process response body. Because we don't have
715
            // any headers to parse, we assume the body continues until
716
            // the end of the stream.
717
            // Have we seen the entire response body?
718
982k
            if input.is_empty() {
719
190k
                let response_tx = self.response_mut().unwrap();
720
190k
                response_tx.response_transfer_coding = HtpTransferCoding::Identity;
721
190k
                response_tx.response_progress = HtpResponseProgress::BODY;
722
190k
                self.response_body_data_left = None;
723
190k
                self.response_state = State::Finalize
724
792k
            }
725
982k
            return Ok(());
726
161k
        }
727
161k
        self.parse_response_line(line)?;
728
161k
        self.state_response_line()?;
729
        // Move on to the next phase.
730
161k
        self.response_state = State::Headers;
731
161k
        let response_tx = self.response_mut().unwrap();
732
        // delay progress in case of a 100 continue
733
        // so we do not revert progress to line after headers
734
161k
        if !response_tx.response_status_number.eq_num(100) {
735
151k
            response_tx.response_progress = HtpResponseProgress::HEADERS;
736
151k
        }
737
161k
        Ok(())
738
1.60M
    }
739
740
    /// Parses the response line.
741
161k
    pub(crate) fn parse_response_line(&mut self, response_line: &[u8]) -> Result<()> {
742
161k
        let response_tx = self.response_mut();
743
161k
        if response_tx.is_none() {
744
0
            return Err(HtpStatus::ERROR);
745
161k
        }
746
161k
        let response_tx = response_tx.unwrap();
747
748
161k
        response_tx.response_line = Some(Bstr::from(response_line));
749
161k
        response_tx.response_protocol_number = HtpProtocol::Invalid;
750
161k
        response_tx.response_status = None;
751
161k
        response_tx.response_status_number = HtpResponseNumber::Invalid;
752
161k
        response_tx.response_message = None;
753
754
161k
        let mut response_line_parser = (
755
161k
            take_is_space_or_null,
756
161k
            take_not_is_space,
757
161k
            take_is_space,
758
161k
            take_not_is_space,
759
161k
            take_ascii_whitespace(),
760
161k
        );
761
762
161k
        let (message, (_ls, response_protocol, ws1, status_code, ws2)) =
763
161k
            response_line_parser.parse(response_line)?;
764
161k
        if response_protocol.is_empty() {
765
0
            return Ok(());
766
161k
        }
767
768
161k
        response_tx.response_protocol = Some(Bstr::from(response_protocol));
769
161k
        self.response_mut().unwrap().response_protocol_number =
770
161k
            parse_protocol(response_protocol, &mut self.logger);
771
772
161k
        if ws1.is_empty() || status_code.is_empty() {
773
5.69k
            return Ok(());
774
155k
        }
775
776
155k
        let response_tx = self.response_mut().unwrap();
777
155k
        response_tx.response_status = Some(Bstr::from(status_code));
778
155k
        response_tx.response_status_number = parse_status(status_code);
779
780
155k
        if ws2.is_empty() {
781
188
            return Ok(());
782
155k
        }
783
784
155k
        response_tx.response_message = Some(Bstr::from(chomp(message)));
785
155k
        Ok(())
786
161k
    }
787
788
    /// Response header parser.
789
    ///
790
    ///Returns a tuple of the unparsed data and a boolean indicating if the EOH was seen.
791
225k
    fn parse_response_headers<'a>(&mut self, data: &'a [u8]) -> Result<(&'a [u8], bool)> {
792
225k
        let resp = self.response_mut();
793
225k
        if resp.is_none() {
794
0
            return Err(HtpStatus::ERROR);
795
225k
        }
796
797
225k
        let rc = resp.unwrap().response_header_parser.headers()(data);
798
225k
        if let Ok((remaining, (headers, eoh))) = rc {
799
993k
            for h in headers {
800
790k
                let mut flags = 0;
801
790k
                let name_flags = &h.name.flags;
802
790k
                let value_flags = &h.value.flags;
803
790k
                if value_flags.is_set(HeaderFlags::DEFORMED_EOL)
804
787k
                    || name_flags.is_set(HeaderFlags::DEFORMED_EOL)
805
3.08k
                {
806
3.08k
                    htp_warn!(
807
3.08k
                        self.logger,
808
3.08k
                        HtpLogCode::DEFORMED_EOL,
809
3.08k
                        "Weird response end of lines mix"
810
3.08k
                    );
811
787k
                }
812
                // Ignore LWS after field-name.
813
790k
                if name_flags.is_set(HeaderFlags::NAME_TRAILING_WHITESPACE) {
814
4.02k
                    htp_warn_once!(
815
712
                        self.logger,
816
712
                        HtpLogCode::RESPONSE_INVALID_LWS_AFTER_NAME,
817
712
                        "Request field invalid: LWS after name",
818
4.02k
                        self.response_mut().unwrap().flags,
819
4.02k
                        flags,
820
                        HtpFlags::FIELD_INVALID
821
                    );
822
786k
                }
823
                //If there was leading whitespace, probably was invalid folding.
824
790k
                if name_flags.is_set(HeaderFlags::NAME_LEADING_WHITESPACE) {
825
961
                    htp_warn_once!(
826
688
                        self.logger,
827
688
                        HtpLogCode::INVALID_RESPONSE_FIELD_FOLDING,
828
688
                        "Invalid response field folding",
829
961
                        self.response_mut().unwrap().flags,
830
961
                        flags,
831
                        HtpFlags::INVALID_FOLDING
832
                    );
833
961
                    flags.set(HtpFlags::FIELD_INVALID);
834
789k
                }
835
                // Check that field-name is a token
836
790k
                if name_flags.is_set(HeaderFlags::NAME_NON_TOKEN_CHARS) {
837
                    // Incorrectly formed header name.
838
142k
                    htp_warn_once!(
839
68.2k
                        self.logger,
840
68.2k
                        HtpLogCode::RESPONSE_HEADER_NAME_NOT_TOKEN,
841
68.2k
                        "Response header name is not a token",
842
142k
                        self.response_mut().unwrap().flags,
843
142k
                        flags,
844
                        HtpFlags::FIELD_INVALID
845
                    );
846
648k
                }
847
                // No colon?
848
790k
                if name_flags.is_set(HeaderFlags::MISSING_COLON) {
849
                    // We handle this case as a header with an empty name, with the value equal
850
                    // to the entire input string.
851
                    // TODO Apache will respond to this problem with a 400.
852
                    // Now extract the name and the value
853
259k
                    htp_warn_once!(
854
39.4k
                        self.logger,
855
39.4k
                        HtpLogCode::RESPONSE_FIELD_MISSING_COLON,
856
39.4k
                        "Response field invalid: colon missing",
857
259k
                        self.response_mut().unwrap().flags,
858
259k
                        flags,
859
                        HtpFlags::FIELD_UNPARSEABLE
860
                    );
861
259k
                    flags.set(HtpFlags::FIELD_INVALID);
862
530k
                } else if name_flags.is_set(HeaderFlags::NAME_EMPTY) {
863
                    // Empty header name.
864
0
                    htp_warn_once!(
865
0
                        self.logger,
866
0
                        HtpLogCode::RESPONSE_INVALID_EMPTY_NAME,
867
0
                        "Response field invalid: empty name",
868
0
                        self.response_mut().unwrap().flags,
869
0
                        flags,
870
                        HtpFlags::FIELD_INVALID
871
                    );
872
530k
                }
873
790k
                self.process_response_header(Header::new_with_flags(
874
790k
                    h.name.name.into(),
875
790k
                    h.value.value.into(),
876
790k
                    flags,
877
0
                ))?;
878
            }
879
203k
            Ok((remaining, eoh))
880
        } else {
881
21.8k
            Ok((data, false))
882
        }
883
225k
    }
884
885
    /// Response header line(s) processor, which assembles folded lines
886
    /// into a single buffer before invoking the parsing function.
887
790k
    fn process_response_header(&mut self, header: Header) -> Result<()> {
888
790k
        let mut repeated = false;
889
790k
        let hl = self.cfg.number_headers_limit as usize;
890
790k
        let resp = self.response_mut();
891
790k
        if resp.is_none() {
892
0
            return Err(HtpStatus::ERROR);
893
790k
        }
894
790k
        let resp = resp.unwrap();
895
896
790k
        let reps = resp.response_header_repetitions;
897
790k
        let mut update_reps = false;
898
        // Do we already have a header with the same name?
899
790k
        if let Some(h_existing) = resp.response_headers.get_nocase_mut(header.name.as_slice()) {
900
286k
            if !h_existing.flags.is_set(HeaderFlags::FIELD_REPEATED) {
901
90.6k
                // This is the second occurence for this header.
902
90.6k
                repeated = true;
903
195k
            } else if reps < 64 {
904
163k
                update_reps = true;
905
163k
            } else {
906
32.1k
                return Ok(());
907
            }
908
254k
            h_existing.flags.set(HeaderFlags::FIELD_REPEATED);
909
            // For simplicity reasons, we count the repetitions of all headers
910
            // Having multiple C-L headers is against the RFC but many
911
            // browsers ignore the subsequent headers if the values are the same.
912
254k
            if header.name.cmp_nocase("Content-Length") {
913
                // Don't use string comparison here because we want to
914
                // ignore small formatting differences.
915
18.7k
                let existing_cl = parse_content_length(&h_existing.value, None);
916
18.7k
                let new_cl = parse_content_length(&(header.value), None);
917
18.7k
                if existing_cl.is_none() || new_cl.is_none() || existing_cl != new_cl {
918
12.9k
                    // Ambiguous response C-L value.
919
12.9k
                    htp_warn!(
920
12.9k
                        self.logger,
921
12.9k
                        HtpLogCode::DUPLICATE_CONTENT_LENGTH_FIELD_IN_RESPONSE,
922
12.9k
                        "Ambiguous response C-L value"
923
12.9k
                    );
924
12.9k
                }
925
235k
            } else {
926
235k
                // Add to the existing header.
927
235k
                h_existing.value.extend_from_slice(b", ");
928
235k
                h_existing.value.extend_from_slice(header.value.as_slice());
929
235k
            }
930
        } else {
931
504k
            if resp.response_headers.elements.len() > hl {
932
0
                if !resp.flags.is_set(HtpFlags::HEADERS_TOO_MANY) {
933
0
                    htp_warn!(
934
0
                        self.logger,
935
0
                        HtpLogCode::RESPONSE_TOO_MANY_HEADERS,
936
0
                        "Too many response headers"
937
0
                    );
938
0
                    let resp = self.response_mut().unwrap();
939
0
                    resp.flags.set(HtpFlags::HEADERS_TOO_MANY);
940
0
                }
941
0
                return Err(HtpStatus::ERROR);
942
504k
            }
943
504k
            resp.response_headers.elements.push(header);
944
        }
945
758k
        let resp = self.response_mut().unwrap();
946
758k
        if update_reps {
947
163k
            resp.response_header_repetitions = resp.response_header_repetitions.wrapping_add(1)
948
594k
        }
949
758k
        if repeated {
950
90.6k
            htp_warn!(
951
90.6k
                self.logger,
952
90.6k
                HtpLogCode::RESPONSE_HEADER_REPETITION,
953
90.6k
                "Repetition for header"
954
90.6k
            );
955
667k
        }
956
758k
        Ok(())
957
790k
    }
958
    /// Parses response headers.
959
    ///
960
    /// Returns HtpStatus::OK on state change, HtpStatus::ERROR on error, or HtpStatus::DATA when more data is needed.
961
248k
    pub(crate) fn response_headers(&mut self, input: &mut ParserData) -> Result<()> {
962
248k
        let response_index = self.response_index();
963
248k
        if self.response_status == HtpStreamState::CLOSED {
964
2.72k
            let resp = self.response_mut();
965
2.72k
            if resp.is_none() {
966
0
                return Err(HtpStatus::ERROR);
967
2.72k
            }
968
2.72k
            let resp = resp.unwrap();
969
2.72k
            resp.response_header_parser.set_complete(true);
970
            // Parse previous header, if any.
971
2.72k
            if let Some(response_header) = self.response_header.take() {
972
2.67k
                self.parse_response_headers(response_header.as_slice())?;
973
51
            }
974
            // Finalize sending raw trailer data.
975
2.72k
            self.response_receiver_finalize_clear(input)?;
976
            // Run hook response_TRAILER
977
2.72k
            self.cfg
978
2.72k
                .hook_response_trailer
979
2.72k
                .clone()
980
2.72k
                .run_all(self, response_index)?;
981
2.72k
            self.response_state = State::Finalize;
982
2.72k
            return Ok(());
983
245k
        }
984
245k
        if let Ok((_, line)) = take_till_lf(input.as_slice()) {
985
222k
            if self.response_header.is_some() {
986
57.3k
                self.check_response_buffer_limit(line.len())?;
987
165k
            }
988
        } else {
989
23.0k
            let data = input.as_slice();
990
23.0k
            self.response_data_consume(input, data.len());
991
23.0k
            self.check_response_buffer_limit(data.len())?;
992
23.0k
            if let Some(rh) = &mut self.response_header {
993
19.2k
                rh.extend_from_slice(data);
994
19.2k
            } else {
995
3.77k
                self.response_header = Some(Bstr::from(data));
996
3.77k
            }
997
23.0k
            return Err(HtpStatus::DATA_BUFFER);
998
        }
999
222k
        let response_header = if let Some(mut response_header) = self.response_header.take() {
1000
57.3k
            response_header.add(input.as_slice());
1001
57.3k
            response_header
1002
        } else {
1003
165k
            Bstr::from(input.as_slice())
1004
        };
1005
1006
222k
        let (remaining, eoh) = self.parse_response_headers(response_header.as_slice())?;
1007
        //TODO: Update the response state machine so that we don't have to have this EOL check
1008
222k
        let eol = remaining.len() == response_header.len()
1009
19.4k
            && (remaining.eq(b"\r\n") || remaining.eq(b"\n"));
1010
        // If remaining is EOL or header parsing saw EOH this is end of headers
1011
222k
        if eoh || eol {
1012
165k
            if eol {
1013
869
                //Consume the EOL so it isn't included in data processing
1014
869
                self.response_data_consume(input, input.len());
1015
164k
            } else if remaining.len() <= input.len() {
1016
163k
                self.response_data_consume(input, input.len() - remaining.len());
1017
163k
            }
1018
            // We've seen all response headers. At terminator.
1019
            self.response_state =
1020
                // we can have response progress LINE in case of 100 continue
1021
165k
                if self.response().unwrap().response_progress <= HtpResponseProgress::HEADERS {
1022
                    // Response headers.
1023
                    // The next step is to determine if this response has a body.
1024
158k
                    State::BodyDetermine
1025
                } else {
1026
                    // Response trailer.
1027
                    // Finalize sending raw trailer data.
1028
7.19k
                    self.response_receiver_finalize_clear(input)?;
1029
                    // Run hook response_TRAILER.
1030
7.19k
                    self.cfg
1031
7.19k
                        .hook_response_trailer
1032
7.19k
                        .clone()
1033
7.19k
                        .run_all(self, response_index)?;
1034
                    // The next step is to finalize this response.
1035
7.19k
                    State::Finalize
1036
                };
1037
165k
            Ok(())
1038
        } else {
1039
56.9k
            self.response_data_consume(input, input.len());
1040
56.9k
            self.check_response_buffer_limit(remaining.len())?;
1041
56.9k
            let remaining = Bstr::from(remaining);
1042
56.9k
            self.response_header.replace(remaining);
1043
56.9k
            Err(HtpStatus::DATA_BUFFER)
1044
        }
1045
248k
    }
1046
1047
    /// Consumes response body data.
1048
    /// This function assumes that handling of chunked encoding is implemented
1049
    /// by the container. When you're done submitting body data, invoking a state
1050
    /// change (to RESPONSE) will finalize any processing that might be pending.
1051
    ///
1052
    /// The response body data will be decompressed if two conditions are met: one,
1053
    /// decompression is enabled in configuration and two, if the response headers
1054
    /// indicate compression. Alternatively, you can control decompression from
1055
    /// a RESPONSE_HEADERS callback, by setting tx->response_content_encoding either
1056
    /// to COMPRESSION_NONE (to disable compression), or to one of the supported
1057
    /// decompression algorithms.
1058
    ///
1059
    /// Returns HtpStatus::OK on success or HtpStatus::ERROR if the request transaction
1060
    /// is invalid or response body data hook fails.
1061
1.93M
    pub(crate) fn response_body_data(&mut self, data: Option<&[u8]>) -> Result<()> {
1062
        // None data is used to indicate the end of response body.
1063
        // Keep track of body size before decompression.
1064
1.93M
        let resp = self.response_mut();
1065
1.93M
        if resp.is_none() {
1066
0
            return Err(HtpStatus::ERROR);
1067
1.93M
        }
1068
1.93M
        let resp = resp.unwrap();
1069
1070
1.93M
        resp.response_message_len = resp
1071
1.93M
            .response_message_len
1072
1.93M
            .wrapping_add(data.unwrap_or(b"").len() as u64);
1073
1074
1.93M
        match resp.response_content_encoding_processing {
1075
            HtpContentEncoding::Gzip
1076
            | HtpContentEncoding::Deflate
1077
            | HtpContentEncoding::Zlib
1078
            | HtpContentEncoding::Brotli
1079
            | HtpContentEncoding::Zstd
1080
            | HtpContentEncoding::Lzma => {
1081
                // Send data buffer to the decompressor if it exists
1082
138k
                if resp.response_decompressor.is_none() && data.is_none() {
1083
2.18k
                    return Ok(());
1084
136k
                }
1085
136k
                let mut decompressor = resp.response_decompressor.take().ok_or(HtpStatus::ERROR)?;
1086
136k
                if let Some(data) = data {
1087
128k
                    let _ = decompressor.decompress(data);
1088
1089
128k
                    if decompressor.time_spent()
1090
128k
                        > self.cfg.compression_options.get_time_limit() as u64
1091
2
                    {
1092
2
                        htp_error!(
1093
2
                            self.logger,
1094
2
                            HtpLogCode::COMPRESSION_BOMB,
1095
2
                            format!(
1096
2
                                "Compression bomb: spent {} us decompressing",
1097
2
                                decompressor.time_spent(),
1098
2
                            )
1099
2
                        );
1100
2
                        decompressor.set_passthrough(true);
1101
128k
                    }
1102
                    // put the decompressor back in its slot
1103
128k
                    self.response_mut()
1104
128k
                        .unwrap()
1105
128k
                        .response_decompressor
1106
128k
                        .replace(decompressor);
1107
7.79k
                } else {
1108
7.79k
                    // don't put the decompressor back in its slot
1109
7.79k
                    // ignore errors
1110
7.79k
                    let _ = decompressor.finish();
1111
7.79k
                }
1112
            }
1113
            HtpContentEncoding::None => {
1114
                // When there's no decompression, response_entity_len.
1115
                // is identical to response_message_len.
1116
1.79M
                let data = ParserData::from(data);
1117
1.79M
                let mut tx_data = Data::new(resp, &data);
1118
1.79M
                resp.response_entity_len =
1119
1.79M
                    resp.response_entity_len.wrapping_add(tx_data.len() as u64);
1120
1.79M
                self.response_run_hook_body_data(&mut tx_data)?;
1121
            }
1122
        }
1123
1.93M
        Ok(())
1124
1.93M
    }
1125
1126
    /// Initialize the response decompression engine. We can deal with three
1127
    /// scenarios:
1128
    ///
1129
    /// 1. Decompression is enabled, compression indicated in headers, and we decompress.
1130
    ///
1131
    /// 2. As above, but the user disables decompression by setting response_content_encoding
1132
    ///    to COMPRESSION_NONE.
1133
    ///
1134
    /// 3. Decompression is disabled and we do not attempt to enable it, but the user
1135
    ///    forces decompression by setting response_content_encoding to one of the
1136
    ///    supported algorithms.
1137
150k
    pub(crate) fn response_initialize_decompressors(&mut self) -> Result<()> {
1138
150k
        let resp = self.response_mut();
1139
150k
        if resp.is_none() {
1140
0
            return Err(HtpStatus::ERROR);
1141
150k
        }
1142
150k
        let resp = resp.unwrap();
1143
1144
150k
        let ce = resp
1145
150k
            .response_headers
1146
150k
            .get_nocase_nozero("content-encoding")
1147
150k
            .map(|val| val.value.clone());
1148
        // Process multiple encodings if there is no match on fast path
1149
150k
        let mut slow_path = false;
1150
1151
        // Fast path - try to match directly on the encoding value
1152
150k
        resp.response_content_encoding = if let Some(ce) = &ce {
1153
22.8k
            if ce.cmp_nocase_nozero(b"gzip") || ce.cmp_nocase_nozero(b"x-gzip") {
1154
9.09k
                HtpContentEncoding::Gzip
1155
13.7k
            } else if ce.cmp_nocase_nozero(b"deflate") || ce.cmp_nocase_nozero(b"x-deflate") {
1156
881
                HtpContentEncoding::Deflate
1157
12.8k
            } else if ce.cmp_nocase_nozero(b"lzma") {
1158
3.64k
                HtpContentEncoding::Lzma
1159
9.21k
            } else if ce.cmp_nocase_nozero(b"br") {
1160
621
                HtpContentEncoding::Brotli
1161
8.59k
            } else if ce.cmp_nocase_nozero(b"zstd") {
1162
8
                HtpContentEncoding::Zstd
1163
8.58k
            } else if ce.cmp_nocase_nozero(b"inflate") || ce.cmp_nocase_nozero(b"none") {
1164
100
                HtpContentEncoding::None
1165
            } else {
1166
8.48k
                slow_path = true;
1167
8.48k
                HtpContentEncoding::None
1168
            }
1169
        } else {
1170
127k
            HtpContentEncoding::None
1171
        };
1172
1173
        // Configure decompression, if enabled in the configuration.
1174
150k
        resp.response_content_encoding_processing = resp.response_content_encoding;
1175
1176
150k
        let response_content_encoding_processing = resp.response_content_encoding_processing;
1177
150k
        let compression_options = self.cfg.compression_options;
1178
150k
        match &response_content_encoding_processing {
1179
            HtpContentEncoding::Gzip
1180
            | HtpContentEncoding::Deflate
1181
            | HtpContentEncoding::Zlib
1182
            | HtpContentEncoding::Brotli
1183
            | HtpContentEncoding::Zstd
1184
            | HtpContentEncoding::Lzma => {
1185
14.2k
                self.response_prepend_decompressor(response_content_encoding_processing)?;
1186
            }
1187
            HtpContentEncoding::None => {
1188
136k
                if slow_path {
1189
8.48k
                    if let Some(ce) = &ce {
1190
8.48k
                        let mut layers = 0;
1191
8.48k
                        let mut lzma_layers = 0;
1192
317k
                        for encoding in ce.split(|c| *c == b',' || *c == b' ') {
1193
18.5k
                            if encoding.is_empty() {
1194
4.04k
                                continue;
1195
14.4k
                            }
1196
14.4k
                            layers += 1;
1197
1198
14.4k
                            if let Some(limit) = compression_options.get_layer_limit() {
1199
                                // decompression layer depth check
1200
14.4k
                                if layers > limit {
1201
2.02k
                                    htp_warn!(
1202
2.02k
                                        self.logger,
1203
2.02k
                                        HtpLogCode::TOO_MANY_ENCODING_LAYERS,
1204
2.02k
                                        "Too many response content encoding layers"
1205
2.02k
                                    );
1206
2.02k
                                    break;
1207
12.4k
                                }
1208
0
                            }
1209
1210
12.4k
                            let encoding = Bstr::from(encoding);
1211
12.4k
                            let encoding = if encoding.index_of_nocase(b"gzip").is_some() {
1212
6.19k
                                if !(encoding.cmp_slice(b"gzip") == Ordering::Equal
1213
5.75k
                                    || encoding.cmp_slice(b"x-gzip") == Ordering::Equal)
1214
5.70k
                                {
1215
5.70k
                                    htp_warn!(
1216
5.70k
                                        self.logger,
1217
5.70k
                                        HtpLogCode::ABNORMAL_CE_HEADER,
1218
5.70k
                                        "C-E gzip has abnormal value"
1219
5.70k
                                    );
1220
5.70k
                                }
1221
6.19k
                                HtpContentEncoding::Gzip
1222
6.26k
                            } else if encoding.index_of_nocase(b"deflate").is_some() {
1223
3.31k
                                if !(encoding.cmp_slice(b"deflate") == Ordering::Equal
1224
1.88k
                                    || encoding.cmp_slice(b"x-deflate") == Ordering::Equal)
1225
637
                                {
1226
637
                                    htp_warn!(
1227
637
                                        self.logger,
1228
637
                                        HtpLogCode::ABNORMAL_CE_HEADER,
1229
637
                                        "C-E deflate has abnormal value"
1230
637
                                    );
1231
2.67k
                                }
1232
3.31k
                                HtpContentEncoding::Deflate
1233
2.95k
                            } else if encoding.cmp_slice(b"lzma") == Ordering::Equal {
1234
117
                                lzma_layers += 1;
1235
117
                                if let Some(limit) = compression_options.get_lzma_layers() {
1236
                                    // Lzma layer depth check
1237
0
                                    if lzma_layers > limit {
1238
0
                                        htp_warn!(
1239
0
                                            self.logger,
1240
0
                                            HtpLogCode::RESPONSE_TOO_MANY_LZMA_LAYERS,
1241
0
                                            "Too many response content encoding lzma layers"
1242
0
                                        );
1243
0
                                        break;
1244
0
                                    }
1245
117
                                }
1246
117
                                HtpContentEncoding::Lzma
1247
2.83k
                            } else if encoding.cmp_slice(b"inflate") == Ordering::Equal
1248
2.79k
                                || encoding.cmp_slice(b"none") == Ordering::Equal
1249
2.76k
                                || encoding.cmp_slice(b"identity") == Ordering::Equal
1250
                            {
1251
113
                                HtpContentEncoding::None
1252
                            } else {
1253
2.72k
                                htp_warn!(
1254
2.72k
                                    self.logger,
1255
2.72k
                                    HtpLogCode::ABNORMAL_CE_HEADER,
1256
2.72k
                                    "C-E unknown setting"
1257
2.72k
                                );
1258
2.72k
                                HtpContentEncoding::None
1259
                            };
1260
1261
12.4k
                            self.response_prepend_decompressor(encoding)?;
1262
                        }
1263
0
                    }
1264
127k
                }
1265
            }
1266
        }
1267
150k
        Ok(())
1268
150k
    }
1269
1270
251k
    fn response_decompressor_callback(&mut self, data: Option<&[u8]>) -> std::io::Result<usize> {
1271
        // If no data is passed, call the hooks with NULL to signify the end of the
1272
        // response body.
1273
251k
        let parser_data = ParserData::from(data);
1274
251k
        let compression_options = self.cfg.compression_options;
1275
251k
        let resp = self.response_mut().unwrap();
1276
251k
        let mut tx_data = Data::new(resp, &parser_data);
1277
1278
        // Keep track of actual response body length.
1279
251k
        resp.response_entity_len = resp.response_entity_len.wrapping_add(tx_data.len() as u64);
1280
1281
        // Invoke all callbacks.
1282
251k
        self.response_run_hook_body_data(&mut tx_data)
1283
251k
            .map_err(|_| std::io::Error::other("body data hook failed"))?;
1284
251k
        let resp = self.response_mut().unwrap();
1285
251k
        if let Some(decompressor) = &mut resp.response_decompressor {
1286
0
            if decompressor.callback_inc() % compression_options.get_time_test_freq() == 0 {
1287
0
                if let Some(time_spent) = decompressor.timer_reset() {
1288
0
                    if time_spent > compression_options.get_time_limit() as u64 {
1289
0
                        decompressor.set_passthrough(true);
1290
0
                        htp_error!(
1291
0
                            self.logger,
1292
0
                            HtpLogCode::COMPRESSION_BOMB,
1293
0
                            format!("Compression bomb: spent {} us decompressing", time_spent)
1294
0
                        );
1295
0
                    }
1296
0
                }
1297
0
            }
1298
251k
        }
1299
1300
        // output > ratio * input ?
1301
251k
        let ratio = compression_options.get_bomb_ratio();
1302
251k
        let resp = self.response_mut().unwrap();
1303
251k
        let exceeds_ratio = if let Some(ratio) = resp.response_message_len.checked_mul(ratio) {
1304
251k
            resp.response_entity_len > ratio
1305
        } else {
1306
            // overflow occured
1307
0
            true
1308
        };
1309
1310
251k
        let bomb_limit = compression_options.get_bomb_limit();
1311
251k
        let response_entity_len = resp.response_entity_len;
1312
251k
        let response_message_len = resp.response_message_len;
1313
251k
        if response_entity_len > bomb_limit && exceeds_ratio {
1314
104
            htp_error!(
1315
104
                self.logger,
1316
104
                HtpLogCode::COMPRESSION_BOMB,
1317
104
                format!(
1318
104
                    "Compression bomb: decompressed {} bytes out of {}",
1319
104
                    response_entity_len, response_message_len,
1320
104
                )
1321
104
            );
1322
104
            self.bombs += 1;
1323
104
            if self.bombs == compression_options.get_max_bombs() {
1324
18
                htp_error!(
1325
18
                    self.logger,
1326
18
                    HtpLogCode::COMPRESSION_BOMB_LIMIT_REACHED,
1327
18
                    format!("Compression bomb: happened {} times", self.bombs,)
1328
18
                );
1329
86
            }
1330
104
            return Err(std::io::Error::other("compression_bomb_limit reached"));
1331
251k
        }
1332
251k
        Ok(tx_data.len())
1333
251k
    }
1334
1335
    /// Prepend response decompressor
1336
26.7k
    fn response_prepend_decompressor(&mut self, encoding: HtpContentEncoding) -> Result<()> {
1337
26.7k
        let compression_options = self.cfg.compression_options;
1338
26.7k
        if self.bombs >= compression_options.get_max_bombs() {
1339
            // skip decompression for this flow if too many bombs were seen
1340
84
            self.response_mut()
1341
84
                .unwrap()
1342
84
                .response_content_encoding_processing = HtpContentEncoding::None;
1343
84
            return Ok(());
1344
26.6k
        }
1345
26.6k
        if encoding != HtpContentEncoding::None {
1346
            // ensured by caller
1347
23.8k
            let resp = self.response_mut().unwrap();
1348
23.8k
            if let Some(decompressor) = resp.response_decompressor.take() {
1349
2.45k
                let decompressor = decompressor.prepend(encoding, compression_options)?;
1350
2.45k
                resp.response_decompressor.replace(decompressor);
1351
            } else {
1352
                // The processing encoding will be the first one encountered
1353
21.3k
                resp.response_content_encoding_processing = encoding;
1354
1355
                // Add the callback first because it will be called last in
1356
                // the chain of writers
1357
1358
                // TODO: fix lifetime error and remove this line!
1359
21.3k
                let connp_ptr = self as *mut Self;
1360
21.3k
                let decompressor = unsafe {
1361
21.3k
                    Decompressor::new_with_callback(
1362
21.3k
                        encoding,
1363
251k
                        Box::new(move |data: Option<&[u8]>| -> std::io::Result<usize> {
1364
251k
                            (*connp_ptr).response_decompressor_callback(data)
1365
251k
                        }),
1366
21.3k
                        compression_options,
1367
0
                    )?
1368
                };
1369
21.3k
                self.response_mut()
1370
21.3k
                    .unwrap()
1371
21.3k
                    .response_decompressor
1372
21.3k
                    .replace(decompressor);
1373
            }
1374
2.80k
        }
1375
26.6k
        Ok(())
1376
26.7k
    }
1377
1378
    /// Finalizes response parsing.
1379
885k
    pub(crate) fn response_finalize(&mut self, input: &mut ParserData) -> Result<()> {
1380
885k
        if input.is_gap() {
1381
65
            return self.state_response_complete(input);
1382
885k
        }
1383
885k
        let mut work = input.as_slice();
1384
885k
        if self.response_status != HtpStreamState::CLOSED {
1385
877k
            let response_next_byte = input.as_slice().first();
1386
877k
            if response_next_byte.is_none() {
1387
236k
                return self.state_response_complete(input);
1388
640k
            }
1389
640k
            let lf = response_next_byte
1390
640k
                .map(|byte| *byte == b'\n')
1391
640k
                .unwrap_or(false);
1392
640k
            if !lf {
1393
603k
                if let Ok((_, line)) = take_till_lf(work) {
1394
575k
                    self.response_data_consume(input, line.len());
1395
575k
                    work = line;
1396
575k
                } else {
1397
27.7k
                    return self.handle_response_absent_lf(input);
1398
                }
1399
37.1k
            } else {
1400
37.1k
                self.response_data_consume(input, work.len());
1401
37.1k
            }
1402
8.41k
        }
1403
620k
        if !self.response_buf.is_empty() {
1404
18.5k
            self.check_response_buffer_limit(work.len())?;
1405
602k
        }
1406
620k
        let mut data = take(&mut self.response_buf);
1407
620k
        let buf_len = data.len();
1408
620k
        data.add(work);
1409
1410
620k
        if data.is_empty() {
1411
            //closing
1412
7.93k
            return self.state_response_complete(input);
1413
612k
        }
1414
612k
        if treat_response_line_as_body(&data) {
1415
            // Interpret remaining bytes as body data
1416
519k
            htp_warn!(
1417
519k
                self.logger,
1418
519k
                HtpLogCode::RESPONSE_BODY_UNEXPECTED,
1419
519k
                "Unexpected response body"
1420
519k
            );
1421
519k
            return self.response_body_data(Some(data.as_slice()));
1422
93.8k
        }
1423
        // didnt use data, restore
1424
93.8k
        self.response_buf.add(&data[0..buf_len]);
1425
        //unread last end of line so that RES_LINE works
1426
93.8k
        self.response_data_unconsume(input, data.len());
1427
93.8k
        self.state_response_complete(input)
1428
885k
    }
1429
1430
    /// The response idle state will initialize response processing, as well as
1431
    /// finalize each transactions after we are done with it.
1432
    ///
1433
    /// Returns HtpStatus::OK on state change, HtpStatus::ERROR on error, or HtpStatus::DATA
1434
    /// when more data is needed.
1435
596k
    pub(crate) fn response_idle(&mut self, input: &ParserData) -> Result<()> {
1436
        // We want to start parsing the next response (and change
1437
        // the state from IDLE) only if there's at least one
1438
        // byte of data available. Otherwise we could be creating
1439
        // new structures even if there's no more data on the
1440
        // connection.
1441
596k
        if input.is_empty() {
1442
248k
            return Err(HtpStatus::DATA);
1443
347k
        }
1444
1445
        // Parsing a new response
1446
        // Log if we have not seen the corresponding request yet
1447
347k
        let resp = self.response();
1448
347k
        if resp.is_none() {
1449
5
            return Err(HtpStatus::ERROR);
1450
347k
        }
1451
347k
        if resp.unwrap().request_progress == HtpRequestProgress::NOT_STARTED {
1452
214k
            htp_error!(
1453
214k
                self.logger,
1454
214k
                HtpLogCode::UNABLE_TO_MATCH_RESPONSE_TO_REQUEST,
1455
214k
                "Unable to match response to request"
1456
214k
            );
1457
214k
            if self.request_state == State::Finalize {
1458
3.15k
                let _ = self.state_request_complete(&mut ParserData::from(None));
1459
211k
            }
1460
214k
            let tx = self.response_mut();
1461
214k
            if tx.is_none() {
1462
0
                return Err(HtpStatus::ERROR);
1463
214k
            }
1464
214k
            let tx = tx.unwrap();
1465
1466
214k
            let uri = Uri {
1467
214k
                path: Some(Bstr::from("/libhtp::request_uri_not_seen")),
1468
214k
                ..Default::default()
1469
214k
            };
1470
214k
            tx.request_uri = uri.path.clone();
1471
214k
            tx.parsed_uri = Some(uri);
1472
214k
            tx.request_progress = HtpRequestProgress::COMPLETE;
1473
214k
            self.request_next();
1474
132k
        }
1475
347k
        self.response_content_length = None;
1476
347k
        self.response_body_data_left = None;
1477
347k
        self.state_response_start()
1478
596k
    }
1479
1480
    /// Run the RESPONSE_BODY_DATA hook.
1481
2.04M
    fn response_run_hook_body_data(&mut self, d: &mut Data) -> Result<()> {
1482
        // Do not invoke callbacks with an empty data chunk.
1483
2.04M
        if d.is_empty() {
1484
264k
            return Ok(());
1485
1.78M
        }
1486
1.78M
        let resp = self.response().unwrap();
1487
        // Run transaction hooks first
1488
1.78M
        resp.hook_response_body_data.clone().run_all(self, d)?;
1489
        // Run configuration hooks second
1490
1.78M
        self.cfg.hook_response_body_data.run_all(self, d)?;
1491
1.78M
        Ok(())
1492
2.04M
    }
1493
1494
    /// Process a chunk of outbound (server or response) data.
1495
739k
    pub(crate) fn response_data(
1496
739k
        &mut self, mut chunk: ParserData, timestamp: Option<OffsetDateTime>,
1497
739k
    ) -> HtpStreamState {
1498
        // Reset consumed data tracker
1499
739k
        self.response_bytes_consumed = 0;
1500
1501
        // Return if the connection is in stop state
1502
739k
        if self.response_status == HtpStreamState::STOP {
1503
0
            htp_info!(
1504
0
                self.logger,
1505
0
                HtpLogCode::PARSER_STATE_ERROR,
1506
0
                "Outbound parser is in HTP_STREAM_STATE_STOP"
1507
0
            );
1508
0
            return HtpStreamState::STOP;
1509
739k
        }
1510
        // Return if the connection has had a fatal error
1511
739k
        if self.response_status == HtpStreamState::ERROR {
1512
20
            htp_error!(
1513
20
                self.logger,
1514
20
                HtpLogCode::PARSER_STATE_ERROR,
1515
20
                "Outbound parser is in HTP_STREAM_STATE_ERROR"
1516
20
            );
1517
20
            return HtpStreamState::ERROR;
1518
739k
        }
1519
1520
        // If the length of the supplied data chunk is zero, proceed
1521
        // only if the stream has been closed. We do not allow zero-sized
1522
        // chunks in the API, but we use it internally to force the parsers
1523
        // to finalize parsing.
1524
739k
        if chunk.is_empty() && self.response_status != HtpStreamState::CLOSED {
1525
0
            htp_error!(
1526
0
                self.logger,
1527
0
                HtpLogCode::ZERO_LENGTH_DATA_CHUNKS,
1528
0
                "Zero-length data chunks are not allowed"
1529
0
            );
1530
0
            return HtpStreamState::CLOSED;
1531
739k
        }
1532
        // Remember the timestamp of the current response data chunk
1533
739k
        if let Some(timestamp) = timestamp {
1534
739k
            self.response_timestamp = timestamp;
1535
739k
        }
1536
1537
        // Store the current chunk information
1538
739k
        self.conn.track_outbound_data(chunk.len());
1539
        // Return without processing any data if the stream is in tunneling
1540
        // mode (which it would be after an initial CONNECT transaction.
1541
739k
        if self.response_status == HtpStreamState::TUNNEL {
1542
2.62k
            return HtpStreamState::TUNNEL;
1543
737k
        }
1544
737k
        if chunk.is_gap() {
1545
            // Mark the transaction as having a gap
1546
3.65k
            let idx = self.request_index();
1547
3.65k
            let resp = self.response_mut();
1548
3.65k
            if resp.is_none() {
1549
0
                return HtpStreamState::ERROR;
1550
3.65k
            }
1551
3.65k
            let resp = resp.unwrap();
1552
1553
3.65k
            resp.flags.set(HtpFlags::RESPONSE_MISSING_BYTES);
1554
1555
3.65k
            if idx == 0 && resp.response_progress == HtpResponseProgress::NOT_STARTED {
1556
                // We have a leading gap on the first transaction.
1557
1.05k
                return HtpStreamState::CLOSED;
1558
2.60k
            }
1559
733k
        }
1560
1561
        loop
1562
        // Invoke a processor, in a loop, until an error
1563
        // occurs or until we run out of data. Many processors
1564
        // will process a request, each pointing to the next
1565
        // processor that needs to run.
1566
        // Return if there's been an error
1567
        // or if we've run out of data. We are relying
1568
        // on processors to add error messages, so we'll
1569
        // keep quiet here.
1570
        {
1571
3.93M
            if chunk.is_gap()
1572
2.72k
                && self.response_state != State::BodyIdentityCLKnown
1573
1.98k
                && self.response_state != State::BodyIdentityStreamClose
1574
1.86k
                && self.response_state != State::Finalize
1575
            {
1576
1.80k
                htp_error!(
1577
1.80k
                    self.logger,
1578
1.80k
                    HtpLogCode::INVALID_GAP,
1579
1.80k
                    "Gaps are not allowed during this state"
1580
1.80k
                );
1581
1.80k
                return HtpStreamState::CLOSED;
1582
3.93M
            }
1583
3.93M
            let mut rc = self.handle_response_state(&mut chunk);
1584
1585
3.93M
            if rc.is_ok() {
1586
3.20M
                if self.response_status == HtpStreamState::TUNNEL {
1587
2.69k
                    return HtpStreamState::TUNNEL;
1588
3.20M
                }
1589
3.20M
                rc = self.response_handle_state_change(&mut chunk);
1590
731k
            }
1591
731k
            match rc {
1592
                // Continue looping.
1593
3.20M
                Ok(_) => {}
1594
                // Do we need more data?
1595
                Err(HtpStatus::DATA) | Err(HtpStatus::DATA_BUFFER) => {
1596
                    // Ignore result.
1597
731k
                    let _ = self.response_receiver_send_data(&mut chunk);
1598
731k
                    self.response_status = HtpStreamState::DATA;
1599
731k
                    return HtpStreamState::DATA;
1600
                }
1601
                // Check for stop
1602
                Err(HtpStatus::STOP) => {
1603
0
                    self.response_status = HtpStreamState::STOP;
1604
0
                    return HtpStreamState::STOP;
1605
                }
1606
                // Check for suspended parsing
1607
                Err(HtpStatus::DATA_OTHER) => {
1608
                    // We might have actually consumed the entire data chunk?
1609
51
                    if chunk.is_empty() {
1610
20
                        self.response_status = HtpStreamState::DATA;
1611
                        // Do not send STREAM_DATE_DATA_OTHER if we've
1612
                        // consumed the entire chunk
1613
20
                        return HtpStreamState::DATA;
1614
                    } else {
1615
31
                        self.response_status = HtpStreamState::DATA_OTHER;
1616
                        // Partial chunk consumption
1617
31
                        return HtpStreamState::DATA_OTHER;
1618
                    }
1619
                }
1620
                // Permanent stream error.
1621
                Err(_) => {
1622
95
                    self.response_status = HtpStreamState::ERROR;
1623
95
                    return HtpStreamState::ERROR;
1624
                }
1625
            }
1626
        }
1627
739k
    }
1628
1629
    /// Advance out buffer cursor and buffer data.
1630
262k
    fn handle_response_absent_lf(&mut self, data: &ParserData) -> Result<()> {
1631
262k
        self.check_response_buffer_limit(data.len())?;
1632
262k
        self.response_buf.add(data.as_slice());
1633
262k
        self.response_data_consume(data, data.len());
1634
262k
        Err(HtpStatus::DATA_BUFFER)
1635
262k
    }
1636
}