Coverage Report

Created: 2026-11-12 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata8/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, sequence::tuple};
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
611k
    fn response_receiver_send_data(&mut self, data: &mut ParserData) -> Result<()> {
32
611k
        let data = ParserData::from(data.callback_data());
33
611k
        let resp = self.response_mut();
34
611k
        if resp.is_none() {
35
5
            return Err(HtpStatus::ERROR);
36
611k
        }
37
611k
        let mut tx_data = Data::new(resp.unwrap(), &data);
38
611k
        if let Some(hook) = &self.response_data_receiver_hook {
39
203k
            hook.run_all(self, &mut tx_data)?;
40
        } else {
41
408k
            return Ok(());
42
        };
43
203k
        Ok(())
44
611k
    }
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
143k
    pub(crate) fn response_receiver_finalize_clear(
49
143k
        &mut self, input: &mut ParserData,
50
143k
    ) -> Result<()> {
51
143k
        if self.response_data_receiver_hook.is_none() {
52
87.1k
            return Ok(());
53
55.8k
        }
54
55.8k
        let rc = self.response_receiver_send_data(input);
55
55.8k
        self.response_data_receiver_hook = None;
56
55.8k
        rc
57
143k
    }
58
59
    /// Configures the data receiver hook.
60
57.2k
    fn response_receiver_set(&mut self, data_receiver_hook: Option<DataHook>) -> Result<()> {
61
57.2k
        self.response_data_receiver_hook = data_receiver_hook;
62
57.2k
        Ok(())
63
57.2k
    }
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
2.02M
    fn response_handle_state_change(&mut self, input: &mut ParserData) -> Result<()> {
68
2.02M
        if self.response_state_previous == self.response_state {
69
1.62M
            return Ok(());
70
396k
        }
71
72
396k
        if self.response_state == State::Headers {
73
57.2k
            let resp = self.response_mut();
74
57.2k
            if resp.is_none() {
75
0
                return Err(HtpStatus::ERROR);
76
57.2k
            }
77
57.2k
            let resp = resp.unwrap();
78
57.2k
            let header_fn = Some(resp.cfg.hook_response_header_data.clone());
79
57.2k
            let trailer_fn = Some(resp.cfg.hook_response_trailer_data.clone());
80
57.2k
            input.reset_callback_start();
81
82
57.2k
            match resp.response_progress {
83
5.16k
                HtpResponseProgress::TRAILER => self.response_receiver_set(trailer_fn),
84
                // response_state == State::Headers can have progress LINE after a 100 continue
85
52.0k
                _ => self.response_receiver_set(header_fn),
86
0
            }?;
87
338k
        }
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
396k
        self.response_state_previous = self.response_state;
96
396k
        Ok(())
97
2.02M
    }
98
99
    /// The maximum amount accepted for buffering is controlled
100
    /// by htp_config_t::field_limit.
101
1.36M
    fn check_response_buffer_limit(&mut self, len: usize) -> Result<()> {
102
1.36M
        if len == 0 {
103
4.31k
            return Ok(());
104
1.35M
        }
105
        // Check the hard (buffering) limit.
106
1.35M
        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.35M
        if let Some(response_header) = &self.response_header {
110
143k
            newlen = newlen.wrapping_add(response_header.len());
111
1.21M
        }
112
1.35M
        let field_limit = self.cfg.field_limit;
113
1.35M
        if newlen > field_limit {
114
34
            htp_error!(
115
34
                self.logger,
116
34
                HtpLogCode::RESPONSE_FIELD_TOO_LONG,
117
34
                format!(
118
34
                    "Response the buffer limit: size {} limit {}.",
119
34
                    newlen, field_limit
120
34
                )
121
34
            );
122
34
            return Err(HtpStatus::ERROR);
123
1.35M
        }
124
1.35M
        Ok(())
125
1.36M
    }
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
1.35k
    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
1.35k
        let resp = self.response_mut();
135
1.35k
        if resp.is_none() {
136
0
            return Err(HtpStatus::ERROR);
137
1.35k
        }
138
1.35k
        let resp = resp.unwrap();
139
140
1.35k
        if let Ok((_, line)) = take_till_lf(input.as_slice()) {
141
1.06k
            let len = line.len();
142
1.06k
            self.response_data_consume(input, len);
143
1.06k
            let resp = self.response_mut().unwrap();
144
1.06k
            resp.response_message_len = resp.response_message_len.wrapping_add(len as u64);
145
1.06k
            self.response_state = State::BodyChunkedLength;
146
1.06k
            Ok(())
147
        } else {
148
            // Advance to end. Dont need to buffer
149
289
            resp.response_message_len = resp.response_message_len.wrapping_add(input.len() as u64);
150
289
            self.response_data_consume(input, input.len());
151
289
            Err(HtpStatus::DATA_BUFFER)
152
        }
153
1.35k
    }
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
2.37k
    pub(crate) fn response_body_chunked_data(&mut self, input: &ParserData) -> Result<()> {
160
2.37k
        if self.response_status == HtpStreamState::CLOSED {
161
11
            self.response_state = State::Finalize;
162
            // Sends close signal to decompressors
163
11
            return self.response_body_data(input.data());
164
2.35k
        }
165
2.35k
        let bytes_to_consume = min(
166
2.35k
            input.len(),
167
2.35k
            self.response_chunked_length.unwrap_or(0) as usize,
168
        );
169
2.35k
        if bytes_to_consume == 0 {
170
19
            return Err(HtpStatus::DATA);
171
2.34k
        }
172
        // Consume the data.
173
2.34k
        self.response_body_data(Some(&input.as_slice()[0..bytes_to_consume]))?;
174
        // Adjust the counters.
175
2.34k
        self.response_data_consume(input, bytes_to_consume);
176
2.34k
        if let Some(len) = &mut self.response_chunked_length {
177
2.34k
            *len -= bytes_to_consume as u64;
178
            // Have we seen the entire chunk?
179
2.34k
            if *len == 0 {
180
1.07k
                self.response_state = State::BodyChunkedDataEnd;
181
1.07k
                return Ok(());
182
1.26k
            }
183
0
        }
184
185
1.26k
        Err(HtpStatus::DATA)
186
2.37k
    }
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
7.16k
    pub(crate) fn response_body_chunked_length(&mut self, input: &mut ParserData) -> Result<()> {
192
7.16k
        let mut data = input.as_slice();
193
        loop {
194
7.99k
            let buf_empty = self.response_buf.is_empty();
195
7.99k
            let resp = self.response_mut();
196
7.99k
            if resp.is_none() {
197
0
                return Err(HtpStatus::ERROR);
198
7.99k
            }
199
7.99k
            let resp = resp.unwrap();
200
201
7.99k
            match take_till_lf(data) {
202
7.29k
                Ok((remaining, line)) => {
203
7.29k
                    self.response_data_consume(input, line.len());
204
7.29k
                    if !buf_empty {
205
177
                        self.check_response_buffer_limit(line.len())?;
206
7.11k
                    }
207
7.29k
                    let mut data2 = take(&mut self.response_buf);
208
7.29k
                    data2.add(line);
209
7.29k
                    if is_chunked_ctl_line(&data2) {
210
836
                        let resp = self.response_mut().unwrap();
211
836
                        resp.response_message_len =
212
836
                            (resp.response_message_len).wrapping_add(data2.len() as u64);
213
                        //Empty chunk len. Try to continue parsing.
214
836
                        data = remaining;
215
836
                        continue;
216
6.45k
                    }
217
6.45k
                    let resp = self.response_mut().unwrap();
218
6.45k
                    resp.response_message_len =
219
6.45k
                        (resp.response_message_len).wrapping_add(data2.len() as u64);
220
221
6.45k
                    match parse_chunked_length(&data2) {
222
6.34k
                        Ok((len, ext)) => {
223
6.34k
                            self.response_chunked_length = len;
224
6.34k
                            if ext {
225
318
                                let mut flags = 0; // unused but needed by macro
226
318
                                htp_warn_once!(
227
303
                                    self.logger,
228
303
                                    HtpLogCode::RESPONSE_CHUNK_EXTENSION,
229
303
                                    "Response chunk extension",
230
318
                                    self.response_mut().unwrap().flags,
231
318
                                    flags,
232
                                    HtpFlags::FIELD_RESP_CHUNK_EXTENSION
233
                                );
234
6.03k
                            }
235
                            // Handle chunk length
236
6.34k
                            if let Some(len) = len {
237
6.33k
                                match len.cmp(&0) {
238
                                    Ordering::Equal => {
239
                                        // End of data
240
5.16k
                                        self.response_state = State::Headers;
241
5.16k
                                        self.response_mut().unwrap().response_progress =
242
5.16k
                                            HtpResponseProgress::TRAILER
243
                                    }
244
                                    Ordering::Greater => {
245
                                        // More data available.
246
1.16k
                                        self.response_state = State::BodyChunkedData
247
                                    }
248
0
                                    _ => {}
249
                                }
250
                            } else {
251
19
                                return Ok(()); // empty chunk length line, lets try to continue
252
                            }
253
                        }
254
105
                        Err(_) => {
255
105
                            // unconsume so response_body_identity_stream_close doesn't miss the first bytes
256
105
                            self.response_data_unconsume(input, line.len());
257
105
                            self.response_state = State::BodyIdentityStreamClose;
258
105
                            self.response_mut().unwrap().response_transfer_coding =
259
105
                                HtpTransferCoding::Identity;
260
105
                            htp_error!(
261
105
                                self.logger,
262
105
                                HtpLogCode::INVALID_RESPONSE_CHUNK_LEN,
263
105
                                "Response chunk encoding: Invalid chunk length"
264
105
                            );
265
105
                        }
266
                    }
267
268
6.43k
                    return Ok(());
269
                }
270
                _ => {
271
                    // Check if the data we have seen so far is invalid
272
709
                    if buf_empty && !is_valid_chunked_length_data(data) {
273
                        // Contains leading junk non hex_ascii data
274
21
                        resp.response_transfer_coding = HtpTransferCoding::Identity;
275
21
                        self.response_state = State::BodyIdentityStreamClose;
276
21
                        htp_error!(
277
21
                            self.logger,
278
21
                            HtpLogCode::INVALID_RESPONSE_CHUNK_LEN,
279
21
                            "Response chunk encoding: Invalid chunk length"
280
21
                        );
281
21
                        return Ok(());
282
                    } else {
283
688
                        return self.handle_response_absent_lf(input);
284
                    }
285
                }
286
            }
287
        }
288
7.16k
    }
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
10.5k
    pub(crate) fn response_body_identity_cl_known(&mut self, data: &mut ParserData) -> Result<()> {
295
10.5k
        if self.response_status == HtpStreamState::CLOSED {
296
74
            self.response_state = State::Finalize;
297
            // Sends close signal to decompressors
298
74
            return self.response_body_data(data.data());
299
10.4k
        }
300
10.4k
        let left = self.response_body_data_left.ok_or(HtpStatus::ERROR)?;
301
10.4k
        let bytes_to_consume = std::cmp::min(data.len() as u64, left);
302
10.4k
        if bytes_to_consume == 0 {
303
395
            return Err(HtpStatus::DATA);
304
10.0k
        }
305
10.0k
        if data.is_gap() {
306
163
            let resp = self.response_mut();
307
163
            if resp.is_none() {
308
0
                return Err(HtpStatus::ERROR);
309
163
            }
310
163
            let resp = resp.unwrap();
311
312
163
            if resp.response_content_encoding_processing == HtpContentEncoding::None {
313
142
                resp.response_message_len =
314
142
                    resp.response_message_len.wrapping_add(bytes_to_consume);
315
                // Create a new gap of the appropriate length
316
142
                let parser_data = ParserData::from(bytes_to_consume as usize);
317
                // Send the gap to the data hooks
318
142
                let mut tx_data = Data::new(resp, &parser_data);
319
142
                self.response_run_hook_body_data(&mut tx_data)?;
320
            } else {
321
                // end decompression on gap
322
21
                self.response_body_data(None)?;
323
            }
324
        } else {
325
            // Consume the data.
326
9.87k
            self.response_body_data(Some(&data.as_slice()[0..bytes_to_consume as usize]))?;
327
        }
328
        // Adjust the counters.
329
10.0k
        self.response_data_consume(data, bytes_to_consume as usize);
330
10.0k
        self.response_body_data_left = Some(left - bytes_to_consume);
331
        // Have we seen the entire response body?
332
10.0k
        if self.response_body_data_left > Some(0) {
333
5.53k
            return Err(HtpStatus::DATA);
334
4.48k
        }
335
        // End of response body.
336
4.48k
        self.response_state = State::Finalize;
337
        // Sends close signal to decompressors, outputting any partially decompressed data
338
4.48k
        self.response_body_data(None)
339
10.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
176k
    pub(crate) fn response_body_identity_stream_close(&mut self, data: &ParserData) -> Result<()> {
347
176k
        if !data.is_empty() {
348
            // Consume all data from the input buffer.
349
175k
            self.response_body_data(data.data())?;
350
            // Adjust the counters.
351
175k
            self.response_data_consume(data, data.len());
352
1.52k
        }
353
        // Have we seen the entire response body?
354
176k
        if self.response_status == HtpStreamState::CLOSED {
355
708
            self.response_state = State::Finalize;
356
708
            return Ok(());
357
176k
        }
358
359
176k
        Err(HtpStatus::DATA)
360
176k
    }
361
362
    /// Determines presence (and encoding) of a response body.
363
50.7k
    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
50.7k
        let response_tx = self.response_mut();
368
50.7k
        if response_tx.is_none() {
369
0
            return Err(HtpStatus::ERROR);
370
50.7k
        }
371
50.7k
        let response_tx = response_tx.unwrap();
372
373
50.7k
        if response_tx.request_method_number == HtpMethod::CONNECT {
374
1.15k
            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
15
                self.response_state = State::Finalize;
381
                // we may have response headers
382
15
                return self.state_response_headers(input);
383
1.13k
            } else if response_tx.response_status_number.eq_num(407) {
384
                // proxy telling us to auth
385
1
                if self.request_status != HtpStreamState::ERROR {
386
1
                    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
1.13k
                if self.request_status != HtpStreamState::ERROR {
392
1.13k
                    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
1.13k
                self.response_data_other_at_tx_end = true
398
            }
399
49.6k
        }
400
50.7k
        let response_tx = self.response_mut().unwrap();
401
50.7k
        let cl_opt = response_tx
402
50.7k
            .response_headers
403
50.7k
            .get_nocase_nozero("content-length")
404
50.7k
            .cloned();
405
50.7k
        let te_opt = response_tx
406
50.7k
            .response_headers
407
50.7k
            .get_nocase_nozero("transfer-encoding")
408
50.7k
            .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
50.7k
        if response_tx.response_status_number.eq_num(101) {
416
35
            if response_tx
417
35
                .response_headers
418
35
                .get_nocase_nozero("upgrade")
419
35
                .map(|upgrade| upgrade.value.index_of_nocase_nozero("h2c").is_some())
420
35
                .unwrap_or(false)
421
1
            {
422
1
                response_tx.is_http_2_upgrade = true;
423
34
            }
424
35
            if te_opt.is_none() && cl_opt.is_none() {
425
31
                self.response_state = State::Finalize;
426
31
                if self.request_status != HtpStreamState::ERROR {
427
30
                    self.request_status = HtpStreamState::TUNNEL
428
1
                }
429
31
                self.response_status = HtpStreamState::TUNNEL;
430
                // we may have response headers
431
31
                return self.state_response_headers(input);
432
4
            } else {
433
4
                htp_warn!(
434
4
                    self.logger,
435
4
                    HtpLogCode::SWITCHING_PROTO_WITH_CONTENT_LENGTH,
436
4
                    "Switching Protocol with Content-Length"
437
4
                );
438
4
            }
439
        }
440
        // Check for an interim "100 Continue" response. Ignore it if found, and revert back to RES_LINE.
441
50.7k
        else if response_tx.response_status_number.eq_num(100) && te_opt.is_none() {
442
1.99k
            match cl_opt
443
1.99k
                .as_ref()
444
1.99k
                .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
15
                Some(x) if x > 0 => (),
449
                // Otherwise we treat it as a continue and prep for the next response
450
                _ => {
451
1.98k
                    let response_tx = self.response_mut().unwrap();
452
1.98k
                    if response_tx.seen_100continue {
453
441
                        let mut flags = 0; // unused but needed by macro
454
441
                        htp_warn_once!(
455
231
                            self.logger,
456
231
                            HtpLogCode::CONTINUE_ALREADY_SEEN,
457
231
                            "Already seen 100-Continue.",
458
441
                            self.response_mut().unwrap().flags,
459
441
                            flags,
460
                            HtpFlags::FIELD_100_CONTINUE
461
                        );
462
1.54k
                    }
463
                    // Expecting to see another response line next.
464
1.98k
                    self.response_state = State::Line;
465
1.98k
                    let response_tx = self.response_mut().unwrap();
466
                    // Ignore any response headers seen so far.
467
1.98k
                    response_tx.response_headers.elements.clear();
468
1.98k
                    response_tx.seen_100continue = true;
469
1.98k
                    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
48.7k
        else if response_tx.response_status_number.in_range(400, 499)
477
768
            && self.request_content_length > Some(0)
478
546
            && self.request_body_data_left == self.request_content_length
479
        {
480
219
            let response_tx = self.response_mut().unwrap();
481
219
            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
219
            }
486
48.5k
        }
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
48.7k
        let response_tx = self.response_mut().unwrap();
494
48.7k
        if response_tx.request_method_number == HtpMethod::HEAD {
495
            // There's no response body whatsoever
496
0
            response_tx.response_transfer_coding = HtpTransferCoding::NoBody;
497
0
            self.response_state = State::Finalize
498
48.7k
        } else if response_tx.response_status_number.in_range(100, 199)
499
14.2k
            || response_tx.response_status_number.eq_num(204)
500
13.5k
            || 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
35.4k
            if te_opt.is_none() && cl_opt.is_none() {
505
34.9k
                response_tx.response_transfer_coding = HtpTransferCoding::NoBody;
506
34.9k
                self.response_state = State::Finalize
507
523
            } else {
508
523
                htp_warn!(
509
523
                    self.logger,
510
523
                    HtpLogCode::RESPONSE_BODY_UNEXPECTED,
511
523
                    "Unexpected Response body"
512
523
                );
513
523
            }
514
13.3k
        }
515
        // Hack condition to check that we do not assume "no body"
516
48.7k
        let mut multipart_byteranges = false;
517
48.7k
        if self.response_state != State::Finalize {
518
            // We have a response body
519
13.8k
            let response_tx = self.response_mut().unwrap();
520
13.8k
            let response_content_type = if let Some(ct) = response_tx
521
13.8k
                .response_headers
522
13.8k
                .get_nocase_nozero("content-type")
523
            {
524
                // TODO Some platforms may do things differently here.
525
8.90k
                let response_content_type = if let Ok((_, ct)) =
526
563k
                    streaming_take_till::<_, _, (&[u8], ErrorKind)>(|c| c == b';' || is_space(c))(
527
8.90k
                        &ct.value,
528
                    ) {
529
5.74k
                    ct
530
                } else {
531
3.16k
                    &ct.value
532
                };
533
534
8.90k
                let mut response_content_type = Bstr::from(response_content_type);
535
8.90k
                response_content_type.make_ascii_lowercase();
536
8.90k
                if response_content_type
537
8.90k
                    .index_of_nocase("multipart/byteranges")
538
8.90k
                    .is_some()
539
0
                {
540
0
                    multipart_byteranges = true;
541
8.90k
                }
542
8.90k
                Some(response_content_type)
543
            } else {
544
4.93k
                None
545
            };
546
547
13.8k
            if response_content_type.is_some() {
548
8.90k
                response_tx.response_content_type = response_content_type;
549
8.90k
            }
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
5.42k
            if let Some(te) =
554
13.8k
                te_opt.and_then(|te| te.value.index_of_nocase_nozero("chunked").and(Some(te)))
555
            {
556
5.42k
                if !te.value.cmp_nocase("chunked") {
557
1.56k
                    htp_warn!(
558
1.56k
                        self.logger,
559
1.56k
                        HtpLogCode::RESPONSE_ABNORMAL_TRANSFER_ENCODING,
560
1.56k
                        "Transfer-encoding has abnormal chunked value"
561
1.56k
                    );
562
3.86k
                }
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
5.42k
                let response_tx = self.response_mut().unwrap();
567
5.42k
                if response_tx.response_protocol_number < HtpProtocol::V1_1 {
568
4.86k
                    htp_warn!(
569
4.86k
                        self.logger,
570
4.86k
                        HtpLogCode::RESPONSE_CHUNKED_OLD_PROTO,
571
4.86k
                        "Chunked transfer-encoding on HTTP/0.9 or HTTP/1.0"
572
4.86k
                    );
573
4.86k
                }
574
                // If the T-E header is present we are going to use it.
575
5.42k
                let response_tx = self.response_mut().unwrap();
576
5.42k
                response_tx.response_transfer_coding = HtpTransferCoding::Chunked;
577
                // We are still going to check for the presence of C-L
578
5.42k
                if cl_opt.is_some() {
579
                    // This is a violation of the RFC
580
2.55k
                    response_tx.flags.set(HtpFlags::REQUEST_SMUGGLING)
581
2.87k
                }
582
5.42k
                response_tx.response_progress = HtpResponseProgress::BODY;
583
5.42k
                self.response_state = State::BodyChunkedLength
584
8.41k
            } 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
6.03k
                response_tx.response_transfer_coding = HtpTransferCoding::Identity;
588
                // Check for multiple C-L headers
589
6.03k
                if cl.flags.is_set(HtpFlags::FIELD_REPEATED) {
590
471
                    response_tx.flags.set(HtpFlags::REQUEST_SMUGGLING)
591
5.56k
                }
592
                // Get body length
593
6.03k
                let response_content_length =
594
6.03k
                    parse_content_length((*cl.value).as_slice(), Some(&mut self.logger));
595
6.03k
                self.response_mut().unwrap().response_content_length = response_content_length;
596
6.03k
                self.response_content_length = response_content_length;
597
6.03k
                self.response_body_data_left = response_content_length;
598
6.03k
                if let Some(len) = response_content_length {
599
6.03k
                    if len != 0 {
600
4.91k
                        self.response_state = State::BodyIdentityCLKnown;
601
4.91k
                        self.response_mut().unwrap().response_progress = HtpResponseProgress::BODY
602
                    } else {
603
1.11k
                        self.response_state = State::Finalize
604
                    }
605
                } else {
606
3
                    htp_error!(
607
3
                        self.logger,
608
3
                        HtpLogCode::INVALID_CONTENT_LENGTH_FIELD_IN_RESPONSE,
609
3
                        "Invalid C-L field in response"
610
3
                    );
611
3
                    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
2.37k
                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
2.37k
                }
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
2.37k
                response_tx.response_transfer_coding = HtpTransferCoding::Identity;
633
2.37k
                response_tx.response_progress = HtpResponseProgress::BODY;
634
2.37k
                self.response_state = State::BodyIdentityStreamClose;
635
2.37k
                self.response_body_data_left = None
636
            }
637
34.9k
        }
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
48.7k
        self.state_response_headers(input)
641
50.7k
    }
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.06M
    pub(crate) fn response_line(&mut self, input: &ParserData) -> Result<()> {
648
1.06M
        match take_till_eol(input.as_slice()) {
649
915k
            Ok((_, (line, _))) => {
650
                // We have a line ending, so consume the input
651
                // and grab any buffered data.
652
915k
                let mut data = take(&mut self.response_buf);
653
915k
                data.add(line);
654
915k
                self.response_data_consume(input, line.len());
655
915k
                self.response_line_complete(data.as_slice(), input)
656
            }
657
            _ => {
658
151k
                if self.response_status == HtpStreamState::CLOSED {
659
1.00k
                    let mut data = take(&mut self.response_buf);
660
1.00k
                    data.add(input.as_slice());
661
1.00k
                    self.response_data_consume(input, input.len());
662
1.00k
                    self.response_line_complete(data.as_slice(), input)
663
                } else {
664
150k
                    self.handle_response_absent_lf(input)
665
                }
666
            }
667
        }
668
1.06M
    }
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
916k
    fn response_line_complete(&mut self, line: &[u8], input: &ParserData) -> Result<()> {
675
916k
        self.check_response_buffer_limit(line.len())?;
676
916k
        if line.is_empty() {
677
40
            return Err(HtpStatus::DATA);
678
916k
        }
679
916k
        let response_tx = self.response_mut();
680
916k
        if response_tx.is_none() {
681
0
            return Err(HtpStatus::ERROR);
682
916k
        }
683
916k
        if is_line_ignorable(self.cfg.server_personality, line) {
684
312k
            if self.response_status == HtpStreamState::CLOSED {
685
10
                self.response_state = State::Finalize
686
312k
            }
687
            // We have an empty/whitespace line, which we'll note, ignore and move on
688
312k
            let response_tx = self.response_mut().unwrap();
689
312k
            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
312k
            return Ok(());
693
603k
        }
694
        // Deallocate previous response line allocations, which we would have on a 100 response.
695
603k
        let response_tx = self.response_mut().unwrap();
696
603k
        response_tx.response_line = None;
697
603k
        response_tx.response_protocol = None;
698
603k
        response_tx.response_status = None;
699
603k
        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
603k
        if treat_response_line_as_body(line) {
706
            // if we have a next line beginning with H, skip this one
707
551k
            if input.len() > 1 && (input.as_slice()[0] == b'H' || chomp(line).len() <= 2) {
708
93.1k
                response_tx.response_ignored_lines =
709
93.1k
                    response_tx.response_ignored_lines.wrapping_add(1);
710
93.1k
                return Ok(());
711
458k
            }
712
458k
            response_tx.response_content_encoding_processing = HtpContentEncoding::None;
713
458k
            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
458k
            if input.is_empty() {
719
41.4k
                let response_tx = self.response_mut().unwrap();
720
41.4k
                response_tx.response_transfer_coding = HtpTransferCoding::Identity;
721
41.4k
                response_tx.response_progress = HtpResponseProgress::BODY;
722
41.4k
                self.response_body_data_left = None;
723
41.4k
                self.response_state = State::Finalize
724
416k
            }
725
458k
            return Ok(());
726
52.0k
        }
727
52.0k
        self.parse_response_line(line)?;
728
52.0k
        self.state_response_line()?;
729
        // Move on to the next phase.
730
52.0k
        self.response_state = State::Headers;
731
52.0k
        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
52.0k
        if !response_tx.response_status_number.eq_num(100) {
735
50.0k
            response_tx.response_progress = HtpResponseProgress::HEADERS;
736
50.0k
        }
737
52.0k
        Ok(())
738
916k
    }
