ntp: add transaction logging

Adds basic NTP transaction logging for the current supported message
types.

Includes small cleanups around reference ID.

Ticket: #8425
pull/15220/head
Jason Ish 5 months ago
parent 214e47bea1
commit 31b967b089

@ -240,6 +240,8 @@ outputs:
- ssh - ssh
- arp: - arp:
enabled: no enabled: no
- ntp:
enabled: no
- snmp - snmp
- rfb - rfb
- sip - sip

@ -4467,6 +4467,16 @@
} }
} }
}, },
"ntp": {
"type": "object",
"additionalProperties": false,
"properties": {
"reference_id": {
"type": "integer",
"description": "Identifies specific server or reference clock"
}
}
},
"packet": { "packet": {
"type": "string" "type": "string"
}, },

@ -0,0 +1,34 @@
/* 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.
*/
use super::ntp::NTPTransaction;
use crate::jsonbuilder::{JsonBuilder, JsonError};
fn log(jb: &mut JsonBuilder, tx: &NTPTransaction) -> Result<(), JsonError> {
jb.open_object("ntp")?;
jb.set_uint("reference_id", tx.reference_id)?;
jb.close()?;
Ok(())
}
pub(super) unsafe extern "C" fn ntp_log_json(
tx: *const std::os::raw::c_void, jb: *mut std::os::raw::c_void,
) -> bool {
let tx = cast_pointer!(tx, NTPTransaction);
let jb = cast_pointer!(jb, JsonBuilder);
log(jb, tx).is_ok()
}

@ -15,8 +15,9 @@
* 02110-1301, USA. * 02110-1301, USA.
*/ */
//! NTP application layer and parser module. //! NTP application layer, parser and logger module.
// written by Pierre Chifflier <chifflier@wzdftpd.net> // written by Pierre Chifflier <chifflier@wzdftpd.net>
pub mod log;
pub mod ntp; pub mod ntp;

@ -1,4 +1,4 @@
/* Copyright (C) 2017-2021 Open Information Security Foundation /* Copyright (C) 2017-2026 Open Information Security Foundation
* *
* You can copy, redistribute or modify this Program under the terms of * You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free * the GNU General Public License version 2 as published by the Free
@ -19,6 +19,7 @@
extern crate ntp_parser; extern crate ntp_parser;
use self::ntp_parser::*; use self::ntp_parser::*;
use super::log::ntp_log_json;
use crate::applayer::{self, *}; use crate::applayer::{self, *};
use crate::core; use crate::core;
use crate::core::{ALPROTO_FAILED, ALPROTO_UNKNOWN}; use crate::core::{ALPROTO_FAILED, ALPROTO_UNKNOWN};
@ -29,8 +30,10 @@ use std::ffi::CString;
use nom7::Err; use nom7::Err;
use suricata_sys::sys::{ use suricata_sys::sys::{
AppLayerParserState, AppProto, SCAppLayerParserConfParserEnabled, AppLayerParserState, AppProto, EveJsonTxLoggerRegistrationData,
SCAppLayerProtoDetectConfProtoDetectionEnabled, SCAppLayerParserConfParserEnabled, SCAppLayerParserRegisterLogger,
SCAppLayerProtoDetectConfProtoDetectionEnabled, SCOutputEvePreRegisterLogger,
SCOutputJsonLogDirection,
}; };
#[derive(AppLayerEvent)] #[derive(AppLayerEvent)]
@ -58,7 +61,7 @@ pub struct NTPState {
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct NTPTransaction { pub struct NTPTransaction {
/// The NTP reference ID /// The NTP reference ID
pub xid: u32, pub reference_id: u32,
/// The internal transaction id /// The internal transaction id
id: u64, id: u64,
@ -101,9 +104,7 @@ impl NTPState {
NtpPacket::V4(pkt) => (pkt.mode, pkt.ref_id), NtpPacket::V4(pkt) => (pkt.mode, pkt.ref_id),
}; };
if mode == NtpMode::SymmetricActive || mode == NtpMode::Client { if mode == NtpMode::SymmetricActive || mode == NtpMode::Client {
let mut tx = self.new_tx(direction); let tx = self.new_tx(direction, ref_id);
// use the reference id as identifier
tx.xid = ref_id;
self.transactions.push(tx); self.transactions.push(tx);
} }
0 0
@ -127,9 +128,9 @@ impl NTPState {
self.transactions.clear(); self.transactions.clear();
} }
fn new_tx(&mut self, direction: Direction) -> NTPTransaction { fn new_tx(&mut self, direction: Direction, ref_id: u32) -> NTPTransaction {
self.tx_id += 1; self.tx_id += 1;
NTPTransaction::new(direction, self.tx_id) NTPTransaction::new(direction, self.tx_id, ref_id)
} }
pub fn get_tx_by_id(&mut self, tx_id: u64) -> Option<&NTPTransaction> { pub fn get_tx_by_id(&mut self, tx_id: u64) -> Option<&NTPTransaction> {
@ -154,9 +155,9 @@ impl NTPState {
} }
impl NTPTransaction { impl NTPTransaction {
pub fn new(direction: Direction, id: u64) -> NTPTransaction { pub fn new(direction: Direction, id: u64, reference_id: u32) -> NTPTransaction {
NTPTransaction { NTPTransaction {
xid: 0, reference_id,
id, id,
tx_data: applayer::AppLayerTxData::for_direction(direction), tx_data: applayer::AppLayerTxData::for_direction(direction),
} }
@ -295,12 +296,19 @@ pub unsafe extern "C" fn SCRegisterNtpParser() {
let ip_proto_str = CString::new("udp").unwrap(); let ip_proto_str = CString::new("udp").unwrap();
if SCAppLayerProtoDetectConfProtoDetectionEnabled(ip_proto_str.as_ptr(), parser.name) != 0 { if SCAppLayerProtoDetectConfProtoDetectionEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
let alproto = applayer_register_protocol_detection(&parser, 1); ALPROTO_NTP = applayer_register_protocol_detection(&parser, 1);
// store the allocated ID for the probe function let reg_data = EveJsonTxLoggerRegistrationData {
ALPROTO_NTP = alproto; confname: b"eve-log.ntp\0".as_ptr() as *const std::os::raw::c_char,
logname: b"JsonNTPLog\0".as_ptr() as *const std::os::raw::c_char,
alproto: ALPROTO_NTP,
dir: SCOutputJsonLogDirection::LOG_DIR_PACKET as u8,
LogTx: Some(ntp_log_json),
};
SCOutputEvePreRegisterLogger(reg_data);
if SCAppLayerParserConfParserEnabled(ip_proto_str.as_ptr(), parser.name) != 0 { if SCAppLayerParserConfParserEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
let _ = AppLayerRegisterParser(&parser, alproto); let _ = AppLayerRegisterParser(&parser, ALPROTO_NTP);
} }
SCAppLayerParserRegisterLogger(core::IPPROTO_UDP, ALPROTO_NTP);
} else { } else {
SCLogDebug!("Protocol detector and parser disabled for NTP."); SCLogDebug!("Protocol detector and parser disabled for NTP.");
} }

@ -328,6 +328,8 @@ outputs:
- ftp - ftp
- rdp - rdp
- nfs - nfs
#- ntp:
# enabled: no
- smb: - smb:
# restrict to only certain types in the following list # restrict to only certain types in the following list
#types: [file, tree_connect, negotiate, dcerpc, create, #types: [file, tree_connect, negotiate, dcerpc, create,

Loading…
Cancel
Save