Commit Graph

1408 Commits (suricata-7.0.9)

Author SHA1 Message Date
Jason Ish 5ce35f581a rust/conf: collapse match pattern into if
Fixes clippy lint for collapsible_match.

error: this `match` can be collapsed into the outer `if let`
  --> src/conf.rs:85:9
   |
85 | /         match val {
86 | |             "1" | "yes" | "true" | "on" => {
87 | |                 return true;
88 | |             },
89 | |             _ => {},
90 | |         }
   | |_________^
   |
help: the outer pattern can be modified to include the inner pattern
  --> src/conf.rs:84:17
   |
84 |     if let Some(val) = conf_get(key) {
   |                 ^^^ replace this binding
85 |         match val {
86 |             "1" | "yes" | "true" | "on" => {
   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ with this pattern
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_match
12 months ago
Jason Ish 2c92b12e19 rust/http2: remove redundant pattern match
Fix clippy lint for if_let_redundant_pattern_matching by using
.is_some().
12 months ago
Jason Ish 8e93ae0a22 rust/dcerpc: clippy fix for match
error: this `match` can be collapsed into the outer `match`
   --> src/dcerpc/detect.rs:215:20
    |
215 |           Some(x) => match x {
    |  ____________________^
216 | |             DCERPC_TYPE_REQUEST | DCERPC_TYPE_RESPONSE => {}
217 | |             _ => {
218 | |                 return 0;
219 | |             }
220 | |         },
    | |_________^
    |
help: the outer pattern can be modified to include the inner pattern
   --> src/dcerpc/detect.rs:215:14
    |
215 |         Some(x) => match x {
    |              ^ replace this binding
216 |             DCERPC_TYPE_REQUEST | DCERPC_TYPE_RESPONSE => {}
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ with this pattern
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_match
12 months ago
Jason Ish fcc1da0144 rust/ssh: fix clippy warning, reference can be used
Fix done by clippy --fix.
12 months ago
Jason Ish f3f7bcc091 rust: fix clippy warnings for match as if statements
Fix done by clippy --fix.
12 months ago
Juliana Fajardini f74fa898cf dns: allow triggering raw stream reassembly
For TCP streams, app proto stream reassembly can start earlier, instead
of waiting and queueing up data before doing so.

Task #7018
Related to
Bug #7004

(cherry picked from commit bb45ac71ef)
1 year ago
Victor Julien ff8d9ca1a1 smb/ntlmssp: improve version check
Don't assume the ntlmssp version field is always present if the flag is
set. Instead keep track of the offsets of the data of the various blobs
and see if there is space for the version.

Inspired by how Wireshark does the parsing.

Bug: #7121.
(cherry picked from commit f59c43b1c7)
1 year ago
Victor Julien d2ee5a1e9e detect/iprep: implement isset and isnotset
Implement special "isset" and "isnotset" modes.

"isset" matches if an IP address is part of an iprep category with any
value.

It is internally implemented as ">=,0", which should always be true if
there is a value to evaluate, as valid reputation values are 0-127.

"isnotset" matches if an IP address is not part of an iprep category.

Internally it is implemented outside the uint support.

Ticket: #6857.
(cherry picked from commit 83976a4cd4)
1 year ago
Victor Julien b4acd71b8b detect/iprep: update keyword parser for extendibility
(cherry picked from commit 539ab3a404)
1 year ago
Philippe Antoine ea215902d5 filestore: do not try to store a file set to nostore
Ticket: 6390

This can happen with keyword filestore:both,flow
If one direction does not have a signature group with a filestore,
the file is set to nostore on opening, until a signature in
the other direction tries to set it to store.
Subsequent files will be stored in both directions as flow flags
are now set.

(cherry picked from commit 5f35035928)
1 year ago
Philippe Antoine c82fa5ca0d http2: do not expand duplicate headers
Ticket: 7104

As this can cause a big mamory allocation due to the quadratic
nature of the HPACK compression.

(cherry picked from commit 5bd17934df)
1 year ago
Philippe Antoine a753cdbe84 modbus: abort flow parsing on flood
Ticket: 6987

Let's not spend more resources for a flow which is trying to
make us do it...

(cherry picked from commit 37509e8e0e)
1 year ago
Jason Ish 82b502ec25 rust/ike: prefix never read field names with _
New warning from rustc.

The other option is to allow dead code, however this is more explicit,
and when they are read, its obvious they should be renamed.
1 year ago
Jason Ish 192ef5bb90 rust: fix clippy lint for legacy_numeric_constants
https://rust-lang.github.io/rust-clippy/master/index.html#legacy_numeric_constants
1 year ago
Jason Ish 97409fe37b rust: rename .cargo/config to .cargo/config.toml
Addresses this warning from the Rust compiler:

warning: `../rust/.cargo/config` is deprecated in favor of `config.toml`
note: if you need to support cargo 1.38 or earlier, you can symlink `config` to `config.toml`
(cherry picked from commit 8560564657)
1 year ago
Jason Ish 9c9181ee19 cargo: use default-features instead of default_features
"default_features" is being deprecated in Rust 2024.
1 year ago
Jason Ish d88eb343af rust: simply matches with unwrap_or_default
New default clippy warning:
https://rust-lang.github.io/rust-clippy/master/index.html#manual_unwrap_or_default
1 year ago
Jeff Lucovsky 1f5e10a49c output/ja4: Restrict ja4 hashes to alerts
This commit restricts ja4 hash output to alerts; ja4 hashes will not be
in tls or quic events.

Issue: 7010
1 year ago
Sascha Steinbiss 93fd349b3f ja4: implement for TLS and QUIC
Ticket: OISF#6379
(cherry picked from commit 120313f4da)
1 year ago
Sascha Steinbiss f48b48da65 ja3: make feature compile time configurable
(cherry picked from commit 9d0db71ebf)
1 year ago
Philippe Antoine b556619213 rust/probing: safety check for null input
Ticket: 7013

Done consistently for all protocols

This may change some protocols behaviors which failed early
if they found there was not enough data...

(cherry picked from commit 37a9003736)
1 year ago
Philippe Antoine e797836b6e rust: return empty slice without using from_raw_parts
As this triggers rustc 1.78
unsafe precondition(s) violated: slice::from_raw_parts requires
the pointer to be aligned and non-null,
and the total size of the slice not to exceed `isize::MAX`

Ticket: 7013
(cherry picked from commit 5dc8dea869)
1 year ago
Philippe Antoine c0af92295e http2: do not log duplicate headers
Ticket: 6900

And thus avoid DOS by logging a request using a compressed
header block repeated many times and having a long value...

(cherry picked from commit 03442c9071)
1 year ago
Philippe Antoine e68ec4b227 http2: use a reference counter for headers
Ticket: 6892

As HTTP hpack header compression allows one single byte to
express a previously seen arbitrary-size header block (name+value)
we should avoid to copy the vectors data, but just point
to the same data, while reamining memory safe, even in the case
of later headers eviction from the dybnamic table.

Rust std solution is Rc, and the use of clone, so long as the
data is accessed by only one thread.

(cherry picked from commit 390f09692e)
1 year ago
Jason Ish b83d808994 jsonbuilder: fix serialization of nan and inf
When outputting a float, check if its infinity, or not a number and
output a null instead.

Using a null was chosen as this is what serde_yaml, Firefox, Chrome,
Node, etc. do.

Ticket: #6921
(cherry picked from commit 71f59e529c)
1 year ago
Philippe Antoine 80d2c6e0a1 rust/mqtt: fix clippy 1.77 warning
error: creating a mutable reference to mutable static is discouraged
   --> src/mqtt/mqtt.rs:752:23
    |
752 |     let max_msg_len = &mut MAX_MSG_LEN;
    |                       ^^^^^^^^^^^^^^^^ mutable reference to mutable static
    |
    = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
    = note: this will be a hard error in the 2024 edition
    = note: this mutable reference has lifetime `'static`, but if the static gets accessed (read or written) by any other means, or any other reference is created, then any further use of this mutable reference is Undefined Behavior
1 year ago
Philippe Antoine fce01dad77 rust/smb: fix clippy nightly warning
error: unnecessary use of `to_vec`
    --> src/smb/smb.rs:1048:62
     |
1048 |         let (name, is_dcerpc) = match self.guid2name_map.get(&guid.to_vec()) {
     |                                                              ^^^^^^^^^^^^^^ help: replace it with: `guid`
     |
     = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_to_owned
     = note: `#[deny(clippy::unnecessary_to_owned)]` implied by `#[deny(warnings)]`

And also other uses of to_vec() on already Vec

(cherry picked from commit f7cde8f00e)
1 year ago
Philippe Antoine 5a05e025ed rust: fix clippy 1.77 warning
Ticket: 6883

error: field `0` is never read
  --> src/asn1/mod.rs:36:14
   |
36 |     BerError(Err<der_parser::error::BerError>),
   |     -------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |     |
   |     field in this variant
   |

(cherry picked from commit 02f2fb8833)
1 year ago
Victor Julien 58c61f1fe4 rust: add MSRV as rust-version
Update github-actions to use it for the MSRV check.
1 year ago
Philippe Antoine c0b9ddb32e ssh: limit length for banner logs
Ticket: 6770
(cherry picked from commit c4b8fb7aca)
1 year ago
Philippe Antoine f9ef96af30 ssh: avoid quadratic complexity from long banner
Ticket: 6799

When we find an overlong banner, we get into the state just
waiting for end of line, and we just want to skip the bytes
until then.
Returning AppLayerResult::incomplete made TCP engine retain
the bytes and grow the buffer that we parsed again and again...

(cherry picked from commit 271ed2008b)
1 year ago
Jeff Lucovsky e5b006beb9 mqtt: Improve frame parsing w/mult. PDUs
This commit improves the mqtt parsing of frames to handle multiple PDUs.

Issue: 6592
(cherry picked from commit f9a20dafc6)
1 year ago
Philippe Antoine e917baafe7 app-layer/template: use a max number of txs
Ticket: 6773
(cherry picked from commit c99d93c257)
1 year ago
Philippe Antoine 8df02ba0e4 rust: fix clippy ptr_arg warnings
error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do
   --> src/dns/log.rs:371:29
    |
371 | pub fn dns_print_addr(addr: &Vec<u8>) -> std::string::String {
    |                             ^^^^^^^^ help: change this to: `&[u8]`
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#ptr_arg

(cherry picked from commit 68b0052018)
1 year ago
Philippe Antoine ce9b903269 http2: limit number of concurrent transactions
Ticket: 6481

Instead of just setting the old transactions to a drop state so
that they get later cleaned up by Suricata, fail creating new ones.

This is because one call to app-layer parsing can create many
transactions, and quadratic complexity could happen in one
single app-layer parsing because of find_or_create_tx

(cherry picked from commit 80abc22f64)
2 years ago
Philippe Antoine b0d762d267 pgsql: parse only PDU when type is unknown
A next PDU may already be in the slice to parse.
Do not skip its parsing, ie do not use rest, but take just
the length of the pdu

(cherry picked from commit 86de7cffa7)
2 years ago
Philippe Antoine 61a32360eb pgsql: parse auth message within its bound
If the next PDU is already in the slice next, do not use it and
restrict ourselves to the length of this PDU.
Avoids overconsumption of memory by quadratic complexity, when
having many small PDUS in one big chunk being parsed

Ticket: #6411
(cherry picked from commit f52c033e56)
2 years ago
Philippe Antoine 478a2a38f5 http2: handle reassembly for continuation frames
Ticket: 5926

HTTP2 continuation frames are defined in RFC 9113.
They allow header blocks to be split over multiple HTTP2 frames.
For Suricata to process correctly these header blocks, it
must do the reassembly of the payload of these HTTP2 frames.
Otherwise, we get incomplete decoding for headers names and/or
values while decoding a single frame.

Design is to add a field to the HTTP2 state, as the RFC states that
these continuation frames form a discrete unit :
> Field blocks MUST be transmitted as a contiguous sequence of frames,
> with no interleaved frames of any other type or from any other stream.
So, we do not have to duplicate this reassembly field per stream id.

Another design choice is to wait for the reassembly to be complete
before doing any decoding, to avoid quadratic complexity on partially
decoding of the data.

(cherry picked from commit aff54f29f8)
2 years ago
Philippe Antoine 3cdd50071b mqtt: fix logic when setting event
Especially sets transactions to complete when we get a response
without having seen the request, so that the transactions
end up getting cleaned (instead of living/leaking in the state).

Also try to set the event on the relevant transaction, instead
of creating a new transaction just for the purpose of having
the event.

Ticket: #6299
(cherry picked from commit 89936b6530)
2 years ago
Jason Ish 09fc36713f requires: add requires keyword
Add a new rule keyword "requires" that allows a rule to require specific
Suricata versions and/or Suricata features to be enabled.

Example:

  requires: feature geoip, version >= 7.0.0, version < 8;
  requires: version >= 7.0.3 < 8
  requires: version >= 7.0.3 < 8 | >= 8.0.3

Feature: #5972

Co-authored-by: Philippe Antoine <pantoine@oisf.net>
(cherry picked from commit 5d5b0509a5)
2 years ago
Jason Ish ea78420d02 feature: provide a Rust binding to the feature API
As the feature module is not available for Rust unit tests, a mock
version is also provided.

(cherry picked from commit 15ed51f9b8)
2 years ago
Juliana Fajardini 2e6322bc36 pgsql: fix u16 overflow in query data_row
Found by oss-fuzz with quadfuzz.

Cf https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=63113

According to PostgreSQL documentation the maximum number of rows can be
the maximum of tuples that can fit onto max u32 pages - 4,294,967,295 (cf
https://www.postgresql.org/docs/current/limits.html). Some rough
calculations for that indicate that this could go over max u32, so
updating the data_row data type to u64.

Bug #6389

(cherry picked from commit 8d3de85edd)
2 years ago
Victor Julien eb5a430154 jsonbuilder: add set_int for signed ints
Bug: #6615
(cherry picked from commit b8440a0917)
2 years ago
Philippe Antoine eff4af46fa rust: allow clippy::items_after_test_module
As clippy began to complain about jsonbuilder.rs

(cherry picked from commit 673d13d445)
2 years ago
Juliana Fajardini 046a18b81a pgsql: remove unused msg field
The `ConsolidatedDataRow` struct had a `length` field that wasn't truly
used.

Related to
Bug #6389

(cherry picked from commit 1afb485dfa)
2 years ago
Juliana Fajardini dda79c689c pgsql: add cancel request message
A CanceldRequest can occur after any query request, and is sent over a
new connection, leading to a new flow. It won't take any reply, but, if
processed by the backend, will lead to an ErrorResponse.

Task #6577

(cherry picked from commit 30ac77ce65)
2 years ago
Juliana Fajardini 6ee4567952 pgsql: extract length validation into function
This is called so many times that it seems to make sense that we use a
function for this.

(cherry picked from commit 7fa8bbfe43)
2 years ago
Philippe Antoine 6b889c4c92 http2: do not have leading space for response line
Ticket: 6547
(cherry picked from commit 1b5e04bee3)
2 years ago
Juliana Fajardini 2e967202d2 pgsql: don't log password msg if password disabled
If the logging of the password is disabled, there isn't much point in
logging the password message itself.

(cherry picked from commit bdec2d8ea8)
2 years ago
Juliana Fajardini bc8231d6ef pgsql: remove probe_ts function
With the changes in the probing_ts function, this other one could become
obsolete. Remove it, and directly call `parser::parse_request` when
checking for gaps, instead.

(cherry picked from commit 9aeeac532e)
2 years ago
Juliana Fajardini d4e7299f68 pgsql: remove unused error handling call
(cherry picked from commit 53d29f652a)
2 years ago
Juliana Fajardini e7c96c3937 pgsql: don't log unknown message type
(cherry picked from commit afd6e4dc41)
2 years ago
Juliana Fajardini c35057a9ed pgsql: fix probing functions
Some non-pgsql traffic seen by Suricata is mistankenly identified as
pgsql, as the probing function is too generic. Now, if the parser sees
an unknown message type, even if it looks like pgsql, it will fail.

Bug #6080

(cherry picked from commit 4f85d06192)
2 years ago
Juliana Fajardini 7e39a9f4a9 pgsql: add unknonwn frontend message type
We had unkonwn message type for the backend, but not the frontend
messages. It's important to better identify those to improve pgsql
probing functions.

Related to
Bug #6080

(cherry picked from commit 1ac5d97259)
2 years ago
Philippe Antoine b6e889bd95 http2: app-layer event for userinfo in uri
Ticket: #6426

as per RFC 9113
":authority" MUST NOT include the deprecated userinfo subcomponent
for "http" or "https" schemed URIs.

(cherry picked from commit e3cd0d073f)
2 years ago
Philippe Antoine 6249722589 http2: normalize host when there is user info
Ticket: 6479
2 years ago
Philippe Antoine b6cd66f41d http2: update brotli crate
Fixes debug assertion found by oss-fuzz:
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=63144
2 years ago
Philippe Antoine 46a46e5b1f http2: event on mismatch between authority and host
Ticket: #6425
2 years ago
Philippe Antoine ae72ce77fa detect: parse units for integers
Ticket: #6423

Especially for filesize, instead of just a number, a signature
can use a number and a unit such as kb, mb or Gb
2 years ago
Daniel Olatunji 54de0450f4 rust: remove cbindgen:ignore on frames module
This directive is no longer required, and does
mess up the rustdoc description of the module.
2 years ago
Daniel Olatunji 5c0af0b203 rust/doc: add docstring to rust module files.
Issue: #4584
2 years ago
Philippe Antoine 14a4c6c696 rust: update brotli decompressor crate
cf https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=59687
2 years ago
Philippe Antoine 9157070907 quic: v2 support per rfc 9369
Ticket: #4968
2 years ago
Yatin Kanetkar b67ff4badf dhcp: Log Vendor Client Identifier (dhcp option 60)
* Log vendor client identifier (dhcp option 60) if extended dhcp
logging is turned on. This required the `vendor_client_identifier` to
be added to the json schema. Validation done using an SV Test
* Added `requested_ip` to the json schema as well, since it was
missed. My SV test failed without it.

Feature #4587
2 years ago
Philippe Antoine 5bdbc1a313 rdp: do not use zero-bit bitflag
cf https://docs.rs/bitflags/latest/bitflags/#zero-bit-flags

As warned by clippy 1.72.0
2 years ago
Philippe Antoine b235e85c68 rust: fix clippy warnings for version 1.72.0
Includes using the right prototype for C SRepCatGetByShortname
2 years ago
Victor Julien 89f1837625 rust: update cargo.lock 2 years ago
Shivani Bhardwaj 8770431986 dcerpc: accept ALTER_CONTEXT as a valid request
So far, if only the starting request was a DCERPC request, it would be
considered DCERPC traffic. Since ALTER_CONTEXT is a valid request type,
it should be accepted too.

Reported and patch proposed in the following Redmine ticket by
InterNALXz.

Bug 6191
2 years ago
Victor Julien 389f166d78 file: remove FILE_USE_DETECT flag
All implementations were converted to use the logic, so the flag itself
can be removed.
2 years ago
Shivani Bhardwaj d4e674b390 rust: fix clippy warnings 2 years ago
Victor Julien 0068b81269 rust: update cargo.lock 2 years ago
Philippe Antoine 60db5e981c http2: do not append data after closing file
Ticket: #6211

Completes commit 02dece5db5

Once a http2 stream has end of stream flag, we close the file.
If we see new data frames with this stream id, the new_chunk
function should ignore them as the file was already closed.
2 years ago
Jeff Lucovsky 690b65ae88 detect/byte_math: Permit var name for bytes value
Issue: 6145

Modifications to permit a variable name to be used for the byte_math
bytes value.
2 years ago
Philippe Antoine 02dece5db5 http2: file tracker is initialized when file is closed
Ticket: #6130

This avoids quadratic complexity by having http2_range_key_get
looking in a growing number of frames
2 years ago
Sascha Steinbiss 1521b77edd rfb: also set unimplemented auth types 2 years ago
Sascha Steinbiss 1606aca881 rfb: ensure logging of incompletely parsed txs 2 years ago
Sascha Steinbiss 1f8a5874fb rfb: never return error on unknown traffic
We only try to parse a small subset of what is possible in
RFB. Currently we only understand some standard auth schemes
and stop parsing when the server-client handshake is complete.
Since in IPS mode returning an error from the parser causes
drops that are likely uncalled for, we do not want to return
errors when we simply do not understand what happens in the
traffic. This addresses Redmine #5912.

Bug: #5912.
2 years ago
Sascha Steinbiss 836fff3679 rfb: add myself as contributor 2 years ago
Sascha Steinbiss bd1fbf392e rfb: be more strict parsing the version 2 years ago
Philippe Antoine d40dca5e55 dcerpc: maximum number of live transactions also for UDP
Ticket: #6129

Avoids that quadratic complexity gets too bad
2 years ago
Jason Ish 68d0d6ca24 rust: fix unit test link error on Rust 1.70
Rust 1.70 appears to now link code on both branches of `if cfg!(test)`
now causing Rust unit tests to fail as that pattern was used to
disable functions only available when linked with the Suricata C code.

To work-around this issue, provide two versions of the `new` function,
one for unit tests and one when running as an application.
2 years ago
Philippe Antoine 7256ec8a6e detect/http2: do not escape ':' in header name or value
for keywords http.request_header and http.response_header

Ticket: #5780
2 years ago
Philippe Antoine 4c466ec5f4 rust/pgsql: remove unused/unconstructed enum variants 2 years ago
Philippe Antoine f2a18e91c4 rust: define AppLayerEventType only in rust
And detect.h does no longer depend on app-layer-events.h
2 years ago
Philippe Antoine 668501c225 rust: remove unused 2 years ago
Philippe Antoine 7ca43e7e1f output/snmp: log version from tx
and not the one from state

If a SNMP flow starts with a V2 version transaction,
then there is a V3i version transaction,
we will now log V3 for the second transaction
2 years ago
Philippe Antoine 0ec0d8de67 output/rfb: remove unused function parameters 2 years ago
Philippe Antoine 24c2702a05 output/mqtt: remove unused function parameters 2 years ago
Philippe Antoine 09d364b32f output/krb5: remove unused function parameters 2 years ago
Lancer Cheng abc76e27de smb: fix data padding logic in writeAndX parser
Bug: #6008
2 years ago
Lancer Cheng 000eb91078 smb: fix wrong data offset when wct = 12
Bug: #6008
2 years ago
Philippe Antoine 6350736882 http2: avoid quadratic complexity in headers
When adding an element to the dynamic headers table, the oldest
ones may get evicted. When multiple elements get evicted, they
should get evicted all at once with drain, instead of one by one
as there will be a massive move each time.

Ticket: #6103
2 years ago
Philippe Antoine 7d3aa91bf4 mqtt: fix quadratic complexity
get_tx_by_pkt_id loops only over the last transactions
in case there is a transaction flood

Ticket: #6100
2 years ago
Haleema Khan 8e19906afa mqtt: rustfmt mqtt.rs 2 years ago
Haleema Khan e474858e25 mqtt: add mqtt frames
Adds PDU, Header and Data frame to the MQTT parser.
Ticket: 5731
2 years ago
Jason Ish 33827beae5 jsonbuilder: check buffer growth
Use try_reserve before growing the internal buffer, and the internal
state vector. This allows allocation errors to be caught and an error
returned instead of just aborting the process.

Ticket: #6057
2 years ago
Jason Ish 95cfc2b34f jsonbuilder: rustfmt
Some very minor changes to formatting.
2 years ago
Jason Ish 039c27789b rust: use 2021 edition
With the MSRV being bumped to 1.62 for 7.0, we can move the edition up
to 2021.
2 years ago
Jason Ish c30fff8bcb rust/doc: restore comment with code example, but ignore
Use backticks for proper markdown processing. As Rust code in
backticks is compiled, and this is a non-complete example, tag the
code sample to be ignored.
2 years ago
Philippe Antoine 5391f0a8a0 detect: http_response_line for HTTP2
Ticket: #4067

Synthetized as HTTP/2 <STAT>\r\n
2 years ago