739
740
    /// Parses the response line.
741
52.0k
    pub(crate) fn parse_response_line(&mut self, response_line: &[u8]) -> Result<()> {
742
52.0k
        let response_tx = self.response_mut();
743
52.0k
        if response_tx.is_none() {
744
0
            return Err(HtpStatus::ERROR);
745
52.0k
        }
746
52.0k
        let response_tx = response_tx.unwrap();
747
748
52.0k
        response_tx.response_line = Some(Bstr::from(response_line));
749
52.0k
        response_tx.response_protocol_number = HtpProtocol::Invalid;
750
52.0k
        response_tx.response_status = None;
751
52.0k
        response_tx.response_status_number = HtpResponseNumber::Invalid;
752
52.0k
        response_tx.response_message = None;
753
754
52.0k
        let mut response_line_parser = tuple((
755
52.0k
            take_is_space_or_null,
756
52.0k
            take_not_is_space,
757
52.0k
            take_is_space,
758
52.0k
            take_not_is_space,
759
52.0k
            take_ascii_whitespace(),
760
52.0k
        ));
761
762
52.0k
        let (message, (_ls, response_protocol, ws1, status_code, ws2)) =
763
52.0k
            response_line_parser(response_line)?;
764
52.0k
        if response_protocol.is_empty() {
765
0
            return Ok(());
766
52.0k
        }
767
768
52.0k
        response_tx.response_protocol = Some(Bstr::from(response_protocol));
769
52.0k
        self.response_mut().unwrap().response_protocol_number =
770
52.0k
            parse_protocol(response_protocol, &mut self.logger);
771
772
52.0k
        if ws1.is_empty() || status_code.is_empty() {
773
5.77k
            return Ok(());
774
46.3k
        }
775
776
46.3k
        let response_tx = self.response_mut().unwrap();
777
46.3k
        response_tx.response_status = Some(Bstr::from(status_code));
778
46.3k
        response_tx.response_status_number = parse_status(status_code);
779
780
46.3k
        if ws2.is_empty() {
781
77
            return Ok(());
782
46.2k
        }
783
784
46.2k
        response_tx.response_message = Some(Bstr::from(chomp(message)));
785
46.2k
        Ok(())
786
52.0k
    }
