Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Use libhtp-rs v4 #8270

Closed
wants to merge 1 commit into from
Closed

Conversation

cccs-rtmorti
Copy link
Contributor

Make sure these boxes are signed before submitting your Pull Request -- thank you.

Link to redmine ticket: 2696

Describe changes:

  • Use libhtp-rs.
  • Rebased from WIP: Libhtp rs v3 #8255
  • A single commit (for now, at least), since separating the API renames / changes from some of the other changes is tricky, and one commit makes it easier to work with for the rest of the CI.

libhtp-repo: https://github.com/cccs-rtmorti/libhtp-rs
libhtp-branch: main

@catenacyber
Copy link
Contributor

Looking better :-)
I see some red builder because of #include <htp/htp.h> not found
Should this include be removed ?

@cccs-rtmorti
Copy link
Contributor Author

Looking better :-) I see some red builder because of #include <htp/htp.h> not found Should this include be removed ?

Yeah, I am working through the build failures now and seeing what's up. I actually don't understand this one: the file htp/htp.h should be generated and dropped into rust/gen right next to rust-bindings.h, so I am not sure why it's not being found on that platform. You can see it builds fine on Fedors36 and some others without issue.

I am also seeing a suricata-verify fail on Fedora36 (Suricata verify), but this test passes for me here, so I am not sure what the problem is.

Will keep working through the red ones and pushing fixes. :)

@catenacyber
Copy link
Contributor

When they finish, you can retry failed builds.

There are some S-V tests that fail sometimes due to some different workload...

This must be an issue about includes paths, try changing to "htp/htp.h" with quotes instead of brackets (as the include is now local to the project, right ?)

@cccs-rtmorti
Copy link
Contributor Author

This must be an issue about includes paths, try changing to "htp/htp.h" with quotes instead of brackets (as the include is now local to the project, right ?)

Oh, that is almost certainly it! :)

@cccs-rtmorti cccs-rtmorti force-pushed the libhtp-rs-v4 branch 4 times, most recently from 131b56d to 1e5dd0c Compare December 15, 2022 18:49
@catenacyber
Copy link
Contributor

Only 3 more failures to go : macOS needs to link a special lib ? fuzz found a null deref ? And fix make distclean somehow...

@cccs-rtmorti
Copy link
Contributor Author

Only 3 more failures to go : macOS needs to link a special lib ? fuzz found a null deref ? And fix make distclean somehow...

One down, two to go. Currently trying to reproduce the fuzz failure.

@cccs-rtmorti
Copy link
Contributor Author

cccs-rtmorti commented Dec 19, 2022

So the failing fuzz test is from GetDetectTx() in src/detect.c:1268:

static DetectTransaction GetDetectTx(const uint8_t ipproto, const AppProto alproto,
        void *alstate, const uint64_t tx_id, void *tx_ptr, const int tx_end_state,
        const uint8_t flow_flags)
{
    uint64_t detect_flags;
    AppLayerTxData *txd = AppLayerParserGetTxData(ipproto, alproto, tx_ptr);
    if (likely(txd != NULL)) {
        detect_flags = (flow_flags & STREAM_TOSERVER) ? txd->detect_flags_ts : txd->detect_flags_tc;
    } else {
        detect_flags = 0;
    }
[...]
    const int tx_progress = AppLayerParserGetStateProgress(ipproto, alproto, tx_ptr, flow_flags);
    const int dir_int = (flow_flags & STREAM_TOSERVER) ? 0 : 1;
    DetectEngineState *tx_de_state = txd->de_state;

The segfault is on the last line here. It is dereferencing txd, but txd is NULL. txd is NULL because there was no AppLayerTxData stored in the transaction previously. Note that we explicitly check for txd being NULL after we fetch it, and set detect_flags = 0 if it is NULL. Later we unconditionally dereference it on the last line there.

The input in question is this:

<<<
HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: h2c


>>>
PRI * HTTP/2.0

SM


I am checking into how libhtp-c and libhtp-rs differ on this input and see why one works and the other doesn't, and will fix any differences. But while I am figuring that out, I wanted to ask about whether or not we should support txd being NULL here? It looks like we have a check for txd == NULL above, but then expect it to be not NULL later. Is this correct? Should we do something else if we detect txd = NULL here?

@catenacyber
Copy link
Contributor

I am checking into how libhtp-c and libhtp-rs differ on this input and see why one works and the other doesn't, and will fix any differences.

Looks like the good thing to do :-)

