imap: implement logger

This introduces a logger for IMAP protocol.

Ticket #8276
pull/16515/head
Giuseppe Longo 9 months ago
parent 1d7da06d9f
commit c3d583349b

@ -2832,6 +2832,27 @@
}
}
},
"imap": {
"type": "object",
"description": "IMAP transaction data",
"additionalProperties": false,
"properties": {
"requests": {
"type": "array",
"description": "Array of IMAP request lines in this transaction",
"items": {
"type": "string"
}
},
"responses": {
"type": "array",
"description": "Array of IMAP response lines in this transaction",
"items": {
"type": "string"
}
}
}
},
"in_iface": {
"type": "string"
},

@ -0,0 +1,97 @@
/* Copyright (C) 2026 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
* Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* version 2 along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
// Author: Giuseppe Longo <glongo@oisf.net>
use std::borrow::Cow;
use crate::imap::imap::ImapTransaction;
use crate::imap::parser::{ImapCommand, ImapMessage, ImapMessageType};
use crate::jsonbuilder::{JsonBuilder, JsonError};
const REDACTED: &str = "<redacted>";
fn log_request_line(
request: &ImapMessage, suppress_continuation_data: bool,
) -> Option<Cow<'_, str>> {
if request.raw_line.is_empty() {
return None;
}
match &request.message {
ImapMessageType::ContinuationData if suppress_continuation_data => None,
ImapMessageType::Command {
command: ImapCommand::Login,
arguments,
..
} if !arguments.is_empty() => {
let tag = request.tag_str();
Some(Cow::Owned(format!("{tag} LOGIN {REDACTED}")))
}
ImapMessageType::Command {
command: ImapCommand::Authenticate,
arguments,
..
} if arguments.len() > 1 => {
let tag = request.tag_str();
let mechanism = String::from_utf8_lossy(&arguments[0]);
Some(Cow::Owned(format!(
"{tag} AUTHENTICATE {mechanism} {REDACTED}"
)))
}
_ => Some(String::from_utf8_lossy(&request.raw_line)),
}
}
fn log_imap(tx: &ImapTransaction, js: &mut JsonBuilder) -> Result<(), JsonError> {
js.open_object("imap")?;
if !tx.requests.is_empty() {
js.open_array("requests")?;
let suppress_continuation_data = tx.command.eq_ignore_ascii_case(b"AUTHENTICATE")
|| tx.command.eq_ignore_ascii_case(b"LOGIN");
for req in &tx.requests {
if let Some(line) = log_request_line(req, suppress_continuation_data) {
js.append_string(&line)?;
}
}
js.close()?;
}
if !tx.response_lines.is_empty() {
js.open_array("responses")?;
for line in &tx.response_lines {
js.append_string(&String::from_utf8_lossy(line))?;
}
js.close()?;
}
js.close()?;
Ok(())
}
#[no_mangle]
pub unsafe extern "C" fn SCImapLoggerLog(
tx: *mut std::os::raw::c_void, js: &mut JsonBuilder,
) -> bool {
let tx = cast_pointer!(tx, ImapTransaction);
log_imap(tx, js).is_ok()
}

@ -18,4 +18,5 @@
// Author: Giuseppe Longo <glongo@oisf.net>
pub mod imap;
pub mod logger;
pub mod parser;

@ -990,6 +990,7 @@ void OutputRegisterRootLoggers(void)
// underscore instead of dash for bittorrent_dht
RegisterSimpleJsonApplayerLogger(ALPROTO_BITTORRENT_DHT,
(EveJsonSimpleTxLogFunc)SCBittorrentDhtLogger, "bittorrent_dht");
RegisterSimpleJsonApplayerLogger(ALPROTO_IMAP, (EveJsonSimpleTxLogFunc)SCImapLoggerLog, NULL);
OutputPacketLoggerRegister();
OutputFiledataLoggerRegister();
@ -1236,6 +1237,10 @@ void OutputRegisterLoggers(void)
JsonArpLogRegister();
/* LLMNR JSON logger */
JsonLLMNRLogRegister();
/* IMAP JSON logger. */
OutputRegisterTxSubModule(LOGGER_JSON_TX, "eve-log", "JsonImapLog", "eve-log.imap",
OutputJsonLogInitSub, ALPROTO_IMAP, JsonGenericDirFlowLogger, JsonLogThreadInit,
JsonLogThreadDeinit);
for (size_t i = 0; i < preregistered_loggers_nb; i++) {
OutputRegisterTxSubModule(LOGGER_JSON_TX, "eve-log", preregistered_loggers[i].logname,

@ -347,6 +347,7 @@ outputs:
- pop3
- llmnr
#- modbus
- imap
- arp:
enabled: no # Many events can be logged. Disabled by default
- dhcp:

Loading…
Cancel
Save