787
788
    /// Response header parser.
789
    ///
790
    ///Returns a tuple of the unparsed data and a boolean indicating if the EOH was seen.
791
179k
    fn parse_response_headers<'a>(&mut self, data: &'a [u8]) -> Result<(&'a [u8], bool)> {
792
179k
        let resp = self.response_mut();
793
179k
        if resp.is_none() {
794
0
            return Err(HtpStatus::ERROR);
795
179k
        }
796
797
179k
        let rc = resp.unwrap().response_header_parser.headers()(data);
798
179k
        if let Ok((remaining, (headers, eoh))) = rc {
799
662k
            for h in headers {
800
505k
                let mut flags = 0;
801
505k
                let name_flags = &h.name.flags;
802
505k
                let value_flags = &h.value.flags;
803
505k
                if value_flags.is_set(HeaderFlags::DEFORMED_EOL)
804
504k
                    || name_flags.is_set(HeaderFlags::DEFORMED_EOL)
805
1.86k
                {
806
1.86k
                    htp_warn!(
807
1.86k
                        self.logger,
808
1.86k
                        HtpLogCode::DEFORMED_EOL,
809
1.86k
                        "Weird response end of lines mix"
810
1.86k
                    );
811
504k
                }
812
                // Ignore LWS after field-name.
813
505k
                if name_flags.is_set(HeaderFlags::NAME_TRAILING_WHITESPACE) {
814
1.31k
                    htp_warn_once!(
815
95
                        self.logger,
816
95
                        HtpLogCode::RESPONSE_INVALID_LWS_AFTER_NAME,
817
95
                        "Request field invalid: LWS after name",
818
1.31k
                        self.response_mut().unwrap().flags,
819
1.31k
                        flags,
820
                        HtpFlags::FIELD_INVALID
821
                    );
822
504k
                }
823
                //If there was leading whitespace, probably was invalid folding.
824
505k
                if name_flags.is_set(HeaderFlags::NAME_LEADING_WHITESPACE) {
825
278
                    htp_warn_once!(
826
145
                        self.logger,
827
145
                        HtpLogCode::INVALID_RESPONSE_FIELD_FOLDING,
828
145
                        "Invalid response field folding",
829
278
                        self.response_mut().unwrap().flags,
830
278
                        flags,
831
                        HtpFlags::INVALID_FOLDING
832
                    );
833
278
                    flags.set(HtpFlags::FIELD_INVALID);
834
505k
                }
835
                // Check that field-name is a token
836
505k
                if name_flags.is_set(HeaderFlags::NAME_NON_TOKEN_CHARS) {
837
                    // Incorrectly formed header name.
838
67.2k
                    htp_warn_once!(
839
10.5k
                        self.logger,
840
10.5k
                        HtpLogCode::RESPONSE_HEADER_NAME_NOT_TOKEN,
841
10.5k
                        "Response header name is not a token",
842
67.2k
                        self.response_mut().unwrap().flags,
843
67.2k
                        flags,
844
                        HtpFlags::FIELD_INVALID
845
                    );
846
438k
                }
847
                // No colon?
848
505k
                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
299k
                    htp_warn_once!(
854
21.5k
                        self.logger,
855
21.5k
                        HtpLogCode::RESPONSE_FIELD_MISSING_COLON,
856
21.5k
                        "Response field invalid: colon missing",
857
299k
                        self.response_mut().unwrap().flags,
858
299k
                        flags,
859
                        HtpFlags::FIELD_UNPARSEABLE
860
                    );
861
299k
                    flags.set(HtpFlags::FIELD_INVALID);
862
206k
                } 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
206k
                }
873
505k
                self.process_response_header(Header::new_with_flags(
874
505k
                    h.name.name.into(),
875
505k
                    h.value.value.into(),
876
505k
                    flags,
877
0
                ))?;
878
            }
879
156k
            Ok((remaining, eoh))
880
        } else {
881
23.2k
            Ok((data, false))
882
        }
883
179k
    }
884
885
    /// Response header line(s) processor, which assembles folded lines
886
    /// into a single buffer before invoking the parsing function.