I wanted to ask about whether or not we should support txd being NULL here?

Ted should become a mandatory part of a transaction (whatever the protocol), but libhtp is the only thing standing in the way for now...

cf https://redmine.openinfosecfoundation.org/issues/4952#note-2

If you feel like implementing https://redmine.openinfosecfoundation.org/issues/5739#note-1 be our guest :-)

@cccs-rtmorti
Copy link
Contributor Author

cccs-rtmorti commented Dec 20, 2022

I am checking into how libhtp-c and libhtp-rs differ on this input and see why one works and the other doesn't, and will fix any differences.

Looks like the good thing to do :-)

So what is happening here is this:

  • libhtp detects the HTTP/2 tunnel and sets both ends to state TUNNEL
  • Suricata later calls htp_connp_req_close(), and this puts the request side into state CLOSED and pushes an empty data input through htp_connp_req_data() in order to finalize the parsers. This ends up in htp_connp_REQ_IDLE, which sees the empty chunk and asks for more data. In the request data processing loop this sets the stream state to HTP_STREAM_DATA, which is essentially 're-opening' the connection, after it has already been in TUNNEL and been explicitly set to CLOSED by Suricata.
  • Request data is pushed into the parser, and it is parsed normally. This is the client HTTP/2 preamble: PRI * HTTP/2.0.... After this, the parser is just proceeding normally.
  • A gap is pushed into the request parser. The parser interprets this as a gap in the leading part of the next transaction. So it sets the next transaction to state GAP on the request side. This lets the caller know that this transaction exists because we know we lost something on the wire that would have been HTTP data, but we lost it. Crucially, there is no callback to suricata's HTPCallbackRequestStart() because there is nothing to handle. This is why there is no Transaction data in suricata at the time, and why it segfaults later.

As near as I can tell, libhtp-rs and libhtp-c have the same behaviour right up to the last step. libhtp-c sees the gap and just returns HTP_STREAM_CLOSED here. I am not sure if this is the most correct behaviour, but it is why there is no segfault later.

I can fix this a number of ways, but I am not sure which one is the most correct, so I wanted to ask your opinion.

  1. If the stream is in state TUNNEL, do not later change to state CLOSED, even if the caller asks for it.
  2. If the stream is in state CLOSED, do not later allow transitions back to parsing.
  3. If there is a leading gap in a transaction, perform the HTPCallbackRequestStart callback even though there is nothing to see.
  4. If there is a leading gap in a transaction, just ignore it and say the stream is closed (this is what libhtp-c seems to do).

I think 3 is probably the "most correct" way, since it acknowledges there is something on the wire, but we just don't know what it is. It is possible that a response comes through for this later and maybe we can do something with it, and it also allows the caller to set up any framing or anything they want to do to track the data flow. I can also see 1 being reasonable, but this opens the parser up to evasion where the attacker pretends to be in a tunnel, but then just proceeds normally. 2 is also reasonable, since the caller earlier asked that the stream be closed, but then sent more data anyway, so there shouldn't be any expectation on the parser to actually do something with it. 4 is practically correct, since we can't do anything with a leading gap anyway, but also ignores the fact that there was something there, and the transaction isn't created as a placeholder to acknowledge the existence of something on the wire at that spot.

Thoughts?

@cccs-rtmorti cccs-rtmorti force-pushed the libhtp-rs-v4 branch 2 times, most recently from 7bb0e81 to 357d81d Compare December 20, 2022 17:56
@cccs-rtmorti
Copy link
Contributor Author

Okay, only one test left, and it's one of the chrono dependencies that is failing on MacOS. I think it will be simpler to just switch to time since it is already a dep in suricata, so I am working on that.

@cccs-rtmorti cccs-rtmorti force-pushed the libhtp-rs-v4 branch 4 times, most recently from d515f6c to 5fae873 Compare December 21, 2022 18:58
@cccs-rtmorti
Copy link
Contributor Author

CI is all green. :-)

Copy link
Contributor

