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

PostgreSQL: add initial support (#4241) - v4 #6463

Closed
wants to merge 7 commits into from

Conversation

jufajardini
Copy link
Contributor

Link to redmine ticket: https://redmine.openinfosecfoundation.org/issues/4241

Previous PR: #6437

Describe changes:

  • tell Suricata to move on, in case it can't find a transaction, in parse_request (was missing in the last PR)
  • address the c-string terminator ugly log message for CommandComplete

Considerations: Pcap-cnt seems to be always 4 more than in Wireshark, have to investigate it. Timestamp doesn't always show the same thing as in Wireshark, too. Not sure yet what causes that, but wondering if it could be related to when is Suri considering that the transaction is completed...

suricata-verify-pr: 556
OISF/suricata-verify#556

- add nom parsers for decoding most messages from StartupPhase and
SimpleQuery subprotocols
- add unittests
- tests/fuzz: add pgsql to confyaml
When an SSL Accepted is parsed, suri calls STARTTLS and sets
PgsqlStateProgress to Finished.
Known bug: Suri won't identify flow as PGSQL, as of now, if there's
just an SSL Handshake and then tls traffic (as seen in this pcap:
https://git.lekensteyn.nl/peter/wireshark-notes/commit/tls/
pgsql-ssl.pcapng?id=836b6f746df24aa04fa29b71806d8d0e496c2a68
Also: delete uneeded unittests API call in C
The CommandComplete messages c-string terminator didn't add value to
the log messages, this seems to fix that.
When pgsql doesn't find a transaction, we'll return
AppLayerResult::ok(). This was missing in the parse_request function.
@codecov
Copy link

codecov bot commented Oct 8, 2021

Codecov Report

Merging #6463 (f23e535) into master (6fadb97) will decrease coverage by 0.03%.
The diff coverage is 77.21%.

@@            Coverage Diff             @@
##           master    #6463      +/-   ##
==========================================
- Coverage   77.01%   76.97%   -0.04%     
==========================================
  Files         613      615       +2     
  Lines      186715   186794      +79     
==========================================
- Hits       143795   143788       -7     
- Misses      42920    43006      +86     
Flag Coverage Δ
fuzzcorpus 53.04% <48.68%> (-0.01%) ⬇️
suricata-verify 51.62% <79.16%> (-0.06%) ⬇️
unittests 63.10% <12.50%> (-0.03%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

@suricata-qa
Copy link

WARNING:

field test baseline %
tlpr1_stats_chk
.flow.mgr.rows_maxlen 539 364 148.08%
.app_layer.flow.ftp-data 468 522 89.66%

Pipeline 4510

#define __APP_LAYER_PGSQL_H__

void RegisterPgsqlParsers(void);
void PgsqlParserRegisterTests(void);
Copy link
Contributor

Choose a reason for hiding this comment

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

unused PgsqlParserRegisterTests

@@ -0,0 +1,45 @@
/* Copyright (C) 2021 Open Information Security Foundation
Copy link
Contributor

Choose a reason for hiding this comment

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

I think you do not need these files cf rs_dhcp_register_parser

@@ -77,6 +77,7 @@ include = [
"SIPState",
"ModbusState",
"CMark",
"PgsqlTransaction",
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do we need this ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For the C side to see PgsqlTransaction, as it was not directly mentioned in the extern C function declarations. I'll check if it can be removed now, with the other removals that you pointed out...

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks. Why do we need C to see PgsqlTransaction ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was getting compilation errors without that, I believe. I think that can be because Suri core is still in C? To be honest, I don't fully understand all the connections and how things work in the background, yet. But will answer once things are clearer in my head.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Tried removing it now: output-json-pgsql.c complains, because I'm using PgsqlTransaction there. So, that's what made me add it :P

Copy link
Member

Choose a reason for hiding this comment

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

If you look at the DNS parser, it doesn't bother with this assignment from void * to DNSTransaction before passing to Rust, it just passes through the void pointer which works just as well. So thats one way to remove this item from the cbindgen config. Unfortunately in this context it doesn't provide any extra type safety.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I see, thanks for the lead. Is that the preferred way to address such cases?

Copy link
Member

Choose a reason for hiding this comment

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

I see, thanks for the lead. Is that the preferred way to address such cases?

Yeah, I think so. The Rust function takes a void ptr as well and does its own cast, so doing it C provides no value.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Noted! Thanks again :)

fn log_pgsql(tx: &PgsqlTransaction, js: &mut JsonBuilder) -> Result<(), JsonError> {
js.set_uint("tx_id", tx.tx_id)?;
if !tx.requests.is_empty() {
if tx.requests.len() > 1 {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this deserves some doc : it looks like we can have multiple responses for one request ? all inside one transaction...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, that is so. In many cases, a transaction will be comprised of one request and a few replies, in a specific order. Thanks, I'll add that as part of the docs requirement.

Ok(js)
}

// fn log_row_description(columns: &Vec<RowField>) -> Result<JsonBuilder, JsonError>
Copy link
Contributor

Choose a reason for hiding this comment

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

to remove ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That is commented out for now, but could possibly be used when we have extended logs. Do I remove them, for now, then?

Copy link
Contributor

Choose a reason for hiding this comment

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

Or add a config option to have extended logging ?
I would delete it for now...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think the plan is for the extended logging to come in a future version... Ok, I'll delete it, thanks :)

let mut jb = JsonBuilder::new_object();
for field in error_fields {
match field.field_type {
PgsqlErrorNoticeFieldType::SeverityLocalizable => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Could this rather be jb.set_string_from_bytes(field.field_type.to_str(), &field.field_value)?; for all field types ?
cc @jasonish

Copy link
Member

Choose a reason for hiding this comment

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

Yes, I think so. Add a to_str() -> &str on PgsqlErrorNoticeFieldType could shorten this up to just the fields we might want to skip.

@catenacyber
Copy link
Contributor

Looks like there could be some doc cf

  • doc/userguide/configuration/suricata-yaml.rst
  • doc/userguide/output/eve/eve-json-format.rst

You can also add some app-layer events in cf rules directory like rules/mqtt-events.rules

I guess it can wait on detection, but then src/output-json-alert.c should also have some modifications

Looks really awesome by the way

CommandCompletedReceived,
ErrorMessageReceived, // TODO do we really need this one?
ConnectionTerminated,
UnknownState, // TODO do we really need this one?
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like we should have error and stop parsing...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

for the UnknownState, right? Thanks :)

///
/// PGSQL messages don't have a header per se, so we parse the slice for an ok()
fn probe_ts(input: &[u8]) -> bool {
SCLogDebug!("We are in probe_ts");
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we get an incomplete result ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

if we have a gap in the stream, that can result in a temporary incomplete result, is that so? If it is, then I think it could happen. But I must probably investigate this further.

Copy link
Contributor

Choose a reason for hiding this comment

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

if we have a gap in the stream, that can result in a temporary incomplete result, is that so?

Not exactly.
Rather if the client sends the TCP data one byte at a time in each packet...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hm... I haven't found mentions of that, so far, in the documentation. Could you recommend a good way for one to verify this?

Copy link
Contributor

Choose a reason for hiding this comment

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

cf rs_http2_probing_parser_tc returning either ALPROTO_FAILED, ALPROTO_UNKNOWN (for incomplete) or ALPROTO_HTTP2

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, thanks :)

@jufajardini
Copy link
Contributor Author

Looks like there could be some doc cf

* doc/userguide/configuration/suricata-yaml.rst

* doc/userguide/output/eve/eve-json-format.rst

You can also add some app-layer events in cf rules directory like rules/mqtt-events.rules

I guess it can wait on detection, but then src/output-json-alert.c should also have some modifications

Looks really awesome by the way

Thanks, and thanks again for all the feedback, I'm slowly digesting and incorporating them. :)

Comment on lines +428 to +432
pub extern "C" fn rs_pgsql_logger_log(tx: *mut std::os::raw::c_void, js: &mut JsonBuilder) -> bool {
let tx_safe: &mut PgsqlTransaction;
unsafe {
tx_safe = cast_pointer!(tx, PgsqlTransaction);
}
Copy link
Member

Choose a reason for hiding this comment

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

This whole function should be made unsafe now. Sometime after you started this we moved all functions that do a raw pointer cast to unsafe.

@catenacyber catenacyber added needs rebase Needs rebase to master and removed needs verify Needs (a) Suricata-verify test(s) labels Nov 8, 2021
@jufajardini
Copy link
Contributor Author

Replaced by: #6630

@jufajardini jufajardini deleted the 4241/pgsql/v4 branch January 21, 2022 15:15
jasonish added a commit to jasonish/suricata that referenced this pull request Feb 19, 2025
To some EVE fields and a "suricata" object that contains an array of
keywords. These are the keywords that map directly to this field, or
somehow cover this field.

This is an attempt at tooling to help with EVE and keyword parity.

Related to tickets: OISF#5642, OISF#6463, OISF#4772
jasonish added a commit to jasonish/suricata that referenced this pull request Feb 19, 2025
Currently this script has two commands: "missing" and "having".

"missing" will show eve fields that do not map to any keywords.

"having" will sohw eve fields along with their keyword mappsings,
while also validating that those keywords really exist.

Related to tickets: OISF#6463, OISF#4772
jasonish added a commit to jasonish/suricata that referenced this pull request Feb 20, 2025
To some EVE fields and a "suricata" object that contains an array of
keywords. These are the keywords that map directly to this field, or
somehow cover this field.

This is an attempt at tooling to help with EVE and keyword parity.

Related to tickets: OISF#5642, OISF#6463, OISF#4772
jasonish added a commit to jasonish/suricata that referenced this pull request Feb 20, 2025
Currently this script has two commands: "missing" and "having".

"missing" will show eve fields that do not map to any keywords.

"having" will sohw eve fields along with their keyword mappsings,
while also validating that those keywords really exist.

Related to tickets: OISF#6463, OISF#4772
jasonish added a commit to jasonish/suricata that referenced this pull request Feb 20, 2025
To some EVE fields and a "suricata" object that contains an array of
keywords. These are the keywords that map directly to this field, or
somehow cover this field.

This is an attempt at tooling to help with EVE and keyword parity.

Related to tickets: OISF#5642, OISF#6463, OISF#4772
jasonish added a commit to jasonish/suricata that referenced this pull request Feb 20, 2025
Currently this script has two commands: "missing" and "having".

"missing" will show eve fields that do not map to any keywords.

"having" will sohw eve fields along with their keyword mappsings,
while also validating that those keywords really exist.

Related to tickets: OISF#6463, OISF#4772
jasonish added a commit to jasonish/suricata that referenced this pull request Feb 20, 2025
To some EVE fields and a "suricata" object that contains an array of
keywords. These are the keywords that map directly to this field, or
somehow cover this field.

This is an attempt at tooling to help with EVE and keyword parity.

Related to tickets: OISF#5642, OISF#6463, OISF#4772
jasonish added a commit to jasonish/suricata that referenced this pull request Feb 20, 2025
Currently this script has two commands: "missing" and "having".

"missing" will show eve fields that do not map to any keywords.

"having" will sohw eve fields along with their keyword mappsings,
while also validating that those keywords really exist.

Related to tickets: OISF#6463, OISF#4772
jasonish added a commit to jasonish/suricata that referenced this pull request Feb 21, 2025
Currently this script has two commands: "missing" and "having".

"missing" will show eve fields that do not map to any keywords.

"having" will sohw eve fields along with their keyword mappsings,
while also validating that those keywords really exist.

Related to tickets: OISF#6463, OISF#4772
jasonish added a commit to jasonish/suricata that referenced this pull request Feb 21, 2025
To some EVE fields and a "suricata" object that contains an array of
keywords. These are the keywords that map directly to this field, or
somehow cover this field.

This is an attempt at tooling to help with EVE and keyword parity.

Related to tickets: OISF#5642, OISF#6463, OISF#4772
jasonish added a commit to jasonish/suricata that referenced this pull request Feb 21, 2025
Currently this script has two commands: "missing" and "having".

"missing" will show eve fields that do not map to any keywords.

"having" will sohw eve fields along with their keyword mappsings,
while also validating that those keywords really exist.

Related to tickets: OISF#6463, OISF#4772
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs rebase Needs rebase to master
Development

Successfully merging this pull request may close these issues.

4 participants