887
505k
    fn process_response_header(&mut self, header: Header) -> Result<()> {
888
505k
        let mut repeated = false;
889
505k
        let hl = self.cfg.number_headers_limit as usize;
890
505k
        let resp = self.response_mut();
891
505k
        if resp.is_none() {
892
0
            return Err(HtpStatus::ERROR);
893
505k
        }
894
505k
        let resp = resp.unwrap();
895
896
505k
        let reps = resp.response_header_repetitions;
897
505k
        let mut update_reps = false;
898
        // Do we already have a header with the same name?
899
505k
        if let Some(h_existing) = resp.response_headers.get_nocase_mut(header.name.as_slice()) {
900
331k
            if !h_existing.flags.is_set(HeaderFlags::FIELD_REPEATED) {
901
31.4k
                // This is the second occurence for this header.
902
31.4k
                repeated = true;
903
299k
            } else if reps < 64 {
904
193k
                update_reps = true;
905
193k
            } else {
906
106k
                return Ok(());
907
            }
908
224k
            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
224k
            if header.name.cmp_nocase("Content-Length") {
913
                // Don't use string comparison here because we want to
914
                // ignore small formatting differences.
915
1.68k
                let existing_cl = parse_content_length(&h_existing.value, None);
916
1.68k
                let new_cl = parse_content_length(&(header.value), None);
917
1.68k
                if existing_cl.is_none() || new_cl.is_none() || existing_cl != new_cl {
918
812
                    // Ambiguous response C-L value.
919
812
                    htp_warn!(
920
812
                        self.logger,
921
812
                        HtpLogCode::DUPLICATE_CONTENT_LENGTH_FIELD_IN_RESPONSE,
922
812
                        "Ambiguous response C-L value"
923
812
                    );
924
876
                }
925
222k
            } else {
926
222k
                // Add to the existing header.
927
222k
                h_existing.value.extend_from_slice(b", ");
928
222k
                h_existing.value.extend_from_slice(header.value.as_slice());
929
222k
            }
930
        } else {
931
174k
            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
174k
            }
943
174k
            resp.response_headers.elements.push(header);
944
        }
945
399k
        let resp = self.response_mut().unwrap();
946
399k
        if update_reps {
947
193k
            resp.response_header_repetitions = resp.response_header_repetitions.wrapping_add(1)
948
206k
        }
949
399k
        if repeated {
950
31.4k
            htp_warn!(
951
31.4k
                self.logger,
952
31.4k
                HtpLogCode::RESPONSE_HEADER_REPETITION,
953
31.4k
                "Repetition for header"
954
31.4k
            );
955
367k
        }
956
399k
        Ok(())
957
505k
    }
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
201k
    pub(crate) fn response_headers(&mut self, input: &mut ParserData) -> Result<()> {
962
201k
        let response_index = self.response_index();
963
201k
        if self.response_status == HtpStreamState::CLOSED {
964
491
            let resp = self.response_mut();
965
491
            if resp.is_none() {
966
0
                return Err(HtpStatus::ERROR);
967
491
            }
968
491
            let resp = resp.unwrap();
969
491
            resp.response_header_parser.set_complete(true);
970
            // Parse previous header, if any.
971
491
            if let Some(response_header) = self.response_header.take() {
972
453
                self.parse_response_headers(response_header.as_slice())?;
973
38
            }
974
            // Finalize sending raw trailer data.
975
491
            self.response_receiver_finalize_clear(input)?;
976
            // Run hook response_TRAILER
977
491
            self.cfg
978
491
                .hook_response_trailer
979
491
                .clone()
980
491
                .run_all(self, response_index)?;
981
491
            self.response_state = State::Finalize;
982
491
            return Ok(());
983
200k
        }
984
200k
        if let Ok((_, line)) = take_till_lf(input.as_slice()) {
985
179k
            if self.response_header.is_some() {
986
129k
                self.check_response_buffer_limit(line.len())?;
987
49.4k
            }
988
        } else {
989
21.7k
            let data = input.as_slice();
990
21.7k
            self.response_data_consume(input, data.len());
991
21.7k
            self.check_response_buffer_limit(data.len())?;
992
21.7k
            if let Some(rh) = &mut self.response_header {
993
13.9k
                rh.extend_from_slice(data);
994
13.9k
            } else {
995
7.75k
                self.response_header = Some(Bstr::from(data));
996
7.75k
            }
997
21.7k
            return Err(HtpStatus::DATA_BUFFER);
998
        }
999
179k
        let response_header = if let Some(mut response_header) = self.response_header.take() {
1000
129k
            response_header.add(input.as_slice());
1001
129k
            response_header
1002
        } else {
1003
49.4k
            Bstr::from(input.as_slice())
1004
        };
1005
1006
179k
        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
179k
        let eol = remaining.len() == response_header.len()
1009
22.9k
            && (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
179k
        if eoh || eol {
1012
55.9k
            if eol {
1013
6
                //Consume the EOL so it isn't included in data processing
1014
6
                self.response_data_consume(input, input.len());
1015
55.9k
            } else if remaining.len() <= input.len() {
1016
55.3k
                self.response_data_consume(input, input.len() - remaining.len());
1017
55.3k
            }
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
55.9k
                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
50.7k
                    State::BodyDetermine
1025
                } else {
1026
                    // Response trailer.
1027
                    // Finalize sending raw trailer data.
1028
5.15k
                    self.response_receiver_finalize_clear(input)?;
1029
                    // Run hook response_TRAILER.
1030
5.15k
                    self.cfg
1031
5.15k
                        .hook_response_trailer
1032
5.15k
                        .clone()
1033
5.15k
                        .run_all(self, response_index)?;
1034
                    // The next step is to finalize this response.
1035
5.15k
                    State::Finalize
1036
                };
1037
55.9k
            Ok(())
1038
        } else {
1039
123k
            self.response_data_consume(input, input.len());
1040
123k
            self.check_response_buffer_limit(remaining.len())?;
1041
123k
            let remaining = Bstr::from(remaining);
1042
123k
            self.response_header.replace(remaining);
1043
123k
            Err(HtpStatus::DATA_BUFFER)
1044
        }
1045
201k
    }
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.50M
    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.50M
        let resp = self.response_mut();
1065
1.50M
        if resp.is_none() {
1066
0
            return Err(HtpStatus::ERROR);
1067
1.50M
        }
1068
1.50M
        let resp = resp.unwrap();
1069
1070
1.50M
        resp.response_message_len = resp
1071
1.50M
            .response_message_len
1072
1.50M
            .wrapping_add(data.unwrap_or(b"").len() as u64);
1073
1074
1.50M
        match resp.response_content_encoding_processing {
1075
            HtpContentEncoding::Gzip
1076
            | HtpContentEncoding::Deflate
1077
            | HtpContentEncoding::Zlib
1078
            | HtpContentEncoding::Brotli
1079
            | HtpContentEncoding::Lzma => {
1080
                // Send data buffer to the decompressor if it exists
1081
34.3k
                if resp.response_decompressor.is_none() && data.is_none() {
1082
1.51k
                    return Ok(());
1083
32.8k
                }
1084
32.8k
                let mut decompressor = resp.response_decompressor.take().ok_or(HtpStatus::ERROR)?;
1085
32.8k
                if let Some(data) = data {
1086
30.7k
                    let _ = decompressor.decompress(data);
1087
1088
30.7k
                    if decompressor.time_spent()
1089
30.7k
                        > self.cfg.compression_options.get_time_limit() as u64
1090
2
                    {
1091
2
                        htp_error!(
1092
2
                            self.logger,
1093
2
                            HtpLogCode::COMPRESSION_BOMB,
1094
2
                            format!(
1095
2
                                "Compression bomb: spent {} us decompressing",
1096
2
                                decompressor.time_spent(),
1097
2
                            )
1098
2
                        );
1099
2
                        decompressor.set_passthrough(true);
1100
30.7k
                    }
1101
                    // put the decompressor back in its slot
1102
30.7k
                    self.response_mut()
1103
30.7k
                        .unwrap()
1104
30.7k
                        .response_decompressor
1105
30.7k
                        .replace(decompressor);
1106
2.13k
                } else {
1107
2.13k
                    // don't put the decompressor back in its slot
1108
2.13k
                    // ignore errors
1109
2.13k
                    let _ = decompressor.finish();
1110
2.13k
                }
1111
            }
1112
            HtpContentEncoding::None => {
1113
                // When there's no decompression, response_entity_len.
1114
                // is identical to response_message_len.
1115
1.47M
                let data = ParserData::from(data);
1116
1.47M
                let mut tx_data = Data::new(resp, &data);
1117
1.47M
                resp.response_entity_len =
1118
1.47M
                    resp.response_entity_len.wrapping_add(tx_data.len() as u64);
1119
1.47M
                self.response_run_hook_body_data(&mut tx_data)?;
1120
            }
1121
        }
1122
1.50M
        Ok(())
1123
1.50M
    }
1124
1125
    /// Initialize the response decompression engine. We can deal with three
1126
    /// scenarios:
1127
    ///
1128
    /// 1. Decompression is enabled, compression indicated in headers, and we decompress.
1129
    ///
1130
    /// 2. As above, but the user disables decompression by setting response_content_encoding
1131
    ///    to COMPRESSION_NONE.
1132
    ///
1133
    /// 3. Decompression is disabled and we do not attempt to enable it, but the user
1134
    ///    forces decompression by setting response_content_encoding to one of the
1135
    ///    supported algorithms.
1136
48.7k
    pub(crate) fn response_initialize_decompressors(&mut self) -> Result<()> {
1137
48.7k
        let resp = self.response_mut();
1138
48.7k
        if resp.is_none() {
1139
0
            return Err(HtpStatus::ERROR);
1140
48.7k
        }
1141
48.7k
        let resp = resp.unwrap();
1142
1143
48.7k
        let ce = resp
1144
48.7k
            .response_headers
1145
48.7k
            .get_nocase_nozero("content-encoding")
1146
48.7k
            .map(|val| val.value.clone());
1147
        // Process multiple encodings if there is no match on fast path
1148
48.7k
        let mut slow_path = false;
1149
1150
        // Fast path - try to match directly on the encoding value
1151
48.7k
        resp.response_content_encoding = if let Some(ce) = &ce {
1152
3.44k
            if ce.cmp_nocase_nozero(b"gzip") || ce.cmp_nocase_nozero(b"x-gzip") {
1153
1.84k
                HtpContentEncoding::Gzip
1154
1.59k
            } else if ce.cmp_nocase_nozero(b"deflate") || ce.cmp_nocase_nozero(b"x-deflate") {
1155
12
                HtpContentEncoding::Deflate
1156
1.58k
            } else if ce.cmp_nocase_nozero(b"lzma") {
1157
129
                HtpContentEncoding::Lzma
1158
1.45k
            } else if ce.cmp_nocase_nozero(b"br") {
1159
646
                HtpContentEncoding::Brotli
1160
809
            } else if ce.cmp_nocase_nozero(b"inflate") || ce.cmp_nocase_nozero(b"none") {
1161
7
                HtpContentEncoding::None
1162
            } else {
1163
802
                slow_path = true;
1164
802
                HtpContentEncoding::None
1165
            }
1166
        } else {
1167
45.3k
            HtpContentEncoding::None
1168
        };
1169
1170
        // Configure decompression, if enabled in the configuration.
1171
48.7k
        resp.response_content_encoding_processing = resp.response_content_encoding;
1172
1173
48.7k
        let response_content_encoding_processing = resp.response_content_encoding_processing;
1174
48.7k
        let compression_options = self.cfg.compression_options;
1175
48.7k
        match &response_content_encoding_processing {
1176
            HtpContentEncoding::Gzip
1177
            | HtpContentEncoding::Deflate
1178
            | HtpContentEncoding::Zlib
1179
            | HtpContentEncoding::Brotli
1180
            | HtpContentEncoding::Lzma => {
1181
2.63k
                self.response_prepend_decompressor(response_content_encoding_processing)?;
1182
            }
1183
            HtpContentEncoding::None => {
1184
46.1k
                if slow_path {
1185
802
                    if let Some(ce) = &ce {
1186
802
                        let mut layers = 0;
1187
802
                        let mut lzma_layers = 0;
1188
34.5k
                        for encoding in ce.split(|c| *c == b',' || *c == b' ') {
1189
2.22k
                            if encoding.is_empty() {
1190
910
                                continue;
1191
1.31k
                            }
1192
1.31k
                            layers += 1;
1193
1194
1.31k
                            if let Some(limit) = compression_options.get_layer_limit() {
1195
                                // decompression layer depth check
1196
1.31k
                                if layers > limit {
1197
172
                                    htp_warn!(
1198
172
                                        self.logger,
1199
172
                                        HtpLogCode::TOO_MANY_ENCODING_LAYERS,
1200
172
                                        "Too many response content encoding layers"
1201
172
                                    );
1202
172
                                    break;
1203
1.14k
                                }
1204
0
                            }
1205
1206
1.14k
                            let encoding = Bstr::from(encoding);
1207
1.14k
                            let encoding = if encoding.index_of_nocase(b"gzip").is_some() {
1208
156
                                if !(encoding.cmp_slice(b"gzip") == Ordering::Equal
1209
9
                                    || encoding.cmp_slice(b"x-gzip") == Ordering::Equal)
1210
9
                                {
1211
9
                                    htp_warn!(
1212
9
                                        self.logger,
1213
9
                                        HtpLogCode::ABNORMAL_CE_HEADER,
1214
9
                                        "C-E gzip has abnormal value"
1215
9
                                    );
1216
147
                                }
1217
156
                                HtpContentEncoding::Gzip
1218
987
                            } else if encoding.index_of_nocase(b"deflate").is_some() {
1219
0
                                if !(encoding.cmp_slice(b"deflate") == Ordering::Equal
1220
0
                                    || encoding.cmp_slice(b"x-deflate") == Ordering::Equal)
1221
0
                                {
1222
0
                                    htp_warn!(
1223
0
                                        self.logger,
1224
0
                                        HtpLogCode::ABNORMAL_CE_HEADER,
1225
0
                                        "C-E deflate has abnormal value"
1226
0
                                    );
1227
0
                                }
1228
0
                                HtpContentEncoding::Deflate
1229
987
                            } else if encoding.cmp_slice(b"lzma") == Ordering::Equal {
1230
47
                                lzma_layers += 1;
1231
47
                                if let Some(limit) = compression_options.get_lzma_layers() {
1232
                                    // Lzma layer depth check
1233
0
                                    if lzma_layers > limit {
1234
0
                                        htp_warn!(
1235
0
                                            self.logger,
1236
0
                                            HtpLogCode::RESPONSE_TOO_MANY_LZMA_LAYERS,
1237
0
                                            "Too many response content encoding lzma layers"
1238
0
                                        );
1239
0
                                        break;
1240
0
                                    }
1241
47
                                }
1242
47
                                HtpContentEncoding::Lzma
1243
940
                            } else if encoding.cmp_slice(b"inflate") == Ordering::Equal
1244
937
                                || encoding.cmp_slice(b"none") == Ordering::Equal
1245
936
                                || encoding.cmp_slice(b"identity") == Ordering::Equal
1246
                            {
1247
5
                                HtpContentEncoding::None
1248
                            } else {
1249
935
                                htp_warn!(
1250
935
                                    self.logger,
1251
935
                                    HtpLogCode::ABNORMAL_CE_HEADER,
1252
935
                                    "C-E unknown setting"
1253
935
                                );
1254
935
                                HtpContentEncoding::None
1255
                            };
1256
1257
1.14k
                            self.response_prepend_decompressor(encoding)?;
1258
                        }
1259
0
                    }
1260
45.3k
                }
1261
            }
1262
        }
1263
48.7k
        Ok(())
1264
48.7k
    }
1265
1266
32.1k
    fn response_decompressor_callback(&mut self, data: Option<&[u8]>) -> std::io::Result<usize> {
1267
        // If no data is passed, call the hooks with NULL to signify the end of the
1268
        // response body.
1269
32.1k
        let parser_data = ParserData::from(data);
1270
32.1k
        let compression_options = self.cfg.compression_options;
1271
32.1k
        let resp = self.response_mut().unwrap();
1272
32.1k
        let mut tx_data = Data::new(resp, &parser_data);
1273
1274
        // Keep track of actual response body length.
1275
32.1k
        resp.response_entity_len = resp.response_entity_len.wrapping_add(tx_data.len() as u64);
1276
1277
        // Invoke all callbacks.
1278
32.1k
        self.response_run_hook_body_data(&mut tx_data)
1279
32.1k
            .map_err(|_| std::io::Error::new(std::io::ErrorKind::Other, "body data hook failed"))?;
1280
32.1k
        let resp = self.response_mut().unwrap();
1281
32.1k
        if let Some(decompressor) = &mut resp.response_decompressor {
1282
0
            if decompressor.callback_inc() % compression_options.get_time_test_freq() == 0 {
1283
0
                if let Some(time_spent) = decompressor.timer_reset() {
1284
0
                    if time_spent > compression_options.get_time_limit() as u64 {
1285
0
                        decompressor.set_passthrough(true);
1286
0
                        htp_error!(
1287
0
                            self.logger,
1288
0
                            HtpLogCode::COMPRESSION_BOMB,
1289
0
                            format!("Compression bomb: spent {} us decompressing", time_spent)
1290
0
                        );
1291
0
                    }
1292
0
                }
1293
0
            }
1294
32.1k
        }
1295
1296
        // output > ratio * input ?
1297
32.1k
        let ratio = compression_options.get_bomb_ratio();
1298
32.1k
        let resp = self.response_mut().unwrap();
1299
32.1k
        let exceeds_ratio = if let Some(ratio) = resp.response_message_len.checked_mul(ratio) {
1300
32.1k
            resp.response_entity_len > ratio
1301
        } else {
1302
            // overflow occured
1303
0
            true
1304
        };
1305
1306
32.1k
        let bomb_limit = compression_options.get_bomb_limit();
1307
32.1k
        let response_entity_len = resp.response_entity_len;
1308
32.1k
        let response_message_len = resp.response_message_len;
1309
32.1k
        if response_entity_len > bomb_limit && exceeds_ratio {
1310
16
            htp_error!(
1311
16
                self.logger,
1312
16
                HtpLogCode::COMPRESSION_BOMB,
1313
16
                format!(
1314
16
                    "Compression bomb: decompressed {} bytes out of {}",
1315
16
                    response_entity_len, response_message_len,
1316
16
                )
1317
16
            );
1318
16
            self.bombs += 1;
1319
16
            if self.bombs == compression_options.get_max_bombs() {
1320
0
                htp_error!(
1321
0
                    self.logger,
1322
0
                    HtpLogCode::COMPRESSION_BOMB_LIMIT_REACHED,
1323
0
                    format!("Compression bomb: happened {} times", self.bombs,)
1324
0
                );
1325
16
            }
1326
16
            return Err(std::io::Error::other("compression_bomb_limit reached"));
1327
32.1k
        }
1328
32.1k
        Ok(tx_data.len())
1329
32.1k
    }
1330
1331
    /// Prepend response decompressor
1332
3.77k
    fn response_prepend_decompressor(&mut self, encoding: HtpContentEncoding) -> Result<()> {
1333
3.77k
        let compression_options = self.cfg.compression_options;
1334
3.77k
        if self.bombs >= compression_options.get_max_bombs() {
1335
            // skip decompression for this flow if too many bombs were seen
1336
1
            self.response_mut()
1337
1
                .unwrap()
1338
1
                .response_content_encoding_processing = HtpContentEncoding::None;
1339
1
            return Ok(());
1340
3.77k
        }
1341
3.77k
        if encoding != HtpContentEncoding::None {
1342
            // ensured by caller
1343
2.83k
            let resp = self.response_mut().unwrap();
1344
2.83k
            if let Some(decompressor) = resp.response_decompressor.take() {
1345
14
                let decompressor = decompressor.prepend(encoding, compression_options)?;
1346
14
                resp.response_decompressor.replace(decompressor);
1347
            } else {
1348
                // The processing encoding will be the first one encountered
1349
2.82k
                resp.response_content_encoding_processing = encoding;
1350
1351
                // Add the callback first because it will be called last in
1352
                // the chain of writers
1353
1354
                // TODO: fix lifetime error and remove this line!
1355
2.82k
                let connp_ptr = self as *mut Self;
1356
2.82k
                let decompressor = unsafe {
1357
2.82k
                    Decompressor::new_with_callback(
1358
2.82k
                        encoding,
1359
32.1k
                        Box::new(move |data: Option<&[u8]>| -> std::io::Result<usize> {
1360
32.1k
                            (*connp_ptr).response_decompressor_callback(data)
1361
32.1k
                        }),
1362
2.82k
                        compression_options,
1363
0
                    )?
1364
                };
1365
2.82k
                self.response_mut()
1366
2.82k
                    .unwrap()
1367
2.82k
                    .response_decompressor
1368
2.82k
                    .replace(decompressor);
1369
            }
1370
940
        }
1371
3.77k
        Ok(())
1372
3.77k
    }
1373
1374
    /// Finalizes response parsing.
1375
905k
    pub(crate) fn response_finalize(&mut self, input: &mut ParserData) -> Result<()> {
1376
905k
        if input.is_gap() {
1377
30
            return self.state_response_complete(input);
1378
905k
        }
1379
905k
        let mut work = input.as_slice();
1380
905k
        if self.response_status != HtpStreamState::CLOSED {
1381
903k
            let response_next_byte = input.as_slice().first();
1382
903k
            if response_next_byte.is_none() {
1383
62.2k
                return self.state_response_complete(input);
1384
840k
            }
1385
840k
            let lf = response_next_byte
1386
840k
                .map(|byte| *byte == b'\n')
1387
840k
                .unwrap_or(false);
1388
840k
            if !lf {
1389
827k
                if let Ok((_, line)) = take_till_lf(work) {
1390
815k
                    self.response_data_consume(input, line.len());
1391
815k
                    work = line;
1392
815k
                } else {
1393
11.5k
                    return self.handle_response_absent_lf(input);
1394
                }
1395
13.5k
            } else {
1396
13.5k
                self.response_data_consume(input, work.len());
1397
13.5k
            }
1398
2.38k
        }
1399
831k
        if !self.response_buf.is_empty() {
1400
7.72k
            self.check_response_buffer_limit(work.len())?;
1401
823k
        }
1402
831k
        let mut data = take(&mut self.response_buf);
1403
831k
        let buf_len = data.len();
1404
831k
        data.add(work);
1405
1406
831k
        if data.is_empty() {
1407
            //closing
1408
2.30k
            return self.state_response_complete(input);
1409
829k
        }
1410
829k
        if treat_response_line_as_body(&data) {
1411
            // Interpret remaining bytes as body data
1412
804k
            htp_warn!(
1413
804k
                self.logger,
1414
804k
                HtpLogCode::RESPONSE_BODY_UNEXPECTED,
1415
804k
                "Unexpected response body"
1416
804k
            );
1417
804k
            return self.response_body_data(Some(data.as_slice()));
1418
24.6k
        }
1419
        // didnt use data, restore
1420
24.6k
        self.response_buf.add(&data[0..buf_len]);
1421
        //unread last end of line so that RES_LINE works
1422
24.6k
        self.response_data_unconsume(input, data.len());
1423
24.6k
        self.state_response_complete(input)
1424
905k
    }
1425
1426
    /// The response idle state will initialize response processing, as well as
1427
    /// finalize each transactions after we are done with it.
1428
    ///
1429
    /// Returns HtpStatus::OK on state change, HtpStatus::ERROR on error, or HtpStatus::DATA
1430
    /// when more data is needed.
1431
157k
    pub(crate) fn response_idle(&mut self, input: &ParserData) -> Result<()> {
1432
        // We want to start parsing the next response (and change
1433
        // the state from IDLE) only if there's at least one
1434
        // byte of data available. Otherwise we could be creating
1435
        // new structures even if there's no more data on the
1436
        // connection.
1437
157k
        if input.is_empty() {
1438
64.7k
            return Err(HtpStatus::DATA);
1439
93.1k
        }
1440
1441
        // Parsing a new response
1442
        // Log if we have not seen the corresponding request yet
1443
93.1k
        let resp = self.response();
1444
93.1k
        if resp.is_none() {
1445
4
            return Err(HtpStatus::ERROR);
1446
93.1k
        }
1447
93.1k
        if resp.unwrap().request_progress == HtpRequestProgress::NOT_STARTED {
1448
46.6k
            htp_error!(
1449
46.6k
                self.logger,
1450
46.6k
                HtpLogCode::UNABLE_TO_MATCH_RESPONSE_TO_REQUEST,
1451
46.6k
                "Unable to match response to request"
1452
46.6k
            );
1453
46.6k
            if self.request_state == State::Finalize {
1454
5.26k
                let _ = self.state_request_complete(&mut ParserData::from(None));
1455
41.3k
            }
1456
46.6k
            let tx = self.response_mut();
1457
46.6k
            if tx.is_none() {
1458
0
                return Err(HtpStatus::ERROR);
1459
46.6k
            }
1460
46.6k
            let tx = tx.unwrap();
1461
1462
46.6k
            let uri = Uri {
1463
46.6k
                path: Some(Bstr::from("/libhtp::request_uri_not_seen")),
1464
46.6k
                ..Default::default()
1465
46.6k
            };
1466
46.6k
            tx.request_uri = uri.path.clone();
1467
46.6k
            tx.parsed_uri = Some(uri);
1468
46.6k
            tx.request_progress = HtpRequestProgress::COMPLETE;
1469
46.6k
            self.request_next();
1470
46.5k
        }
1471
93.1k
        self.response_content_length = None;
1472
93.1k
        self.response_body_data_left = None;
1473
93.1k
        self.state_response_start()
1474
157k
    }