@catenacyber catenacyber left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CI : ✅
Code : I need to pat a closer look. Do you have a script to minimize the difference without all the constants renaming ?
Still needs to revert the change about the maximum chunk size ;-) cf differential fuzzing
Commits segmentation : I guess it is ok, maybe needs some refining if possible...
Commit messages : Really nice. Still missing a reference to a ticket in redmine
Git ID set : looks fine for me
CLA : I do not have access, but looks like some commits were already merged
Doc update : I guess there needs to be some changes + an addition in doc/userguide/upgrade.rst
Redmine ticket : To be done
Rustfmt : was not enforced
Tests : green CI is good
Dependencies added: License to figure out cc @victorjulien

@catenacyber
Copy link
Contributor

Hey Todd, thanks for your work, here are some quick remarks about polishing the PR...
Could you open a new PR for the v5 ?

@catenacyber
Copy link
Contributor

BSD3 License looks good ;-)

@cccs-rtmorti
Copy link
Contributor Author

Code : Do you have a script to minimize the difference without all the constants renaming ?

I do not have such a script. I could write one - it would just be a bunch of sed commands to 'unrename' the constants. The resulting code would not compile, and you would have to look at the diff outside of github.

Still needs to revert the change about the maximum chunk size ;-) cf differential fuzzing

This is done, no?

cccs-rtmorti/libhtp-rs@2aef042

The maximum accepted chunk size is std::i32::MAX, like libhtp-c

Commits segmentation : I guess it is ok, maybe needs some refining if possible...

Yeah, I can have another look at this, but it's hard to pull things apart.

Commit messages : Really nice. Still missing a reference to a ticket in redmine

Oops. It's redmine 2696: https://redmine.openinfosecfoundation.org/issues/2696

CLA : I do not have access, but looks like some commits were already merged

I did sign the CLA. :)

Doc update : I guess there needs to be some changes + an addition in doc/userguide/upgrade.rst

I will have a look. I think in upgrade.rst it should be mentioned that libhtp is no longer built separately, so downstream packagers no longer need to include it as a dep or part of their environments. (?) Otherwise, the configuration options and such are the same - from a user point of view there should not be much difference? Anything else that would normally be mentioned?

@catenacyber
Copy link
Contributor

Code : Do you have a script to minimize the difference without all the constants renaming ?

I do not have such a script. I could write one - it would just be a bunch of sed commands to 'unrename' the constants. The resulting code would not compile, and you would have to look at the diff outside of github.

Yes, that is what I would enjoy...
If you have a csv with the constants renaming, I can work on it

Still needs to revert the change about the maximum chunk size ;-) cf differential fuzzing

This is done, no?

cccs-rtmorti/libhtp-rs@2aef042

The maximum accepted chunk size is std::i32::MAX, like libhtp-c

Indeed

Commits segmentation : I guess it is ok, maybe needs some refining if possible...

Yeah, I can have another look at this, but it's hard to pull things apart.

Do not spend too much effort on it yet ;-)

Commit messages : Really nice. Still missing a reference to a ticket in redmine

Oops. It's redmine 2696: https://redmine.openinfosecfoundation.org/issues/2696

Could you put this in the commit message like Ticket: #2696

Doc update : I guess there needs to be some changes + an addition in doc/userguide/upgrade.rst

I will have a look. I think in upgrade.rst it should be mentioned that libhtp is no longer built separately, so downstream packagers no longer need to include it as a dep or part of their environments. (?) Otherwise, the configuration options and such are the same - from a user point of view there should not be much difference? Anything else that would normally be mentioned?

You can try git grep libhtp | cut -d: -f1 | uniq to see which files refer to libhtp... There may be some scripts or .github files to change as well ;-)

@cccs-rtmorti
Copy link
Contributor Author

cccs-rtmorti commented Dec 29, 2022

Code : Do you have a script to minimize the difference without all the constants renaming ?

I do not have such a script. I could write one - it would just be a bunch of sed commands to 'unrename' the constants. The resulting code would not compile, and you would have to look at the diff outside of github.

Yes, that is what I would enjoy... If you have a csv with the constants renaming, I can work on it

No problem. When I wrote the commit message I went through and found all the constants that changed, so turning that into a csv is no problem.

constants.csv

@cccs-rtmorti
Copy link
Contributor Author

You can try git grep libhtp | cut -d: -f1 | uniq to see which files refer to libhtp... There may be some scripts or .github files to change as well ;-)

Will do! :)

@catenacyber
Copy link
Contributor

Thanks for the csv
Are you planning on a next version soon ? Or should I do some code review first ?

@cccs-rtmorti
Copy link
Contributor Author

I am planning to go through the docs tomorrow, and then I will update with a new PR v5 that includes the other changes.

If you want to do some review, that would be great - I can incorporate anything else at the same time.

@catenacyber
Copy link
Contributor

I will wait for v5 first then :-)

Ticket: OISF#2696

There are a lot of changes here, which are described below.

In general these changes are renaming constants to conform to the
libhtp-rs versions (which are generated by cbindgen); making all htp
types opaque and changing struct->member references to
htp_struct_member() function calls; and a handful of changes to offload
functionality onto libhtp-rs from suricata, such as URI normalization
and transaction cleanup.

Constants renamed to correspond to cbindgen generated names:

HTP_OK => HTP_STATUS_OK
HTP_ERROR => HTP_STATUS_ERROR

HTP_SERVER_* => HTP_SERVER_PERSONALITY_*

HTP_REQUEST_INVALID_T_E => HTP_FLAGS_REQUEST_INVALID_T_E
HTP_REQUEST_INVALID_C_L => HTP_FLAGS_REQUEST_INVALID_C_L
HTP_HOST_MISSING => HTP_FLAGS_HOST_MISSING
HTP_HOST_AMBIGUOUS => HTP_FLAGS_HOST_AMBIGUOUS
HTP_HOSTU_INVALID => HTP_FLAGS_HOSTU_INVALID
HTP_HOSTH_INVALID => HTP_FLAGS_HOSTH_INVALID

HTP_AUTH_UNRECOGNIZED => HTP_AUTH_TYPE_UNRECOGNIZED

HTP_M_UNKNOWN => HTP_METHOD_UNKNOWN
HTP_M_GET => HTP_METHOD_GET
HTP_M_POST => HTP_METHOD_POST
HTP_M_PUT => HTP_METHOD_PUT
HTP_M_CONNECT => HTP_METHOD_CONNECT

HTP_STREAM_ERROR => HTP_STREAM_STATE_ERROR
HTP_STREAM_TUNNEL => HTP_STREAM_STATE_TUNNEL

HTP_REQUEST_LINE => HTP_REQUEST_PROGRESS_LINE
HTP_REQUEST_HEADERS => HTP_REQUEST_PROGRESS_HEADERS
HTP_REQUEST_BODY => HTP_REQUEST_PROGRESS_BODY
HTP_REQUEST_TRAILER => HTP_REQUEST_PROGRESS_TRAILER
HTP_REQUEST_COMPLETE => HTP_REQUEST_PROGRESS_COMPLETE
HTP_RESPONSE_LINE => HTP_RESPONSE_PROGRESS_LINE
HTP_RESPONSE_HEADERS => HTP_RESPONSE_PROGRESS_HEADERS
HTP_RESPONSE_BODY => HTP_RESPONSE_PROGRESS_BODY
HTP_RESPONSE_TRAILER => HTP_RESPONSE_PROGRESS_TRAILER
HTP_RESPONSE_COMPLETE => HTP_RESPONSE_PROGRESS_COMPLETE

HTP_PROTOCOL_1_1 => HTP_PROTOCOL_V1_1
HTP_PROTOCOL_1_0 => HTP_PROTOCOL_V1_0
HTP_PROTOCOL_0_9 => HTP_PROTOCOL_V0_9

