IMAP protocol parser, logger and sticky buffers v8#15648
Conversation
This introduces a parser for IMAP protocol.
An IMAP transaction has two states driven by the 'complete' field:
- Open (complete = false): waiting for a matching tagged response.
- Complete (complete = true): tagged response received, or special
conditions met (BYE, server greeting).
Completion logic (is_complete):
- If a tagged request exists: requires a matching tagged response.
- No tagged request + BYE: complete (server closing).
- No tagged request + any response: complete (server greeting).
Transactions are created in three places:
1. Request parser: every parsed command creates a new tx.
2. Response parser (tagged, no matching request): midstream/async;
orphan tagged response gets its own tx.
3. Response parser (untagged, no incomplete tx): server greeting or
unsolicited response.
Once open, messages accumulate:
- Request side: continuation and literal data attach to the most
recent incomplete tx.
- Response side: untagged responses attach to the most recent
incomplete tx; tagged responses attach via find_request(tag).
Email extraction happens at most once per tx:
- From literal data in APPEND commands (request side).
- From FETCH response data (response side).
Seven hard limits prevent unbounded growth:
- IMAP_MAX_TX (256, configurable): total transactions. Exceeded:
all incomplete txs force-completed with TooManyTransactions event.
- IMAP_MAX_MSGS_PER_TX (512): requests/responses per tx. Exceeded:
message silently dropped.
- IMAP_MAX_LINES (512): request/response lines per tx. Exceeded:
line silently dropped.
- IMAP_MAX_BODY_SIZE (10MB): email body in ImapParsedEmail.
Exceeded: body truncated, BodyTooLarge event.
- IMAX_MAX_HEADERS (512): Numbers of headers parsed and stored. Exceeded:
TooManyHeaders event.
- IMAP_MAX_LINE_SIZE (8KB): request/response line max length. Exceeded:
LineTooLong event.
- Literal size (u32): bounded by declared size in {N} specifier.
IMAP_MAX_TX only is configurable limit via app-layer.protocols.imap.max-tx.
Ticket OISF#8276
This introduces a logger for IMAP protocol. Ticket OISF#8276
This implements the following sticky buffers for IMAP protocol: - imap.request - imap.response The following frames have been added: - imap.body - imap.headers - imap.pdu The following email sticky buffers have been updated to work with IMAP: - email.from - email.subject - email.to - email.cc - email.date - email.message_id - email.x_mailer The following email sticky buffers have been added and are supported only for IMAP: - email.command - email.body - email.header - email.header.name - email.header.value Ticket OISF#8276
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #15648 +/- ##
==========================================
+ Coverage 82.90% 82.94% +0.03%
==========================================
Files 1006 1009 +3
Lines 273648 276262 +2614
==========================================
+ Hits 226869 229134 +2265
- Misses 46779 47128 +349
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
|
Information: QA ran without warnings. Pipeline = 32039 |
catenacyber
left a comment
There was a problem hiding this comment.
Thanks for the work
CI/QA : ✅
Git ID set : looks fine for me
CLA : you already contributed
Doc update : nice :-)
Redmine ticket : ok, should https://redmine.openinfosecfoundation.org/issues/3244 be closed as duplicate ?
Rustfmt : 🟡 please add the check in CI see scripts/rustfmt.sh
Tests : 🟡 some unanswered questions on SV PR like OISF/suricata-verify#2908 (comment)
Dependencies added: none
Code : looking
Commits segmentation : ok
Commit messages : cool, some questions below
bounded by declared size in {N} specifier
What is {N} specifier ?
silently dropped
Could we have events for it to be not silent ?
| header_names: Vec::new(), | ||
| header_values: Vec::new(), | ||
| direction, | ||
| body_md5, |
There was a problem hiding this comment.
Is this md5 with truncated data or not ?
There was a problem hiding this comment.
With truncated data.
There was a problem hiding this comment.
(maybe needs a mention in the docs)
| } | ||
|
|
||
| #[no_mangle] | ||
| pub unsafe extern "C" fn SCImapMimeConfigBodyMd5(val: bool) { |
There was a problem hiding this comment.
That should be only if IMAP_MIME_BODY_MD5_DISABLED is false (if we did not explicitily disable md5)
There was a problem hiding this comment.
This should be for SMTP as well
There was a problem hiding this comment.
Those are checked above, line 295-298.
There was a problem hiding this comment.
Which file are you talking about ?
For
line 295-298.
I have
}
}
impl ImapState {
| This keyword works with both SMTP and IMAP protocols. | ||
| For SMTP, the config option ``app-layer.protocols.smtp.mime.body-md5`` | ||
| must be enabled or auto. For IMAP, the config option | ||
| ``app-layer.protocols.imap.mime.body-md5`` must be enabled or auto. |
There was a problem hiding this comment.
Also, could we use email.body; to_md5; ?
|
Do we have file extraction ? (or a ticket for it) ? Should we not log the email field ? |
Victor and I agreed on keeping email out for now, and work on it after this is merged since we want to refactor the current email code (which is strictly bounded to SMTP). |
{N} is the literal size (email body) and come from IMAP command, see below:
|
Ok, this was not clear for someone who does not know IMAP ;-) |
Please add a ticket about it and make it blocked by the current IMAP ticket :-) So I will not ask again next time |
|
Not completely :-p
|
catenacyber
left a comment
There was a problem hiding this comment.
Needs some changes for the explicitly disabled md5 : see #15648 (comment)
and likely other changes from inline discussions
|
Replaced with #15730 |
Changes:
Vec::with_capacityin literal is bounded withIMAP_MAX_BODY_SIZEIMAP_MAX_HEADERSLink to ticket: https://redmine.openinfosecfoundation.org/issues/8276
Previous PR: #15617
SV_BRANCH=OISF/suricata-verify#2908