1475
1476
    /// Run the RESPONSE_BODY_DATA hook.
1477
1.50M
    fn response_run_hook_body_data(&mut self, d: &mut Data) -> Result<()> {
1478
        // Do not invoke callbacks with an empty data chunk.
1479
1.50M
        if d.is_empty() {
1480
56.8k
            return Ok(());
1481
1.44M
        }
1482
1.44M
        let resp = self.response().unwrap();
1483
        // Run transaction hooks first
1484
1.44M
        resp.hook_response_body_data.clone().run_all(self, d)?;
1485
        // Run configuration hooks second
1486
1.44M
        self.cfg.hook_response_body_data.run_all(self, d)?;
1487
1.44M
        Ok(())
1488
1.50M
    }
1489
1490
    /// Process a chunk of outbound (server or response) data.
1491
560k
    pub(crate) fn response_data(
1492
560k
        &mut self, mut chunk: ParserData, timestamp: Option<OffsetDateTime>,
1493
560k
    ) -> HtpStreamState {
1494
        // Reset consumed data tracker
1495
560k
        self.response_bytes_consumed = 0;
1496
1497
        // Return if the connection is in stop state
1498
560k
        if self.response_status == HtpStreamState::STOP {
1499
0
            htp_info!(
1500
0
                self.logger,
1501
0
                HtpLogCode::PARSER_STATE_ERROR,
1502
0
                "Outbound parser is in HTP_STREAM_STATE_STOP"
1503
0
            );
1504
0
            return HtpStreamState::STOP;
1505
560k
        }
1506
        // Return if the connection has had a fatal error
1507
560k
        if self.response_status == HtpStreamState::ERROR {
1508
8
            htp_error!(
1509
8
                self.logger,
1510
8
                HtpLogCode::PARSER_STATE_ERROR,
1511
8
                "Outbound parser is in HTP_STREAM_STATE_ERROR"
1512
8
            );
1513
8
            return HtpStreamState::ERROR;
1514
560k
        }
1515
1516
        // If the length of the supplied data chunk is zero, proceed
1517
        // only if the stream has been closed. We do not allow zero-sized
1518
        // chunks in the API, but we use it internally to force the parsers
1519
        // to finalize parsing.
1520
560k
        if chunk.is_empty() && self.response_status != HtpStreamState::CLOSED {
1521
0
            htp_error!(
1522
0
                self.logger,
1523
0
                HtpLogCode::ZERO_LENGTH_DATA_CHUNKS,
1524
0
                "Zero-length data chunks are not allowed"
1525
0
            );
1526
0
            return HtpStreamState::CLOSED;
1527
560k
        }
1528
        // Remember the timestamp of the current response data chunk
1529
560k
        if let Some(timestamp) = timestamp {
1530
560k
            self.response_timestamp = timestamp;
1531
560k
        }
1532
1533
        // Store the current chunk information
1534
560k
        self.conn.track_outbound_data(chunk.len());
1535
        // Return without processing any data if the stream is in tunneling
1536
        // mode (which it would be after an initial CONNECT transaction.
1537
560k
        if self.response_status == HtpStreamState::TUNNEL {
1538
3.08k
            return HtpStreamState::TUNNEL;
1539
557k
        }
1540
557k
        if chunk.is_gap() {
1541
            // Mark the transaction as having a gap
1542
424
            let idx = self.request_index();
1543
424
            let resp = self.response_mut();
1544
424
            if resp.is_none() {
1545
0
                return HtpStreamState::ERROR;
1546
424
            }
1547
424
            let resp = resp.unwrap();
1548
1549
424
            resp.flags.set(HtpFlags::RESPONSE_MISSING_BYTES);
1550
1551
424
            if idx == 0 && resp.response_progress == HtpResponseProgress::NOT_STARTED {
1552
                // We have a leading gap on the first transaction.
1553
10
                return HtpStreamState::CLOSED;
1554
414
            }
1555
556k
        }
1556
1557
        loop
1558
        // Invoke a processor, in a loop, until an error
1559
        // occurs or until we run out of data. Many processors
1560
        // will process a request, each pointing to the next
1561
        // processor that needs to run.
1562
        // Return if there's been an error
1563
        // or if we've run out of data. We are relying
1564
        // on processors to add error messages, so we'll
1565
        // keep quiet here.
1566
        {
1567
2.58M
            if chunk.is_gap()
1568
473
                && self.response_state != State::BodyIdentityCLKnown
1569
310
                && self.response_state != State::BodyIdentityStreamClose
1570
293
                && self.response_state != State::Finalize
1571
            {
1572
263
                htp_error!(
1573
263
                    self.logger,
1574
263
                    HtpLogCode::INVALID_GAP,
1575
263
                    "Gaps are not allowed during this state"
1576
263
                );
1577
263
                return HtpStreamState::CLOSED;
1578
2.58M
            }
1579
2.58M
            let mut rc = self.handle_response_state(&mut chunk);
1580
1581
2.58M
            if rc.is_ok() {
1582
2.02M
                if self.response_status == HtpStreamState::TUNNEL {
1583
31
                    return HtpStreamState::TUNNEL;
1584
2.02M
                }
1585
2.02M
                rc = self.response_handle_state_change(&mut chunk);
1586
556k
            }
1587
556k
            match rc {
1588
                // Continue looping.
1589
2.02M
                Ok(_) => {}
1590
                // Do we need more data?
1591
                Err(HtpStatus::DATA) | Err(HtpStatus::DATA_BUFFER) => {
1592
                    // Ignore result.
1593
555k
                    let _ = self.response_receiver_send_data(&mut chunk);
1594
555k
                    self.response_status = HtpStreamState::DATA;
1595
555k
                    return HtpStreamState::DATA;
1596
                }
1597
                // Check for stop
1598
                Err(HtpStatus::STOP) => {
1599
0
                    self.response_status = HtpStreamState::STOP;
1600
0
                    return HtpStreamState::STOP;
1601
                }
1602
                // Check for suspended parsing
1603
                Err(HtpStatus::DATA_OTHER) => {
1604
                    // We might have actually consumed the entire data chunk?
1605
965
                    if chunk.is_empty() {
1606
825
                        self.response_status = HtpStreamState::DATA;
1607
                        // Do not send STREAM_DATE_DATA_OTHER if we've
1608
                        // consumed the entire chunk
1609
825
                        return HtpStreamState::DATA;
1610
                    } else {
1611
140
                        self.response_status = HtpStreamState::DATA_OTHER;
1612
                        // Partial chunk consumption
1613
140
                        return HtpStreamState::DATA_OTHER;
1614
                    }
1615
                }
1616
                // Permanent stream error.
1617
                Err(_) => {
1618
73
                    self.response_status = HtpStreamState::ERROR;
1619
73
                    return HtpStreamState::ERROR;
1620
                }
1621
            }
1622
        }
1623
560k
    }
1624
1625
    /// Advance out buffer cursor and buffer data.
1626
162k
    fn handle_response_absent_lf(&mut self, data: &ParserData) -> Result<()> {
1627
162k
        self.check_response_buffer_limit(data.len())?;
1628
162k
        self.response_buf.add(data.as_slice());
1629
162k
        self.response_data_consume(data, data.len());
1630
162k
        Err(HtpStatus::DATA_BUFFER)
1631
162k
    }
1632
}