diff --git a/rust/src/applayertemplate/logger.rs b/rust/src/applayertemplate/logger.rs index 0105526fc0f1..766a07acdb9d 100644 --- a/rust/src/applayertemplate/logger.rs +++ b/rust/src/applayertemplate/logger.rs @@ -20,12 +20,14 @@ use crate::jsonbuilder::{JsonBuilder, JsonError}; use std; fn log_template(tx: &TemplateTransaction, js: &mut JsonBuilder) -> Result<(), JsonError> { + js.open_object("template")?; if let Some(ref request) = tx.request { js.set_string("request", request)?; } if let Some(ref response) = tx.response { js.set_string("response", response)?; } + js.close()?; Ok(()) } diff --git a/rust/src/bittorrent_dht/logger.rs b/rust/src/bittorrent_dht/logger.rs index 2cfb9270ef67..74ea7c59ba57 100644 --- a/rust/src/bittorrent_dht/logger.rs +++ b/rust/src/bittorrent_dht/logger.rs @@ -48,6 +48,7 @@ fn print_ip_addr(addr: &[u8]) -> std::string::String { fn log_bittorrent_dht( tx: &BitTorrentDHTTransaction, js: &mut JsonBuilder, ) -> Result<(), JsonError> { + js.open_object("bittorrent_dht")?; js.set_hex("transaction_id", &tx.transaction_id)?; if let Some(client_version) = &tx.client_version { js.set_hex("client_version", client_version)?; @@ -125,6 +126,7 @@ fn log_bittorrent_dht( } js.close()?; }; + js.close()?; Ok(()) } diff --git a/rust/src/http2/logger.rs b/rust/src/http2/logger.rs index d25f852c43ab..099112b1aeb4 100644 --- a/rust/src/http2/logger.rs +++ b/rust/src/http2/logger.rs @@ -192,6 +192,7 @@ fn log_http2_frames(frames: &[HTTP2Frame], js: &mut JsonBuilder) -> Result Result { + js.open_object("http")?; js.set_string("version", "2")?; let mut common: HashMap> = HashMap::new(); @@ -261,8 +262,8 @@ fn log_http2(tx: &HTTP2Transaction, js: &mut JsonBuilder) -> Result Option { } } -fn log_template(tx: &QuicTransaction, js: &mut JsonBuilder) -> Result<(), JsonError> { +fn log_quic(tx: &QuicTransaction, js: &mut JsonBuilder) -> Result<(), JsonError> { js.open_object("quic")?; if tx.header.ty != QuicType::Short { js.set_string("version", String::from(tx.header.version).as_str())?; @@ -153,5 +153,5 @@ pub unsafe extern "C" fn rs_quic_to_json( tx: *mut std::os::raw::c_void, js: &mut JsonBuilder, ) -> bool { let tx = cast_pointer!(tx, QuicTransaction); - log_template(tx, js).is_ok() + log_quic(tx, js).is_ok() } diff --git a/rust/src/snmp/log.rs b/rust/src/snmp/log.rs index 83414816c466..5707f30ccb4e 100644 --- a/rust/src/snmp/log.rs +++ b/rust/src/snmp/log.rs @@ -39,6 +39,7 @@ fn str_of_pdu_type(t:&PduType) -> Cow { fn snmp_log_response(jsb: &mut JsonBuilder, tx: &mut SNMPTransaction) -> Result<(), JsonError> { + jsb.open_object("snmp")?; jsb.set_uint("version", tx.version as u64)?; if tx.encrypted { jsb.set_string("pdu_type", "encrypted")?; @@ -71,11 +72,12 @@ fn snmp_log_response(jsb: &mut JsonBuilder, tx: &mut SNMPTransaction) -> Result< } } + jsb.close()?; return Ok(()); } #[no_mangle] -pub extern "C" fn rs_snmp_log_json_response(jsb: &mut JsonBuilder, tx: &mut SNMPTransaction) -> bool +pub extern "C" fn rs_snmp_log_json_response(tx: &mut SNMPTransaction, jsb: &mut JsonBuilder) -> bool { snmp_log_response(jsb, tx).is_ok() } diff --git a/rust/src/ssh/logger.rs b/rust/src/ssh/logger.rs index 9bc7d7c33f39..008c6cb4517a 100644 --- a/rust/src/ssh/logger.rs +++ b/rust/src/ssh/logger.rs @@ -19,6 +19,7 @@ use super::ssh::SSHTransaction; use crate::jsonbuilder::{JsonBuilder, JsonError}; fn log_ssh(tx: &SSHTransaction, js: &mut JsonBuilder) -> Result { + js.open_object("ssh")?; if tx.cli_hdr.protover.is_empty() && tx.srv_hdr.protover.is_empty() { return Ok(false); } @@ -58,6 +59,7 @@ fn log_ssh(tx: &SSHTransaction, js: &mut JsonBuilder) -> Result } js.close()?; } + js.close()?; return Ok(true); } diff --git a/scripts/setup-app-layer.py b/scripts/setup-app-layer.py index 72f28c986c66..d8426634bca8 100755 --- a/scripts/setup-app-layer.py +++ b/scripts/setup-app-layer.py @@ -200,6 +200,10 @@ def logger_patch_output_c(proto): output = io.StringIO() inlines = open(filename).readlines() for i, line in enumerate(inlines): + if line.find("ALPROTO_TEMPLATE") > -1: + new_line = line.replace("TEMPLATE", proto.upper()).replace( + "template", proto.lower()) + output.write(new_line) if line.find("output-json-template.h") > -1: output.write(line.replace("template", proto.lower())) if line.find("/* Template JSON logger.") > -1: diff --git a/src/app-layer-ftp.c b/src/app-layer-ftp.c index c22c39c134b2..b61fa8b8fd3f 100644 --- a/src/app-layer-ftp.c +++ b/src/app-layer-ftp.c @@ -1406,13 +1406,10 @@ uint16_t JsonGetNextLineFromBuffer(const char *buffer, const uint16_t len) return c == NULL ? len : (uint16_t)(c - buffer + 1); } -void EveFTPDataAddMetadata(const Flow *f, JsonBuilder *jb) +bool EveFTPDataAddMetadata(void *vtx, JsonBuilder *jb) { - const FtpDataState *ftp_state = NULL; - if (f->alstate == NULL) - return; - - ftp_state = (FtpDataState *)f->alstate; + const FtpDataState *ftp_state = (FtpDataState *)vtx; + jb_open_object(jb, "ftp_data"); if (ftp_state->file_name) { jb_set_string_from_bytes(jb, "filename", ftp_state->file_name, ftp_state->file_len); @@ -1427,6 +1424,8 @@ void EveFTPDataAddMetadata(const Flow *f, JsonBuilder *jb) default: break; } + jb_close(jb); + return true; } /** diff --git a/src/app-layer-ftp.h b/src/app-layer-ftp.h index f79c5c9e7675..fb71d6b52de7 100644 --- a/src/app-layer-ftp.h +++ b/src/app-layer-ftp.h @@ -190,7 +190,7 @@ uint64_t FTPMemuseGlobalCounter(void); uint64_t FTPMemcapGlobalCounter(void); uint16_t JsonGetNextLineFromBuffer(const char *buffer, const uint16_t len); -void EveFTPDataAddMetadata(const Flow *f, JsonBuilder *jb); +bool EveFTPDataAddMetadata(void *vtx, JsonBuilder *jb); #endif /* __APP_LAYER_FTP_H__ */ diff --git a/src/output-json-alert.c b/src/output-json-alert.c index c9b5c6a0e022..81cda82ce75d 100644 --- a/src/output-json-alert.c +++ b/src/output-json-alert.c @@ -137,164 +137,6 @@ static int AlertJsonDumpStreamSegmentCallback( return 1; } -static void AlertJsonTls(const Flow *f, JsonBuilder *js) -{ - SSLState *ssl_state = (SSLState *)FlowGetAppState(f); - if (ssl_state) { - jb_open_object(js, "tls"); - - JsonTlsLogJSONExtended(js, ssl_state); - - jb_close(js); - } - - return; -} - -static void AlertJsonSsh(const Flow *f, JsonBuilder *js) -{ - void *ssh_state = FlowGetAppState(f); - if (ssh_state) { - JsonBuilderMark mark = { 0, 0, 0 }; - void *tx_ptr = rs_ssh_state_get_tx(ssh_state, 0); - jb_get_mark(js, &mark); - jb_open_object(js, "ssh"); - if (rs_ssh_log_json(tx_ptr, js)) { - jb_close(js); - } else { - jb_restore_mark(js, &mark); - } - } - - return; -} - -static void AlertJsonHttp2(const Flow *f, const uint64_t tx_id, JsonBuilder *js) -{ - void *h2_state = FlowGetAppState(f); - if (h2_state) { - void *tx_ptr = rs_http2_state_get_tx(h2_state, tx_id); - if (tx_ptr) { - JsonBuilderMark mark = { 0, 0, 0 }; - jb_get_mark(js, &mark); - jb_open_object(js, "http"); - if (rs_http2_log_json(tx_ptr, js)) { - jb_close(js); - } else { - jb_restore_mark(js, &mark); - } - } - } - - return; -} - -static void AlertJsonDnp3(const Flow *f, const uint64_t tx_id, JsonBuilder *js) -{ - DNP3State *dnp3_state = (DNP3State *)FlowGetAppState(f); - if (dnp3_state) { - DNP3Transaction *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_DNP3, - dnp3_state, tx_id); - if (tx) { - JsonBuilderMark mark = { 0, 0, 0 }; - jb_get_mark(js, &mark); - bool logged = false; - jb_open_object(js, "dnp3"); - if (tx->is_request && tx->done) { - jb_open_object(js, "request"); - JsonDNP3LogRequest(js, tx); - jb_close(js); - logged = true; - } - if (!tx->is_request && tx->done) { - jb_open_object(js, "response"); - JsonDNP3LogResponse(js, tx); - jb_close(js); - logged = true; - } - if (logged) { - /* Close dnp3 object. */ - jb_close(js); - } else { - jb_restore_mark(js, &mark); - } - } - } -} - -static void AlertJsonDns(const Flow *f, const uint64_t tx_id, JsonBuilder *js) -{ - void *dns_state = (void *)FlowGetAppState(f); - if (dns_state) { - void *txptr = AppLayerParserGetTx(f->proto, ALPROTO_DNS, - dns_state, tx_id); - if (txptr) { - jb_open_object(js, "dns"); - JsonBuilder *qjs = JsonDNSLogQuery(txptr); - if (qjs != NULL) { - jb_set_object(js, "query", qjs); - jb_free(qjs); - } - JsonBuilder *ajs = JsonDNSLogAnswer(txptr); - if (ajs != NULL) { - jb_set_object(js, "answer", ajs); - jb_free(ajs); - } - jb_close(js); - } - } - return; -} - -static void AlertJsonSNMP(const Flow *f, const uint64_t tx_id, JsonBuilder *js) -{ - void *snmp_state = (void *)FlowGetAppState(f); - if (snmp_state != NULL) { - void *tx = AppLayerParserGetTx(f->proto, ALPROTO_SNMP, snmp_state, - tx_id); - if (tx != NULL) { - jb_open_object(js, "snmp"); - rs_snmp_log_json_response(js, tx); - jb_close(js); - } - } -} - -static void AlertJsonRDP(const Flow *f, const uint64_t tx_id, JsonBuilder *js) -{ - void *rdp_state = (void *)FlowGetAppState(f); - if (rdp_state != NULL) { - void *tx = AppLayerParserGetTx(f->proto, ALPROTO_RDP, rdp_state, - tx_id); - if (tx != NULL) { - JsonBuilderMark mark = { 0, 0, 0 }; - jb_get_mark(js, &mark); - if (!rs_rdp_to_json(tx, js)) { - jb_restore_mark(js, &mark); - } - } - } -} - -static void AlertJsonBitTorrentDHT(const Flow *f, const uint64_t tx_id, JsonBuilder *js) -{ - void *bittorrent_dht_state = (void *)FlowGetAppState(f); - if (bittorrent_dht_state != NULL) { - void *tx = - AppLayerParserGetTx(f->proto, ALPROTO_BITTORRENT_DHT, bittorrent_dht_state, tx_id); - if (tx != NULL) { - JsonBuilderMark mark = { 0, 0, 0 }; - jb_get_mark(js, &mark); - jb_open_object(js, "bittorrent_dht"); - if (rs_bittorrent_dht_logger_log(tx, js)) { - jb_close(js); - } else { - jb_restore_mark(js, &mark); - } - } - } -} - static void AlertJsonSourceTarget(const Packet *p, const PacketAlert *pa, JsonBuilder *js, JsonAddrInfo *addr) { @@ -471,7 +313,21 @@ static void AlertAddAppLayer(const Packet *p, JsonBuilder *jb, const uint64_t tx_id, const uint16_t option_flags) { const AppProto proto = FlowGetAppProtocol(p->flow); + AppLayerLogger *al = GetAppProtoLogger(proto); JsonBuilderMark mark = { 0, 0, 0 }; + if (al && al->LogTx) { + void *state = FlowGetAppState(p->flow); + if (state) { + void *tx = AppLayerParserGetTx(p->flow->proto, proto, state, tx_id); + if (tx) { + jb_get_mark(jb, &mark); + if (!al->LogTx(tx, jb)) { + jb_restore_mark(jb, &mark); + } + } + } + return; + } switch (proto) { case ALPROTO_HTTP1: // TODO: Could result in an empty http object being logged. @@ -486,12 +342,6 @@ static void AlertAddAppLayer(const Packet *p, JsonBuilder *jb, } jb_close(jb); break; - case ALPROTO_TLS: - AlertJsonTls(p->flow, jb); - break; - case ALPROTO_SSH: - AlertJsonSsh(p->flow, jb); - break; case ALPROTO_SMTP: jb_get_mark(jb, &mark); jb_open_object(jb, "smtp"); @@ -535,63 +385,12 @@ static void AlertAddAppLayer(const Packet *p, JsonBuilder *jb, jb_restore_mark(jb, &mark); } break; - case ALPROTO_SIP: - JsonSIPAddMetadata(jb, p->flow, tx_id); - break; - case ALPROTO_RFB: - jb_get_mark(jb, &mark); - if (!JsonRFBAddMetadata(p->flow, tx_id, jb)) { - jb_restore_mark(jb, &mark); - } - break; - case ALPROTO_FTPDATA: - jb_get_mark(jb, &mark); - jb_open_object(jb, "ftp_data"); - EveFTPDataAddMetadata(p->flow, jb); - jb_close(jb); - break; - case ALPROTO_DNP3: - AlertJsonDnp3(p->flow, tx_id, jb); - break; - case ALPROTO_HTTP2: - AlertJsonHttp2(p->flow, tx_id, jb); - break; - case ALPROTO_DNS: - AlertJsonDns(p->flow, tx_id, jb); - break; case ALPROTO_IKE: jb_get_mark(jb, &mark); if (!EveIKEAddMetadata(p->flow, tx_id, jb)) { jb_restore_mark(jb, &mark); } break; - case ALPROTO_MQTT: - jb_get_mark(jb, &mark); - if (!JsonMQTTAddMetadata(p->flow, tx_id, jb)) { - jb_restore_mark(jb, &mark); - } - break; - case ALPROTO_QUIC: - jb_get_mark(jb, &mark); - if (!JsonQuicAddMetadata(p->flow, tx_id, jb)) { - jb_restore_mark(jb, &mark); - } - break; - case ALPROTO_SNMP: - AlertJsonSNMP(p->flow, tx_id, jb); - break; - case ALPROTO_RDP: - AlertJsonRDP(p->flow, tx_id, jb); - break; - case ALPROTO_MODBUS: - jb_get_mark(jb, &mark); - if (!JsonModbusAddMetadata(p->flow, tx_id, jb)) { - jb_restore_mark(jb, &mark); - } - break; - case ALPROTO_BITTORRENT_DHT: - AlertJsonBitTorrentDHT(p->flow, tx_id, jb); - break; default: break; } diff --git a/src/output-json-bittorrent-dht.c b/src/output-json-bittorrent-dht.c index 08b7dc4d722c..066df78f61fb 100644 --- a/src/output-json-bittorrent-dht.c +++ b/src/output-json-bittorrent-dht.c @@ -65,11 +65,9 @@ static int JsonBitTorrentDHTLogger(ThreadVars *tv, void *thread_data, const Pack return TM_ECODE_FAILED; } - jb_open_object(js, "bittorrent_dht"); if (!rs_bittorrent_dht_logger_log(tx, js)) { goto error; } - jb_close(js); OutputJsonBuilderBuffer(js, thread->ctx); jb_free(js); diff --git a/src/output-json-dnp3.c b/src/output-json-dnp3.c index 97b1e92e00ce..4336e04e070c 100644 --- a/src/output-json-dnp3.c +++ b/src/output-json-dnp3.c @@ -210,6 +210,27 @@ void JsonDNP3LogResponse(JsonBuilder *js, DNP3Transaction *dnp3tx) jb_close(js); } +bool AlertJsonDnp3(void *vtx, JsonBuilder *js) +{ + DNP3Transaction *tx = (DNP3Transaction *)vtx; + bool logged = false; + jb_open_object(js, "dnp3"); + if (tx->is_request && tx->done) { + jb_open_object(js, "request"); + JsonDNP3LogRequest(js, tx); + jb_close(js); + logged = true; + } + if (!tx->is_request && tx->done) { + jb_open_object(js, "response"); + JsonDNP3LogResponse(js, tx); + jb_close(js); + logged = true; + } + jb_close(js); + return logged; +} + static int JsonDNP3LoggerToServer(ThreadVars *tv, void *thread_data, const Packet *p, Flow *f, void *state, void *vtx, uint64_t tx_id) { diff --git a/src/output-json-dnp3.h b/src/output-json-dnp3.h index 85d02ff1011c..6f81026780d9 100644 --- a/src/output-json-dnp3.h +++ b/src/output-json-dnp3.h @@ -24,5 +24,6 @@ void JsonDNP3LogRequest(JsonBuilder *js, DNP3Transaction *); void JsonDNP3LogResponse(JsonBuilder *js, DNP3Transaction *); void JsonDNP3LogRegister(void); +bool AlertJsonDnp3(void *vtx, JsonBuilder *js); #endif /* __OUTPUT_JSON_DNP3_H__ */ diff --git a/src/output-json-dns.c b/src/output-json-dns.c index 0b6589d5c1bf..e6a19323632a 100644 --- a/src/output-json-dns.c +++ b/src/output-json-dns.c @@ -263,7 +263,7 @@ typedef struct LogDnsLogThread_ { OutputJsonThreadCtx *ctx; } LogDnsLogThread; -JsonBuilder *JsonDNSLogQuery(void *txptr) +static JsonBuilder *JsonDNSLogQuery(void *txptr) { JsonBuilder *queryjb = jb_new_array(); if (queryjb == NULL) { @@ -292,7 +292,7 @@ JsonBuilder *JsonDNSLogQuery(void *txptr) return queryjb; } -JsonBuilder *JsonDNSLogAnswer(void *txptr) +static JsonBuilder *JsonDNSLogAnswer(void *txptr) { if (!rs_dns_do_log_answer(txptr, LOG_ALL_RRTYPES)) { return NULL; @@ -304,6 +304,23 @@ JsonBuilder *JsonDNSLogAnswer(void *txptr) } } +bool AlertJsonDns(void *txptr, JsonBuilder *js) +{ + jb_open_object(js, "dns"); + JsonBuilder *qjs = JsonDNSLogQuery(txptr); + if (qjs != NULL) { + jb_set_object(js, "query", qjs); + jb_free(qjs); + } + JsonBuilder *ajs = JsonDNSLogAnswer(txptr); + if (ajs != NULL) { + jb_set_object(js, "answer", ajs); + jb_free(ajs); + } + jb_close(js); + return true; +} + static int JsonDnsLoggerToServer(ThreadVars *tv, void *thread_data, const Packet *p, Flow *f, void *alstate, void *txptr, uint64_t tx_id) { diff --git a/src/output-json-dns.h b/src/output-json-dns.h index 1e19427361b8..f46cad011089 100644 --- a/src/output-json-dns.h +++ b/src/output-json-dns.h @@ -26,7 +26,6 @@ void JsonDnsLogRegister(void); -JsonBuilder *JsonDNSLogQuery(void *txptr) __attribute__((nonnull)); -JsonBuilder *JsonDNSLogAnswer(void *txptr) __attribute__((nonnull)); +bool AlertJsonDns(void *vtx, JsonBuilder *js); #endif /* __OUTPUT_JSON_DNS_H__ */ diff --git a/src/output-json-file.c b/src/output-json-file.c index a0ce76d71f01..2c559c1b6357 100644 --- a/src/output-json-file.c +++ b/src/output-json-file.c @@ -174,10 +174,7 @@ JsonBuilder *JsonBuildFileInfoRecord(const Packet *p, const File *ff, void *tx, break; case ALPROTO_HTTP2: jb_get_mark(js, &mark); - jb_open_object(js, "http"); - if (EveHTTP2AddMetadata(p->flow, tx_id, js)) { - jb_close(js); - } else { + if (!EveHTTP2AddMetadata(p->flow, tx_id, js)) { jb_restore_mark(js, &mark); } break; diff --git a/src/output-json-ftp.c b/src/output-json-ftp.c index ece9344bf409..9fb8b8c622db 100644 --- a/src/output-json-ftp.c +++ b/src/output-json-ftp.c @@ -57,6 +57,7 @@ static void EveFTPLogCommand(FTPTransaction *tx, JsonBuilder *jb) return; } } + jb_open_object(jb, "ftp"); jb_set_string(jb, "command", tx->command_descriptor->command_name); uint32_t min_length = tx->command_descriptor->command_length + 1; /* command + space */ if (tx->request_length > min_length) { @@ -149,6 +150,7 @@ static void EveFTPLogCommand(FTPTransaction *tx, JsonBuilder *jb) } else { JB_SET_FALSE(jb, "reply_truncated"); } + jb_close(jb); } @@ -169,17 +171,14 @@ static int JsonFTPLogger(ThreadVars *tv, void *thread_data, JsonBuilder *jb = CreateEveHeaderWithTxId(p, LOG_DIR_FLOW, event_type, NULL, tx_id, thread->ctx); if (likely(jb)) { - jb_open_object(jb, event_type); if (f->alproto == ALPROTO_FTPDATA) { - EveFTPDataAddMetadata(f, jb); + if (!EveFTPDataAddMetadata(vtx, jb)) { + goto fail; + } } else { EveFTPLogCommand(tx, jb); } - if (!jb_close(jb)) { - goto fail; - } - OutputJsonBuilderBuffer(jb, thread); jb_free(jb); diff --git a/src/output-json-http2.c b/src/output-json-http2.c index d762e76d0665..171b985e8ae6 100644 --- a/src/output-json-http2.c +++ b/src/output-json-http2.c @@ -88,11 +88,9 @@ static int JsonHttp2Logger(ThreadVars *tv, void *thread_data, const Packet *p, if (unlikely(js == NULL)) return 0; - jb_open_object(js, "http"); if (!rs_http2_log_json(txptr, js)) { goto end; } - jb_close(js); OutputJsonBuilderBuffer(js, aft->ctx); end: jb_free(js); diff --git a/src/output-json-modbus.c b/src/output-json-modbus.c index ace8c061f92d..9e508ead9acc 100644 --- a/src/output-json-modbus.c +++ b/src/output-json-modbus.c @@ -136,19 +136,6 @@ static TmEcode JsonModbusLogThreadDeinit(ThreadVars *t, void *data) return TM_ECODE_OK; } -bool JsonModbusAddMetadata(const Flow *f, uint64_t tx_id, JsonBuilder *js) -{ - void *state = FlowGetAppState(f); - if (state) { - void *tx = AppLayerParserGetTx(f->proto, ALPROTO_MODBUS, state, tx_id); - if (tx) { - return rs_modbus_to_json(tx, js); - } - } - - return false; -} - void JsonModbusLogRegister(void) { /* Register as an eve sub-module. */ diff --git a/src/output-json-modbus.h b/src/output-json-modbus.h index 9bde2dae57a3..2b07e4eb2d5c 100644 --- a/src/output-json-modbus.h +++ b/src/output-json-modbus.h @@ -19,6 +19,5 @@ #define __OUTPUT_JSON_MODBUS_H__ void JsonModbusLogRegister(void); -bool JsonModbusAddMetadata(const Flow *f, uint64_t tx_id, JsonBuilder *js); #endif /* __OUTPUT_JSON_MODBUS_H__ */ diff --git a/src/output-json-mqtt.c b/src/output-json-mqtt.c index 9ea890508070..2f600343e20d 100644 --- a/src/output-json-mqtt.c +++ b/src/output-json-mqtt.c @@ -59,17 +59,9 @@ typedef struct LogMQTTLogThread_ { OutputJsonThreadCtx *ctx; } LogMQTTLogThread; -bool JsonMQTTAddMetadata(const Flow *f, uint64_t tx_id, JsonBuilder *js) +bool JsonMQTTAddMetadata(void *vtx, JsonBuilder *js) { - MQTTState *state = FlowGetAppState(f); - if (state) { - MQTTTransaction *tx = AppLayerParserGetTx(f->proto, ALPROTO_MQTT, state, tx_id); - if (tx) { - return rs_mqtt_logger_log(tx, MQTT_DEFAULTS, js); - } - } - - return false; + return rs_mqtt_logger_log(vtx, MQTT_DEFAULTS, js); } static int JsonMQTTLogger(ThreadVars *tv, void *thread_data, diff --git a/src/output-json-mqtt.h b/src/output-json-mqtt.h index 1acb4e107faf..42d66f48680d 100644 --- a/src/output-json-mqtt.h +++ b/src/output-json-mqtt.h @@ -25,6 +25,6 @@ #define __OUTPUT_JSON_MQTT_H__ void JsonMQTTLogRegister(void); -bool JsonMQTTAddMetadata(const Flow *f, uint64_t tx_id, JsonBuilder *js); +bool JsonMQTTAddMetadata(void *vtx, JsonBuilder *js); #endif /* __OUTPUT_JSON_MQTT_H__ */ diff --git a/src/output-json-quic.c b/src/output-json-quic.c index fdf2d0f09340..830ac78fdfbb 100644 --- a/src/output-json-quic.c +++ b/src/output-json-quic.c @@ -140,19 +140,6 @@ static TmEcode JsonQuicLogThreadDeinit(ThreadVars *t, void *data) return TM_ECODE_OK; } -bool JsonQuicAddMetadata(const Flow *f, uint64_t tx_id, JsonBuilder *js) -{ - void *state = FlowGetAppState(f); - if (state) { - void *tx = AppLayerParserGetTx(f->proto, ALPROTO_QUIC, state, tx_id); - if (tx) { - return rs_quic_to_json(tx, js); - } - } - - return false; -} - void JsonQuicLogRegister(void) { /* Register as an eve sub-module. */ diff --git a/src/output-json-quic.h b/src/output-json-quic.h index 2448d5063a34..48e38185f2bd 100644 --- a/src/output-json-quic.h +++ b/src/output-json-quic.h @@ -22,7 +22,6 @@ #ifndef __OUTPUT_JSON_QUIC_H__ #define __OUTPUT_JSON_QUIC_H__ -bool JsonQuicAddMetadata(const Flow *f, uint64_t tx_id, JsonBuilder *js); void JsonQuicLogRegister(void); #endif /* __OUTPUT_JSON_QUIC_H__ */ diff --git a/src/output-json-rfb.c b/src/output-json-rfb.c index cc12d2f1bbdc..e2b832bece13 100644 --- a/src/output-json-rfb.c +++ b/src/output-json-rfb.c @@ -46,19 +46,6 @@ #include "rust-bindings.h" -bool JsonRFBAddMetadata(const Flow *f, uint64_t tx_id, JsonBuilder *js) -{ - void *state = FlowGetAppState(f); - if (state) { - RFBTransaction *tx = AppLayerParserGetTx(f->proto, ALPROTO_RFB, state, tx_id); - if (tx) { - return rs_rfb_logger_log(tx, js); - } - } - - return false; -} - static int JsonRFBLogger(ThreadVars *tv, void *thread_data, const Packet *p, Flow *f, void *state, void *tx, uint64_t tx_id) { diff --git a/src/output-json-rfb.h b/src/output-json-rfb.h index 1264ee3f6b4b..7e4e48ebd4c8 100644 --- a/src/output-json-rfb.h +++ b/src/output-json-rfb.h @@ -26,6 +26,4 @@ void JsonRFBLogRegister(void); -bool JsonRFBAddMetadata(const Flow *f, uint64_t tx_id, JsonBuilder *js); - #endif /* __OUTPUT_JSON_RFB_H__ */ diff --git a/src/output-json-sip.c b/src/output-json-sip.c index 8297be1cc3eb..7dd442cf6aba 100644 --- a/src/output-json-sip.c +++ b/src/output-json-sip.c @@ -48,17 +48,6 @@ #include "rust.h" -void JsonSIPAddMetadata(JsonBuilder *js, const Flow *f, uint64_t tx_id) -{ - SIPState *state = FlowGetAppState(f); - if (state) { - SIPTransaction *tx = AppLayerParserGetTx(f->proto, ALPROTO_SIP, state, tx_id); - if (tx) { - rs_sip_log_json(tx, js); - } - } -} - static int JsonSIPLogger(ThreadVars *tv, void *thread_data, const Packet *p, Flow *f, void *state, void *tx, uint64_t tx_id) { diff --git a/src/output-json-sip.h b/src/output-json-sip.h index 60145dab5b98..0d2c53fa50df 100644 --- a/src/output-json-sip.h +++ b/src/output-json-sip.h @@ -26,6 +26,4 @@ void JsonSIPLogRegister(void); -void JsonSIPAddMetadata(JsonBuilder *js, const Flow *f, uint64_t tx_id); - #endif /* __OUTPUT_JSON_SIP_H__ */ diff --git a/src/output-json-snmp.c b/src/output-json-snmp.c index 27545b6f6903..cbf0a7c992e4 100644 --- a/src/output-json-snmp.c +++ b/src/output-json-snmp.c @@ -59,11 +59,9 @@ static int JsonSNMPLogger(ThreadVars *tv, void *thread_data, return TM_ECODE_FAILED; } - jb_open_object(jb, "snmp"); - if (!rs_snmp_log_json_response(jb, snmptx)) { + if (!rs_snmp_log_json_response(snmptx, jb)) { goto error; } - jb_close(jb); OutputJsonBuilderBuffer(jb, thread); diff --git a/src/output-json-ssh.c b/src/output-json-ssh.c index 5ec70142f634..45a8d8eab333 100644 --- a/src/output-json-ssh.c +++ b/src/output-json-ssh.c @@ -64,11 +64,9 @@ static int JsonSshLogger(ThreadVars *tv, void *thread_data, const Packet *p, if (unlikely(js == NULL)) return 0; - jb_open_object(js, "ssh"); if (!rs_ssh_log_json(txptr, js)) { goto end; } - jb_close(js); OutputJsonBuilderBuffer(js, thread); end: diff --git a/src/output-json-template.c b/src/output-json-template.c index 76d42ad834e6..2ca48b7ae373 100644 --- a/src/output-json-template.c +++ b/src/output-json-template.c @@ -74,11 +74,9 @@ static int JsonTemplateLogger(ThreadVars *tv, void *thread_data, const Packet *p return TM_ECODE_FAILED; } - jb_open_object(js, "template"); if (!rs_template_logger_log(tx, js)) { goto error; } - jb_close(js); OutputJsonBuilderBuffer(js, thread->ctx); jb_free(js); diff --git a/src/output-json-tls.c b/src/output-json-tls.c index 9771f4d1cd7c..7460a32f2574 100644 --- a/src/output-json-tls.c +++ b/src/output-json-tls.c @@ -392,8 +392,9 @@ static void JsonTlsLogJSONCustom(OutputTlsCtx *tls_ctx, JsonBuilder *js, } } -void JsonTlsLogJSONExtended(JsonBuilder *tjs, SSLState * state) +static bool JsonTlsLogJSONExtendedAux(void *vtx, JsonBuilder *tjs) { + SSLState *state = (SSLState *)vtx; JsonTlsLogJSONBasic(tjs, state); /* tls serial */ @@ -425,6 +426,15 @@ void JsonTlsLogJSONExtended(JsonBuilder *tjs, SSLState * state) JsonTlsLogClientCert(tjs, &state->client_connp, false, false); jb_close(tjs); } + return true; +} + +bool JsonTlsLogJSONExtended(void *vtx, JsonBuilder *tjs) +{ + jb_open_object(tjs, "tls"); + bool r = JsonTlsLogJSONExtendedAux(vtx, tjs); + jb_close(tjs); + return r; } static int JsonTlsLogger(ThreadVars *tv, void *thread_data, const Packet *p, @@ -459,7 +469,7 @@ static int JsonTlsLogger(ThreadVars *tv, void *thread_data, const Packet *p, } /* log extended */ else if (tls_ctx->flags & LOG_TLS_EXTENDED) { - JsonTlsLogJSONExtended(js, ssl_state); + JsonTlsLogJSONExtendedAux(ssl_state, js); } /* log basic */ else { diff --git a/src/output-json-tls.h b/src/output-json-tls.h index 737e6233ef10..42f706b91d3f 100644 --- a/src/output-json-tls.h +++ b/src/output-json-tls.h @@ -29,6 +29,6 @@ void JsonTlsLogRegister(void); #include "app-layer-ssl.h" void JsonTlsLogJSONBasic(JsonBuilder *js, SSLState *ssl_state); -void JsonTlsLogJSONExtended(JsonBuilder *js, SSLState *ssl_state); +bool JsonTlsLogJSONExtended(void *vtx, JsonBuilder *js); #endif /* __OUTPUT_JSON_TLS_H__ */ diff --git a/src/output.c b/src/output.c index c13ab4862eda..8d0ebe6fc129 100644 --- a/src/output.c +++ b/src/output.c @@ -67,6 +67,8 @@ #include "log-stats.h" #include "output-json-nfs.h" #include "output-json-ftp.h" +// for misplaced EveFTPDataAddMetadata +#include "app-layer-ftp.h" #include "output-json-tftp.h" #include "output-json-smb.h" #include "output-json-ike.h" @@ -1126,3 +1128,53 @@ void OutputRegisterLoggers(void) /* BitTorrent DHT JSON logger */ JsonBitTorrentDHTLogRegister(); } + +static AppLayerLogger alert_applayer_loggers[ALPROTO_MAX] = { + { ALPROTO_UNKNOWN, NULL }, + { ALPROTO_HTTP1, NULL }, // special: uses some options flags + { ALPROTO_FTP, NULL }, // TODO missing + { ALPROTO_SMTP, NULL }, // special: uses state + { ALPROTO_TLS, JsonTlsLogJSONExtended }, + { ALPROTO_SSH, rs_ssh_log_json }, + { ALPROTO_IMAP, NULL }, // protocol detection only + { ALPROTO_JABBER, NULL }, // no parser, no logging + { ALPROTO_SMB, NULL }, // special: uses state + { ALPROTO_DCERPC, NULL }, // TODO missing + { ALPROTO_IRC, NULL }, // no parser, no logging + { ALPROTO_DNS, AlertJsonDns }, + { ALPROTO_MODBUS, (SimpleTxLogFunc)rs_modbus_to_json }, + { ALPROTO_ENIP, NULL }, // no logging + { ALPROTO_DNP3, AlertJsonDnp3 }, + { ALPROTO_NFS, NULL }, // special: uses state + { ALPROTO_NTP, NULL }, // no logging + { ALPROTO_FTPDATA, EveFTPDataAddMetadata }, + { ALPROTO_TFTP, NULL }, // TODO missing + { ALPROTO_IKE, NULL }, // special: uses state + { ALPROTO_KRB5, NULL }, // TODO missing + { ALPROTO_QUIC, rs_quic_to_json }, + { ALPROTO_DHCP, NULL }, // TODO missing + { ALPROTO_SNMP, (SimpleTxLogFunc)rs_snmp_log_json_response }, + { ALPROTO_SIP, (SimpleTxLogFunc)rs_sip_log_json }, + { ALPROTO_RFB, rs_rfb_logger_log }, + { ALPROTO_MQTT, JsonMQTTAddMetadata }, + { ALPROTO_PGSQL, NULL }, // TODO missing + { ALPROTO_TELNET, NULL }, // no logging + { ALPROTO_TEMPLATE, rs_template_logger_log }, + { ALPROTO_RDP, (SimpleTxLogFunc)rs_rdp_to_json }, + { ALPROTO_HTTP2, rs_http2_log_json }, + { ALPROTO_BITTORRENT_DHT, rs_bittorrent_dht_logger_log }, + { ALPROTO_HTTP, NULL }, // signature protocol, not for app-layer logging + { ALPROTO_FAILED, NULL }, +#ifdef UNITTESTS + { ALPROTO_TEST, NULL }, +#endif /* UNITESTS */ +}; + +AppLayerLogger *GetAppProtoLogger(AppProto alproto) +{ + if (alproto < ALPROTO_MAX) { + BUG_ON(alert_applayer_loggers[alproto].proto != alproto); + return &alert_applayer_loggers[alproto]; + } + return NULL; +} diff --git a/src/output.h b/src/output.h index 5c2d7bc90e62..0a1196a52e80 100644 --- a/src/output.h +++ b/src/output.h @@ -208,4 +208,13 @@ void OutputLoggerExitPrintStats(ThreadVars *, void *); void OutputSetupActiveLoggers(void); void OutputClearActiveLoggers(void); +typedef bool (*SimpleTxLogFunc)(void *, struct JsonBuilder *); + +typedef struct AppLayerLogger { + AppProto proto; + SimpleTxLogFunc LogTx; +} AppLayerLogger; + +AppLayerLogger *GetAppProtoLogger(AppProto alproto); + #endif /* ! __OUTPUT_H__ */