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

detect: add ldap.request.option keyword - v1 #12321

Conversation

AkakiAlice
Copy link
Contributor

@AkakiAlice AkakiAlice commented Dec 23, 2024

Ticket: #7453

Contribution style:

Our Contribution agreements:

Changes (if applicable):

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

Description:

  • Add ldap.request.operation keyword

ldap.rs

  • Change static mut to pub(super) static mut so I can use ALPROTO_LDAP on file ldap/detect.rs

mod.rs

  • Include detect

types.rs

  • Implement function to convert enum to u8. I used the existing ldap pcaps in S-V and RFC 4511 to set the values

detect-engine-register.c

  • Include ScDetectLdapRegister()

detect.rs

  • Create new file to implement ldap keywords

ldap-keywords.rst

  • Create new file to document ldap keywords

index.rst

  • Include ldap-keywords

SV_BRANCH=OISF/suricata-verify#2206

ldap.request.operation matches on Lightweight Directory Access Protocol request operations
It is an unsigned 8-bit integer
Doesn't support prefiltering

Ticket: OISF#7453
Copy link

codecov bot commented Dec 23, 2024

Codecov Report

Attention: Patch coverage is 77.02703% with 17 lines in your changes missing coverage. Please review.

Project coverage is 83.24%. Comparing base (6f937c7) to head (68fbc10).
Report is 5 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master   #12321      +/-   ##
==========================================
- Coverage   83.26%   83.24%   -0.03%     
==========================================
  Files         912      913       +1     
  Lines      257643   257717      +74     
==========================================
+ Hits       214521   214528       +7     
- Misses      43122    43189      +67     
Flag Coverage Δ
fuzzcorpus 61.19% <24.32%> (+0.05%) ⬆️
livemode 19.40% <24.32%> (+<0.01%) ⬆️
pcap 44.39% <24.32%> (-0.03%) ⬇️
suricata-verify 62.88% <77.02%> (+0.02%) ⬆️
unittests 59.18% <24.32%> (-0.01%) ⬇️

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


Syntax::

ldap.request.operation: operation;
Copy link
Member

Choose a reason for hiding this comment

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

Looking good from a brief overview! Would like other opinions on the name of the keyword. This looks good to me but perhaps too long?

Copy link
Contributor

Choose a reason for hiding this comment

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

For info, this name comes from json schema

@catenacyber
Copy link
Contributor

rustfmt rust/src/ldap/mod.rs does a little change ;-)

@catenacyber
Copy link
Contributor

Please put the full clickable link to redmine ticket https://redmine.openinfosecfoundation.org/issues/7453 ;-)


.. table:: **Operation values for ldap.request.operation keyword**

==== ================================================
Copy link
Contributor

Choose a reason for hiding this comment

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

When you implement ldap.response.operation, the same table should be used for both

Copy link
Contributor

Choose a reason for hiding this comment

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

Following up on what was commented during today's call: I suggest that we move this table to a subsection within LDAP Keywords could be titled LDAP Request and Response operations, and then in each section we can refer to the table/ link to it.

ProtocolOp::ModDnRequest(_) => 12,
ProtocolOp::ModDnResponse(_) => 13,
ProtocolOp::CompareRequest(_) => 14,
ProtocolOp::CompareResponse(_) => 15,
Copy link
Contributor

Choose a reason for hiding this comment

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

Do you know why is there a hole for 16, 17... ?

Maybe something that was implement in LDAP v1 and is obsolete in LDAP v3 but we should still recognize ?

Copy link
Contributor Author

@AkakiAlice AkakiAlice Dec 31, 2024

Choose a reason for hiding this comment

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

I didn't find anything about 17, 16 refers to the option AbandonRequest that is present in etc/schema.json as abandon_request but I didn't see this option in the code

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

But 0x17 = 23

Copy link
Contributor

Choose a reason for hiding this comment

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

So, only 16 seems missing cf ldap_ProtocolOp_vals in Wireshark source code

Copy link
Contributor

Choose a reason for hiding this comment

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

So, we need only to add support for 16 = AbandonRequest

That means

  • Create a ticket about it
  • Create a SV test with a ldap abandon request pcap (with detection support)
  • upgrading ldap-parser crate to 0.4.1 in Cargo.toml.in (dedicated commit) cf https://github.com/rusticata/ldap-parser/blob/master/CHANGELOG.md#041 (recompile + mv Cargo.lock Cargo.lock.in)
  • Then fix uses of abandon cf `git grep -i abandon rust/src/ldap/
  • Add support for detection

Copy link
Contributor

@catenacyber catenacyber Jan 2, 2025

Choose a reason for hiding this comment

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

And for AbandonRequest (and other cases not handled by match &response.protocol_op { in logger.rs ) we should log something, and we can use he functionality offered by EnumStringU8

It would be nice if the switch cases were complete...

ProtocolOp::ExtendedRequest(_) => 23,
ProtocolOp::ExtendedResponse(_) => 24,
ProtocolOp::IntermediateResponse(_) => 25,
ProtocolOp::Unknown => 255,
Copy link
Contributor

Choose a reason for hiding this comment

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

This is not ideal
There should be some documentation at least
Or even better, we should have ProtocolOp::Unknown(u) => u.opcode, but this may require big changes...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is there any example that I could follow to implement ProtocolOp::Unknown(u) => u.opcode,?

Copy link
Contributor

Choose a reason for hiding this comment

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

No example, this requires code investigation, and maybe big changes...

Copy link
Contributor

Choose a reason for hiding this comment

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

Your version should create no unknown (ProtocolOp::Unknown will no longer exist)

And you should document that we are not able to match on some unknown ldap operation like 17.

Maybe we should have a ticket + SV test for it, but let's not bother with this first...

@@ -300,6 +300,34 @@ pub enum ProtocolOp {
Unknown,
}

impl ProtocolOp {
Copy link
Contributor

Choose a reason for hiding this comment

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

@jasonish what do you think about this rust code that works ?

G_LDAP_REQUEST_OPERATION_BUFFER_ID = DetectHelperBufferRegister(
b"ldap.request.operation\0".as_ptr() as *const libc::c_char,
ALPROTO_LDAP,
false,
Copy link
Contributor

Choose a reason for hiding this comment

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

Please comment meaning of these true/false values

}
let ctx = rs_detect_u8_parse(raw) as *mut c_void;
if ctx.is_null() {
return -1;
Copy link
Contributor

Choose a reason for hiding this comment

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

You can implement a protocol_op from_str and call it there if rs_detect_u8_parse fails

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.

Really good, you have a first code working :-)

Design seems good, a few bugs to fix, and you can expand on it with ldap.response.operation

@AkakiAlice
Copy link
Contributor Author

Really good, you have a first code working :-)

Design seems good, a few bugs to fix, and you can expand on it with ldap.response.operation

Should I send ldap.response.operation and ldap.request.operation in the same PR (as they are on the same ticket)?

@catenacyber
Copy link
Contributor

Yes one PR for ldap

@catenacyber
Copy link
Contributor

Replaced by #12343 right ?

@catenacyber catenacyber closed this Jan 7, 2025
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.

4 participants