Functions introduced to handle opaque htp_tx_t:
- tx->cfg => htp_tx_cfg(tx)
- tx->flags => htp_tx_flags(tx)
- tx->is_protocol_0_9 => htp_tx_is_protocol_0_9(tx)
- tx->parsed_uri => htp_tx_parsed_uri(tx)
- tx->parsed_uri->path => htp_uri_path(htp_tx_parsed_uri(tx)
- tx->parsed_uri->hostname => htp_uri_hostname(htp_tx_parsed_uri(tx))
- tx->request_auth_type => htp_tx_request_auth_type(tx)
- tx->request_headers => htp_tx_request_headers(tx)
- tx->request_hostname => htp_tx_request_hostname(tx)
- tx->request_line => htp_tx_request_line(tx)
- tx->request_message_len => htp_tx_request_message_len(tx)
- tx->request_method => htp_tx_request_method(tx)
- tx->request_method_number => htp_tx_request_method_number(tx)
- tx->request_port_number => htp_tx_request_port_number(tx)
- tx->request_progress => htp_tx_request_progress(tx)
- tx->request_protocol => htp_tx_request_protocol(tx)
- tx->request_protocol_number => htp_tx_request_protocol_number(tx)
- tx->request_uri => htp_tx_request_uri(tx)
- tx->response_headers => htp_tx_response_headers(tx)
- tx->response_line => htp_tx_response_line(tx)
- tx->response_message => htp_tx_response_message(tx)
- tx->response_message_len => htp_tx_response_message_len(tx)
- tx->response_status => htp_tx_response_status(tx)
- tx->response_status_number => htp_tx_response_status_number(tx)
- tx->response_progress => htp_tx_response_progress(tx)
- tx->response_protocol_number => htp_tx_response_protocol_number(tx)
- htp_tx_get_user_data() => htp_tx_user_data(tx)
- htp_table_get_c(tx->request_headers, header) => htp_tx_request_header(tx, header)
- htp_table_get_c(tx->response_headers, header) => htp_tx_response_header(tx, header)
- htp_table_get_index(tx->request_headers, index) => htp_tx_request_header_index(tx, index)
- htp_table_size(tx->request_headers) => htp_tx_request_headers_size(tx)
- htp_tx_is_http_2_upgrade(tx) convenience function introduced to detect response status 101
  and “Upgrade: h2c" header.

Functions introduced to handle opaque htp_header_t:
- header->name => htp_header_name(header)
- bstr_ptr(header->name) => htp_header_name_ptr(header)
- bstr_len(header->name) => htp_header_name_len(header)
- header->value => htp_header_value(header)
- bstr_len(header->value) => htp_header_value_len(header)
- bstr_ptr(header->value) => htp_header_value_ptr(header)

Functions introduced to handle opaque htp_headers_t:
- htp_table_size(headers) => htp_headers_size(headers)
- htp_table_get_index(headers, index) => htp_headers_get_index(headers, index)

Functions introduced to handle opaque htp_tx_data_t:
- d->len => htp_tx_data_len()
- d->data => htp_tx_data_data()
- htp_tx_data_tx(data) function to get the htp_tx_t from the htp_tx_data_t
- htp_tx_data_is_empty(data) convenience function introduced to test if the data is empty.

Functions introduced to handle opaque htp_connp_t:
- htp_list_get(connp->transactions, txid) => htp_connp_tx(connp, txid)
- htp_list_size(http_state->conn->transactions) => htp_connp_tx_size(connp)
- htp_connp_get_connection(connp) => htp_connp_connection(connp)
- htp_connp_req_data(connp) => htp_connp_request_data(connp)
- htp_connp_req_close(connp) => htp_connp_request_close(connp)
- htp_connp_res_data(connp) => htp_connp_response_data(connp)
- htp_connp_get_jn_tx(connp) => htp_connp_get_request_tx(connp)
- htp_connp_get_out_tx(connp) => htp_connp_get_response_tx(connp)
- htp_connp_req_data_consumed(connp) => htp_connp_request_data_consumed(connp)
- htp_connp_res_data_consumed(connp) => htp_connp_response_data_consumed(connp)
- htp_connp_get_user_data(connp) => htp_connp_user_data(connp)

Functions introduced to handle opaque htp_conn_t:
- conn->in_data_counter => htp_conn_request_data_counter(conn)
- conn->out_data_counter => htp_conn_response_data_counter(conn)

Other changes:

Build libhtp-rs as a crate inside rust. Update autoconf to no longer
use libhtp as an external dependency. Remove HAVE_HTP feature defines
since they are no longer needed.

Make function arguments and return values const where possible

htp_tx_destroy(tx) will now free an incomplete transaction

htp_time_t replaced with standard struct timeval

Callbacks from libhtp now provide the htp_connp_t and the htp_tx_data_t
as separate arguments. This means the connection parser is no longer
fetched from the transaction inside callbacks.

SCHTPGenerateNormalizedUri() functionality moved inside libhtp-rs, which
now provides normalized URI values.
The normalized URI is available with accessor function: htp_tx_normalized_uri()
Configuration settings added to control the behaviour of the URI normalization:
- htp_config_set_normalized_uri_include_all()
- htp_config_set_plusspace_decode()
- htp_config_set_convert_lowercase()
- htp_config_set_double_decode_normalized_query()
- htp_config_set_double_decode_normalized_path()
- htp_config_set_backslash_convert_slashes()
- htp_config_set_bestfit_replacement_byte()
- htp_config_set_convert_lowercase()
- htp_config_set_nul_encoded_terminates()
- htp_config_set_nul_raw_terminates()
- htp_config_set_path_separators_compress()
- htp_config_set_path_separators_decode()
- htp_config_set_u_encoding_decode()
- htp_config_set_url_encoding_invalid_handling()
- htp_config_set_utf8_convert_bestfit()
- htp_config_set_normalized_uri_include_all()
- htp_config_set_plusspace_decode()
Constants related to configuring uri normalization:
- HTP_URL_DECODE_PRESERVE_PERCENT => HTP_URL_ENCODING_HANDLING_PRESERVE_PERCENT
- HTP_URL_DECODE_REMOVE_PERCENT => HTP_URL_ENCODING_HANDLING_REMOVE_PERCENT
- HTP_URL_DECODE_PROCESS_INVALID => HTP_URL_ENCODING_HANDLING_PROCESS_INVALID

htp_config_set_field_limits(soft_limit, hard_limit) changed to
htp_config_set_field_limit(limit) because libhtp didn't implement soft
limits.

libhtp logging API updated to provide HTP_LOG_CODE constants along with
the message. This eliminates the need to perform string matching on
message text to map log messages to HTTP_DECODER_EVENT values, and the
HTP_LOG_CODE values can be used directly. In support of this,
HTP_DECODER_EVENT values are mapped to their corresponding HTP_LOG_CODE
values:

HTTP_DECODER_EVENT_UNKNOWN_ERROR => HTP_LOG_CODE_UNKNOWN
HTTP_DECODER_EVENT_GZIP_DECOMPRESSION_FAILED => HTP_LOG_CODE_GZIP_DECOMPRESSION_FAILED
HTTP_DECODER_EVENT_REQUEST_FIELD_MISSING_COLON => HTP_LOG_CODE_REQUEST_FIELD_MISSING_COLON
HTTP_DECODER_EVENT_RESPONSE_FIELD_MISSING_COLON => HTP_LOG_CODE_RESPONSE_FIELD_MISSING_COLON
HTTP_DECODER_EVENT_INVALID_REQUEST_CHUNK_LEN => HTP_LOG_CODE_INVALID_REQUEST_CHUNK_LEN
HTTP_DECODER_EVENT_INVALID_RESPONSE_CHUNK_LEN => HTP_LOG_CODE_INVALID_RESPONSE_CHUNK_LEN
HTTP_DECODER_EVENT_INVALID_TRANSFER_ENCODING_VALUE_IN_REQUEST => HTP_LOG_CODE_INVALID_TRANSFER_ENCODING_VALUE_IN_REQUEST
HTTP_DECODER_EVENT_INVALID_TRANSFER_ENCODING_VALUE_IN_RESPONSE => HTP_LOG_CODE_INVALID_TRANSFER_ENCODING_VALUE_IN_RESPONSE
HTTP_DECODER_EVENT_INVALID_CONTENT_LENGTH_FIELD_IN_REQUEST => HTP_LOG_CODE_INVALID_CONTENT_LENGTH_FIELD_IN_REQUEST
HTTP_DECODER_EVENT_INVALID_CONTENT_LENGTH_FIELD_IN_RESPONSE => HTP_LOG_CODE_INVALID_CONTENT_LENGTH_FIELD_IN_RESPONSE
HTTP_DECODER_EVENT_DUPLICATE_CONTENT_LENGTH_FIELD_IN_REQUEST => HTP_LOG_CODE_DUPLICATE_CONTENT_LENGTH_FIELD_IN_REQUEST
HTTP_DECODER_EVENT_DUPLICATE_CONTENT_LENGTH_FIELD_IN_RESPONSE => HTP_LOG_CODE_DUPLICATE_CONTENT_LENGTH_FIELD_IN_RESPONSE
HTTP_DECODER_EVENT_100_CONTINUE_ALREADY_SEEN => HTP_LOG_CODE_CONTINUE_ALREADY_SEEN
HTTP_DECODER_EVENT_UNABLE_TO_MATCH_RESPONSE_TO_REQUEST => HTP_LOG_CODE_UNABLE_TO_MATCH_RESPONSE_TO_REQUEST
HTTP_DECODER_EVENT_INVALID_SERVER_PORT_IN_REQUEST => HTP_LOG_CODE_INVALID_SERVER_PORT_IN_REQUEST
HTTP_DECODER_EVENT_INVALID_AUTHORITY_PORT => HTP_LOG_CODE_INVALID_AUTHORITY_PORT
HTTP_DECODER_EVENT_REQUEST_HEADER_INVALID => HTP_LOG_CODE_REQUEST_HEADER_INVALID
HTTP_DECODER_EVENT_RESPONSE_HEADER_INVALID => HTP_LOG_CODE_RESPONSE_HEADER_INVALID
HTTP_DECODER_EVENT_MISSING_HOST_HEADER => HTP_LOG_CODE_MISSING_HOST_HEADER
HTTP_DECODER_EVENT_HOST_HEADER_AMBIGUOUS => HTP_LOG_CODE_HOST_HEADER_AMBIGUOUS
HTTP_DECODER_EVENT_INVALID_REQUEST_FIELD_FOLDING => HTP_LOG_CODE_INVALID_REQUEST_FIELD_FOLDING
HTTP_DECODER_EVENT_INVALID_RESPONSE_FIELD_FOLDING => HTP_LOG_CODE_INVALID_RESPONSE_FIELD_FOLDING
HTTP_DECODER_EVENT_REQUEST_FIELD_TOO_LONG => HTP_LOG_CODE_REQUEST_FIELD_TOO_LONG
HTTP_DECODER_EVENT_RESPONSE_FIELD_TOO_LONG => HTP_LOG_CODE_RESPONSE_FIELD_TOO_LONG
HTTP_DECODER_EVENT_FILE_NAME_TOO_LONG => HTP_LOG_CODE_REQUEST_LINE_INVALID
HTTP_DECODER_EVENT_REQUEST_LINE_INVALID => HTP_LOG_CODE_REQUEST_BODY_UNEXPECTED
HTTP_DECODER_EVENT_REQUEST_BODY_UNEXPECTED => HTP_LOG_CODE_RESPONSE_BODY_UNEXPECTED
HTTP_DECODER_EVENT_REQUEST_SERVER_PORT_TCP_PORT_MISMATCH => HTP_LOG_CODE_REQUEST_SERVER_PORT_TCP_PORT_MISMATCH
HTTP_DECODER_EVENT_URI_HOST_INVALID => HTP_LOG_CODE_URI_HOST_INVALID
HTTP_DECODER_EVENT_HEADER_HOST_INVALID => HTP_LOG_CODE_HEADER_HOST_INVALID
HTTP_DECODER_EVENT_AUTH_UNRECOGNIZED => HTP_LOG_CODE_AUTH_UNRECOGNIZED
HTTP_DECODER_EVENT_REQUEST_HEADER_REPETITION => HTP_LOG_CODE_REQUEST_HEADER_REPETITION
HTTP_DECODER_EVENT_RESPONSE_HEADER_REPETITION => HTP_LOG_CODE_RESPONSE_HEADER_REPETITION
HTTP_DECODER_EVENT_DOUBLE_ENCODED_URI => HTP_LOG_CODE_DOUBLE_ENCODED_URI
HTTP_DECODER_EVENT_URI_DELIM_NON_COMPLIANT => HTP_LOG_CODE_URI_DELIM_NON_COMPLIANT
HTTP_DECODER_EVENT_METHOD_DELIM_NON_COMPLIANT => HTP_LOG_CODE_METHOD_DELIM_NON_COMPLIANT
HTTP_DECODER_EVENT_REQUEST_LINE_LEADING_WHITESPACE => HTP_LOG_CODE_REQUEST_LINE_LEADING_WHITESPACE
HTTP_DECODER_EVENT_TOO_MANY_ENCODING_LAYERS => HTP_LOG_CODE_TOO_MANY_ENCODING_LAYERS
HTTP_DECODER_EVENT_ABNORMAL_CE_HEADER => HTP_LOG_CODE_ABNORMAL_CE_HEADER
HTTP_DECODER_EVENT_RESPONSE_MULTIPART_BYTERANGES => HTP_LOG_CODE_RESPONSE_MULTIPART_BYTERANGES
HTTP_DECODER_EVENT_RESPONSE_ABNORMAL_TRANSFER_ENCODING => HTP_LOG_CODE_RESPONSE_ABNORMAL_TRANSFER_ENCODING
HTTP_DECODER_EVENT_RESPONSE_CHUNKED_OLD_PROTO => HTP_LOG_CODE_RESPONSE_CHUNKED_OLD_PROTO
HTTP_DECODER_EVENT_RESPONSE_INVALID_PROTOCOL => HTP_LOG_CODE_RESPONSE_INVALID_PROTOCOL
HTTP_DECODER_EVENT_RESPONSE_INVALID_STATUS => HTP_LOG_CODE_RESPONSE_INVALID_STATUS
HTTP_DECODER_EVENT_REQUEST_LINE_INCOMPLETE => HTP_LOG_CODE_REQUEST_LINE_INCOMPLETE
HTTP_DECODER_EVENT_LZMA_MEMLIMIT_REACHED => HTP_LOG_CODE_LZMA_MEMLIMIT_REACHED
HTTP_DECODER_EVENT_COMPRESSION_BOMB => HTP_LOG_CODE_COMPRESSION_BOMB

New log events to describe additional anomalies:
HTP_LOG_CODE_REQUEST_TOO_MANY_LZMA_LAYERS
HTP_LOG_CODE_RESPONSE_TOO_MANY_LZMA_LAYERS
HTP_LOG_CODE_PROTOCOL_CONTAINS_EXTRA_DATA
HTP_LOG_CODE_CONTENT_LENGTH_EXTRA_DATA_START
HTP_LOG_CODE_CONTENT_LENGTH_EXTRA_DATA_END
HTP_LOG_CODE_SWITCHING_PROTO_WITH_CONTENT_LENGTH
HTP_LOG_CODE_DEFORMED_EOL
HTP_LOG_CODE_PARSER_STATE_ERROR
HTP_LOG_CODE_MISSING_OUTBOUND_TRANSACTION_DATA
HTP_LOG_CODE_MISSING_INBOUND_TRANSACTION_DATA
HTP_LOG_CODE_ZERO_LENGTH_DATA_CHUNKS
HTP_LOG_CODE_REQUEST_LINE_UNKNOWN_METHOD
HTP_LOG_CODE_REQUEST_LINE_UNKNOWN_METHOD_NO_PROTOCOL
HTP_LOG_CODE_REQUEST_LINE_UNKNOWN_METHOD_INVALID_PROTOCOL
HTP_LOG_CODE_REQUEST_LINE_NO_PROTOCOL
HTP_LOG_CODE_RESPONSE_LINE_INVALID_PROTOCOL
HTP_LOG_CODE_RESPONSE_LINE_INVALID_RESPONSE_STATUS
HTP_LOG_CODE_RESPONSE_BODY_INTERNAL_ERROR
HTP_LOG_CODE_REQUEST_BODY_DATA_CALLBACK_ERROR
HTP_LOG_CODE_RESPONSE_INVALID_EMPTY_NAME
HTP_LOG_CODE_REQUEST_INVALID_EMPTY_NAME
HTP_LOG_CODE_RESPONSE_INVALID_LWS_AFTER_NAME
HTP_LOG_CODE_RESPONSE_HEADER_NAME_NOT_TOKEN
HTP_LOG_CODE_REQUEST_INVALID_LWS_AFTER_NAME
HTP_LOG_CODE_LZMA_DECOMPRESSION_DISABLED
HTP_LOG_CODE_CONNECTION_ALREADY_OPEN
HTP_LOG_CODE_COMPRESSION_BOMB_DOUBLE_LZMA
HTP_LOG_CODE_INVALID_CONTENT_ENCODING
HTP_LOG_CODE_INVALID_GAP
HTP_LOG_CODE_ERROR

The new htp_log API supports consuming log messages more easily than
walking a list and tracking the current offset. Internally, libhtp-rs
now provides log messages as a queue of htp_log_t, which means the
application can simply call htp_conn_next_log() to fetch the next log
message until the queue is empty. Once the application is done with a
log message, they can call htp_log_free() to dispose of it.

Functions supporting htp_log_t:
htp_conn_next_log(conn) - Get the next log message
htp_log_message(log) - To get the text of the message
htp_log_code(log) - To get the HTP_LOG_CODE value
htp_log_free(log) - To free the htp_log_t
@cccs-rtmorti
Copy link
Contributor Author

Opened v5 in #8335

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants