mirror of https://github.com/OISF/suricata
parent
1d7da06d9f
commit
c3d583349b
@ -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()
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue