output/alert: rewrite code for app-layer properties

Especially fix setup-app-layer script to not forget this part

This allows, for simple loggers, to have a unique definition
of the actual logging function with the jsonbuilder.
This way, alerts, files, and app-layer event can share the code
to output the same data.

Ticket: #3827
pull/9851/head
Philippe Antoine 2 years ago
parent 90c17652a3
commit 0b6b015e26

@ -20,12 +20,14 @@ use crate::jsonbuilder::{JsonBuilder, JsonError};
use std; use std;
fn log_template(tx: &TemplateTransaction, js: &mut JsonBuilder) -> Result<(), JsonError> { fn log_template(tx: &TemplateTransaction, js: &mut JsonBuilder) -> Result<(), JsonError> {
js.open_object("template")?;
if let Some(ref request) = tx.request { if let Some(ref request) = tx.request {
js.set_string("request", request)?; js.set_string("request", request)?;
} }
if let Some(ref response) = tx.response { if let Some(ref response) = tx.response {
js.set_string("response", response)?; js.set_string("response", response)?;
} }
js.close()?;
Ok(()) Ok(())
} }

@ -48,6 +48,7 @@ fn print_ip_addr(addr: &[u8]) -> std::string::String {
fn log_bittorrent_dht( fn log_bittorrent_dht(
tx: &BitTorrentDHTTransaction, js: &mut JsonBuilder, tx: &BitTorrentDHTTransaction, js: &mut JsonBuilder,
) -> Result<(), JsonError> { ) -> Result<(), JsonError> {
js.open_object("bittorrent_dht")?;
js.set_hex("transaction_id", &tx.transaction_id)?; js.set_hex("transaction_id", &tx.transaction_id)?;
if let Some(client_version) = &tx.client_version { if let Some(client_version) = &tx.client_version {
js.set_hex("client_version", client_version)?; js.set_hex("client_version", client_version)?;
@ -125,6 +126,7 @@ fn log_bittorrent_dht(
} }
js.close()?; js.close()?;
}; };
js.close()?;
Ok(()) Ok(())
} }

@ -192,6 +192,7 @@ fn log_http2_frames(frames: &[HTTP2Frame], js: &mut JsonBuilder) -> Result<bool,
} }
fn log_http2(tx: &HTTP2Transaction, js: &mut JsonBuilder) -> Result<bool, JsonError> { fn log_http2(tx: &HTTP2Transaction, js: &mut JsonBuilder) -> Result<bool, JsonError> {
js.open_object("http")?;
js.set_string("version", "2")?; js.set_string("version", "2")?;
let mut common: HashMap<HeaderName, &Vec<u8>> = HashMap::new(); let mut common: HashMap<HeaderName, &Vec<u8>> = HashMap::new();
@ -261,8 +262,8 @@ fn log_http2(tx: &HTTP2Transaction, js: &mut JsonBuilder) -> Result<bool, JsonEr
let has_response = log_http2_frames(&tx.frames_tc, js)?; let has_response = log_http2_frames(&tx.frames_tc, js)?;
js.close()?; js.close()?;
// Close http2. js.close()?; // http2
js.close()?; js.close()?; // http
return Ok(has_request || has_response || has_headers); return Ok(has_request || has_response || has_headers);
} }

@ -88,7 +88,7 @@ fn quic_tls_extension_name(e: u16) -> Option<String> {
} }
} }
fn log_template(tx: &QuicTransaction, js: &mut JsonBuilder) -> Result<(), JsonError> { fn log_quic(tx: &QuicTransaction, js: &mut JsonBuilder) -> Result<(), JsonError> {
js.open_object("quic")?; js.open_object("quic")?;
if tx.header.ty != QuicType::Short { if tx.header.ty != QuicType::Short {
js.set_string("version", String::from(tx.header.version).as_str())?; 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, tx: *mut std::os::raw::c_void, js: &mut JsonBuilder,
) -> bool { ) -> bool {
let tx = cast_pointer!(tx, QuicTransaction); let tx = cast_pointer!(tx, QuicTransaction);
log_template(tx, js).is_ok() log_quic(tx, js).is_ok()
} }

@ -39,6 +39,7 @@ fn str_of_pdu_type(t:&PduType) -> Cow<str> {
fn snmp_log_response(jsb: &mut JsonBuilder, tx: &mut SNMPTransaction) -> Result<(), JsonError> fn snmp_log_response(jsb: &mut JsonBuilder, tx: &mut SNMPTransaction) -> Result<(), JsonError>
{ {
jsb.open_object("snmp")?;
jsb.set_uint("version", tx.version as u64)?; jsb.set_uint("version", tx.version as u64)?;
if tx.encrypted { if tx.encrypted {
jsb.set_string("pdu_type", "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(()); return Ok(());
} }
#[no_mangle] #[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() snmp_log_response(jsb, tx).is_ok()
} }

@ -19,6 +19,7 @@ use super::ssh::SSHTransaction;
use crate::jsonbuilder::{JsonBuilder, JsonError}; use crate::jsonbuilder::{JsonBuilder, JsonError};
fn log_ssh(tx: &SSHTransaction, js: &mut JsonBuilder) -> Result<bool, JsonError> { fn log_ssh(tx: &SSHTransaction, js: &mut JsonBuilder) -> Result<bool, JsonError> {
js.open_object("ssh")?;
if tx.cli_hdr.protover.is_empty() && tx.srv_hdr.protover.is_empty() { if tx.cli_hdr.protover.is_empty() && tx.srv_hdr.protover.is_empty() {
return Ok(false); return Ok(false);
} }
@ -58,6 +59,7 @@ fn log_ssh(tx: &SSHTransaction, js: &mut JsonBuilder) -> Result<bool, JsonError>
} }
js.close()?; js.close()?;
} }
js.close()?;
return Ok(true); return Ok(true);
} }

@ -200,6 +200,10 @@ def logger_patch_output_c(proto):
output = io.StringIO() output = io.StringIO()
inlines = open(filename).readlines() inlines = open(filename).readlines()
for i, line in enumerate(inlines): 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: if line.find("output-json-template.h") > -1:
output.write(line.replace("template", proto.lower())) output.write(line.replace("template", proto.lower()))
if line.find("/* Template JSON logger.") > -1: if line.find("/* Template JSON logger.") > -1:

@ -1405,13 +1405,10 @@ uint16_t JsonGetNextLineFromBuffer(const char *buffer, const uint16_t len)
return c == NULL ? len : (uint16_t)(c - buffer + 1); 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; const FtpDataState *ftp_state = (FtpDataState *)vtx;
if (f->alstate == NULL) jb_open_object(jb, "ftp_data");
return;
ftp_state = (FtpDataState *)f->alstate;
if (ftp_state->file_name) { if (ftp_state->file_name) {
jb_set_string_from_bytes(jb, "filename", ftp_state->file_name, ftp_state->file_len); jb_set_string_from_bytes(jb, "filename", ftp_state->file_name, ftp_state->file_len);
@ -1426,6 +1423,8 @@ void EveFTPDataAddMetadata(const Flow *f, JsonBuilder *jb)
default: default:
break; break;
} }
jb_close(jb);
return true;
} }
/** /**

@ -190,7 +190,7 @@ uint64_t FTPMemuseGlobalCounter(void);
uint64_t FTPMemcapGlobalCounter(void); uint64_t FTPMemcapGlobalCounter(void);
uint16_t JsonGetNextLineFromBuffer(const char *buffer, const uint16_t len); 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__ */ #endif /* __APP_LAYER_FTP_H__ */

@ -137,164 +137,6 @@ static int AlertJsonDumpStreamSegmentCallback(
return 1; 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, static void AlertJsonSourceTarget(const Packet *p, const PacketAlert *pa,
JsonBuilder *js, JsonAddrInfo *addr) 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 uint64_t tx_id, const uint16_t option_flags)
{ {
const AppProto proto = FlowGetAppProtocol(p->flow); const AppProto proto = FlowGetAppProtocol(p->flow);
EveJsonSimpleAppLayerLogger *al = SCEveJsonSimpleGetLogger(proto);
JsonBuilderMark mark = { 0, 0, 0 }; 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) { switch (proto) {
case ALPROTO_HTTP1: case ALPROTO_HTTP1:
// TODO: Could result in an empty http object being logged. // 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); jb_close(jb);
break; break;
case ALPROTO_TLS:
AlertJsonTls(p->flow, jb);
break;
case ALPROTO_SSH:
AlertJsonSsh(p->flow, jb);
break;
case ALPROTO_SMTP: case ALPROTO_SMTP:
jb_get_mark(jb, &mark); jb_get_mark(jb, &mark);
jb_open_object(jb, "smtp"); jb_open_object(jb, "smtp");
@ -535,63 +385,12 @@ static void AlertAddAppLayer(const Packet *p, JsonBuilder *jb,
jb_restore_mark(jb, &mark); jb_restore_mark(jb, &mark);
} }
break; 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: case ALPROTO_IKE:
jb_get_mark(jb, &mark); jb_get_mark(jb, &mark);
if (!EveIKEAddMetadata(p->flow, tx_id, jb)) { if (!EveIKEAddMetadata(p->flow, tx_id, jb)) {
jb_restore_mark(jb, &mark); jb_restore_mark(jb, &mark);
} }
break; 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: default:
break; break;
} }

@ -65,11 +65,9 @@ static int JsonBitTorrentDHTLogger(ThreadVars *tv, void *thread_data, const Pack
return TM_ECODE_FAILED; return TM_ECODE_FAILED;
} }
jb_open_object(js, "bittorrent_dht");
if (!rs_bittorrent_dht_logger_log(tx, js)) { if (!rs_bittorrent_dht_logger_log(tx, js)) {
goto error; goto error;
} }
jb_close(js);
OutputJsonBuilderBuffer(js, thread->ctx); OutputJsonBuilderBuffer(js, thread->ctx);
jb_free(js); jb_free(js);

@ -210,6 +210,27 @@ void JsonDNP3LogResponse(JsonBuilder *js, DNP3Transaction *dnp3tx)
jb_close(js); 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, static int JsonDNP3LoggerToServer(ThreadVars *tv, void *thread_data,
const Packet *p, Flow *f, void *state, void *vtx, uint64_t tx_id) const Packet *p, Flow *f, void *state, void *vtx, uint64_t tx_id)
{ {

@ -24,5 +24,6 @@ void JsonDNP3LogRequest(JsonBuilder *js, DNP3Transaction *);
void JsonDNP3LogResponse(JsonBuilder *js, DNP3Transaction *); void JsonDNP3LogResponse(JsonBuilder *js, DNP3Transaction *);
void JsonDNP3LogRegister(void); void JsonDNP3LogRegister(void);
bool AlertJsonDnp3(void *vtx, JsonBuilder *js);
#endif /* __OUTPUT_JSON_DNP3_H__ */ #endif /* __OUTPUT_JSON_DNP3_H__ */

@ -263,7 +263,7 @@ typedef struct LogDnsLogThread_ {
OutputJsonThreadCtx *ctx; OutputJsonThreadCtx *ctx;
} LogDnsLogThread; } LogDnsLogThread;
JsonBuilder *JsonDNSLogQuery(void *txptr) static JsonBuilder *JsonDNSLogQuery(void *txptr)
{ {
JsonBuilder *queryjb = jb_new_array(); JsonBuilder *queryjb = jb_new_array();
if (queryjb == NULL) { if (queryjb == NULL) {
@ -292,7 +292,7 @@ JsonBuilder *JsonDNSLogQuery(void *txptr)
return queryjb; return queryjb;
} }
JsonBuilder *JsonDNSLogAnswer(void *txptr) static JsonBuilder *JsonDNSLogAnswer(void *txptr)
{ {
if (!rs_dns_do_log_answer(txptr, LOG_ALL_RRTYPES)) { if (!rs_dns_do_log_answer(txptr, LOG_ALL_RRTYPES)) {
return NULL; 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, static int JsonDnsLoggerToServer(ThreadVars *tv, void *thread_data,
const Packet *p, Flow *f, void *alstate, void *txptr, uint64_t tx_id) const Packet *p, Flow *f, void *alstate, void *txptr, uint64_t tx_id)
{ {

@ -26,7 +26,6 @@
void JsonDnsLogRegister(void); void JsonDnsLogRegister(void);
JsonBuilder *JsonDNSLogQuery(void *txptr) __attribute__((nonnull)); bool AlertJsonDns(void *vtx, JsonBuilder *js);
JsonBuilder *JsonDNSLogAnswer(void *txptr) __attribute__((nonnull));
#endif /* __OUTPUT_JSON_DNS_H__ */ #endif /* __OUTPUT_JSON_DNS_H__ */

@ -123,6 +123,7 @@ JsonBuilder *JsonBuildFileInfoRecord(const Packet *p, const File *ff, void *tx,
return NULL; return NULL;
JsonBuilderMark mark = { 0, 0, 0 }; JsonBuilderMark mark = { 0, 0, 0 };
EveJsonSimpleAppLayerLogger *al;
switch (p->flow->alproto) { switch (p->flow->alproto) {
case ALPROTO_HTTP1: case ALPROTO_HTTP1:
jb_open_object(js, "http"); jb_open_object(js, "http");
@ -172,13 +173,19 @@ JsonBuilder *JsonBuildFileInfoRecord(const Packet *p, const File *ff, void *tx,
jb_restore_mark(js, &mark); jb_restore_mark(js, &mark);
} }
break; break;
case ALPROTO_HTTP2: default:
jb_get_mark(js, &mark); al = SCEveJsonSimpleGetLogger(p->flow->alproto);
jb_open_object(js, "http"); if (al && al->LogTx) {
if (EveHTTP2AddMetadata(p->flow, tx_id, js)) { void *state = FlowGetAppState(p->flow);
jb_close(js); if (state) {
} else { tx = AppLayerParserGetTx(p->flow->proto, p->flow->alproto, state, tx_id);
jb_restore_mark(js, &mark); if (tx) {
jb_get_mark(js, &mark);
if (!al->LogTx(tx, js)) {
jb_restore_mark(js, &mark);
}
}
}
} }
break; break;
} }

@ -57,6 +57,7 @@ static void EveFTPLogCommand(FTPTransaction *tx, JsonBuilder *jb)
return; return;
} }
} }
jb_open_object(jb, "ftp");
jb_set_string(jb, "command", tx->command_descriptor->command_name); jb_set_string(jb, "command", tx->command_descriptor->command_name);
uint32_t min_length = tx->command_descriptor->command_length + 1; /* command + space */ uint32_t min_length = tx->command_descriptor->command_length + 1; /* command + space */
if (tx->request_length > min_length) { if (tx->request_length > min_length) {
@ -149,6 +150,7 @@ static void EveFTPLogCommand(FTPTransaction *tx, JsonBuilder *jb)
} else { } else {
JB_SET_FALSE(jb, "reply_truncated"); JB_SET_FALSE(jb, "reply_truncated");
} }
jb_close(jb);
} }
@ -169,17 +171,14 @@ static int JsonFTPLogger(ThreadVars *tv, void *thread_data,
JsonBuilder *jb = JsonBuilder *jb =
CreateEveHeaderWithTxId(p, LOG_DIR_FLOW, event_type, NULL, tx_id, thread->ctx); CreateEveHeaderWithTxId(p, LOG_DIR_FLOW, event_type, NULL, tx_id, thread->ctx);
if (likely(jb)) { if (likely(jb)) {
jb_open_object(jb, event_type);
if (f->alproto == ALPROTO_FTPDATA) { if (f->alproto == ALPROTO_FTPDATA) {
EveFTPDataAddMetadata(f, jb); if (!EveFTPDataAddMetadata(vtx, jb)) {
goto fail;
}
} else { } else {
EveFTPLogCommand(tx, jb); EveFTPLogCommand(tx, jb);
} }
if (!jb_close(jb)) {
goto fail;
}
OutputJsonBuilderBuffer(jb, thread); OutputJsonBuilderBuffer(jb, thread);
jb_free(jb); jb_free(jb);

@ -61,19 +61,6 @@ typedef struct JsonHttp2LogThread_ {
OutputJsonThreadCtx *ctx; OutputJsonThreadCtx *ctx;
} JsonHttp2LogThread; } JsonHttp2LogThread;
bool EveHTTP2AddMetadata(const Flow *f, uint64_t tx_id, JsonBuilder *jb)
{
void *state = FlowGetAppState(f);
if (state) {
void *tx = AppLayerParserGetTx(f->proto, ALPROTO_HTTP2, state, tx_id);
if (tx) {
return rs_http2_log_json(tx, jb);
}
}
return false;
}
static int JsonHttp2Logger(ThreadVars *tv, void *thread_data, const Packet *p, static int JsonHttp2Logger(ThreadVars *tv, void *thread_data, const Packet *p,
Flow *f, void *state, void *txptr, uint64_t tx_id) Flow *f, void *state, void *txptr, uint64_t tx_id)
{ {
@ -88,11 +75,9 @@ static int JsonHttp2Logger(ThreadVars *tv, void *thread_data, const Packet *p,
if (unlikely(js == NULL)) if (unlikely(js == NULL))
return 0; return 0;
jb_open_object(js, "http");
if (!rs_http2_log_json(txptr, js)) { if (!rs_http2_log_json(txptr, js)) {
goto end; goto end;
} }
jb_close(js);
OutputJsonBuilderBuffer(js, aft->ctx); OutputJsonBuilderBuffer(js, aft->ctx);
end: end:
jb_free(js); jb_free(js);

@ -25,6 +25,5 @@
#define __OUTPUT_JSON_HTTP2_H__ #define __OUTPUT_JSON_HTTP2_H__
void JsonHttp2LogRegister(void); void JsonHttp2LogRegister(void);
bool EveHTTP2AddMetadata(const Flow *f, uint64_t tx_id, JsonBuilder *jb);
#endif /* __OUTPUT_JSON_HTTP2_H__ */ #endif /* __OUTPUT_JSON_HTTP2_H__ */

@ -136,19 +136,6 @@ static TmEcode JsonModbusLogThreadDeinit(ThreadVars *t, void *data)
return TM_ECODE_OK; 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) void JsonModbusLogRegister(void)
{ {
/* Register as an eve sub-module. */ /* Register as an eve sub-module. */

@ -19,6 +19,5 @@
#define __OUTPUT_JSON_MODBUS_H__ #define __OUTPUT_JSON_MODBUS_H__
void JsonModbusLogRegister(void); void JsonModbusLogRegister(void);
bool JsonModbusAddMetadata(const Flow *f, uint64_t tx_id, JsonBuilder *js);
#endif /* __OUTPUT_JSON_MODBUS_H__ */ #endif /* __OUTPUT_JSON_MODBUS_H__ */

@ -59,17 +59,9 @@ typedef struct LogMQTTLogThread_ {
OutputJsonThreadCtx *ctx; OutputJsonThreadCtx *ctx;
} LogMQTTLogThread; } LogMQTTLogThread;
bool JsonMQTTAddMetadata(const Flow *f, uint64_t tx_id, JsonBuilder *js) bool JsonMQTTAddMetadata(void *vtx, JsonBuilder *js)
{ {
MQTTState *state = FlowGetAppState(f); return rs_mqtt_logger_log(vtx, MQTT_DEFAULTS, js);
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;
} }
static int JsonMQTTLogger(ThreadVars *tv, void *thread_data, static int JsonMQTTLogger(ThreadVars *tv, void *thread_data,

@ -25,6 +25,6 @@
#define __OUTPUT_JSON_MQTT_H__ #define __OUTPUT_JSON_MQTT_H__
void JsonMQTTLogRegister(void); 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__ */ #endif /* __OUTPUT_JSON_MQTT_H__ */

@ -140,19 +140,6 @@ static TmEcode JsonQuicLogThreadDeinit(ThreadVars *t, void *data)
return TM_ECODE_OK; 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) void JsonQuicLogRegister(void)
{ {
/* Register as an eve sub-module. */ /* Register as an eve sub-module. */

@ -22,7 +22,6 @@
#ifndef __OUTPUT_JSON_QUIC_H__ #ifndef __OUTPUT_JSON_QUIC_H__
#define __OUTPUT_JSON_QUIC_H__ #define __OUTPUT_JSON_QUIC_H__
bool JsonQuicAddMetadata(const Flow *f, uint64_t tx_id, JsonBuilder *js);
void JsonQuicLogRegister(void); void JsonQuicLogRegister(void);
#endif /* __OUTPUT_JSON_QUIC_H__ */ #endif /* __OUTPUT_JSON_QUIC_H__ */

@ -46,19 +46,6 @@
#include "rust-bindings.h" #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, static int JsonRFBLogger(ThreadVars *tv, void *thread_data,
const Packet *p, Flow *f, void *state, void *tx, uint64_t tx_id) const Packet *p, Flow *f, void *state, void *tx, uint64_t tx_id)
{ {

@ -26,6 +26,4 @@
void JsonRFBLogRegister(void); void JsonRFBLogRegister(void);
bool JsonRFBAddMetadata(const Flow *f, uint64_t tx_id, JsonBuilder *js);
#endif /* __OUTPUT_JSON_RFB_H__ */ #endif /* __OUTPUT_JSON_RFB_H__ */

@ -48,17 +48,6 @@
#include "rust.h" #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, static int JsonSIPLogger(ThreadVars *tv, void *thread_data,
const Packet *p, Flow *f, void *state, void *tx, uint64_t tx_id) const Packet *p, Flow *f, void *state, void *tx, uint64_t tx_id)
{ {

@ -26,6 +26,4 @@
void JsonSIPLogRegister(void); void JsonSIPLogRegister(void);
void JsonSIPAddMetadata(JsonBuilder *js, const Flow *f, uint64_t tx_id);
#endif /* __OUTPUT_JSON_SIP_H__ */ #endif /* __OUTPUT_JSON_SIP_H__ */

@ -59,11 +59,9 @@ static int JsonSNMPLogger(ThreadVars *tv, void *thread_data,
return TM_ECODE_FAILED; return TM_ECODE_FAILED;
} }
jb_open_object(jb, "snmp"); if (!rs_snmp_log_json_response(snmptx, jb)) {
if (!rs_snmp_log_json_response(jb, snmptx)) {
goto error; goto error;
} }
jb_close(jb);
OutputJsonBuilderBuffer(jb, thread); OutputJsonBuilderBuffer(jb, thread);

@ -64,11 +64,9 @@ static int JsonSshLogger(ThreadVars *tv, void *thread_data, const Packet *p,
if (unlikely(js == NULL)) if (unlikely(js == NULL))
return 0; return 0;
jb_open_object(js, "ssh");
if (!rs_ssh_log_json(txptr, js)) { if (!rs_ssh_log_json(txptr, js)) {
goto end; goto end;
} }
jb_close(js);
OutputJsonBuilderBuffer(js, thread); OutputJsonBuilderBuffer(js, thread);
end: end:

@ -74,11 +74,9 @@ static int JsonTemplateLogger(ThreadVars *tv, void *thread_data, const Packet *p
return TM_ECODE_FAILED; return TM_ECODE_FAILED;
} }
jb_open_object(js, "template");
if (!rs_template_logger_log(tx, js)) { if (!rs_template_logger_log(tx, js)) {
goto error; goto error;
} }
jb_close(js);
OutputJsonBuilderBuffer(js, thread->ctx); OutputJsonBuilderBuffer(js, thread->ctx);
jb_free(js); jb_free(js);

@ -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); JsonTlsLogJSONBasic(tjs, state);
/* tls serial */ /* tls serial */
@ -425,6 +426,15 @@ void JsonTlsLogJSONExtended(JsonBuilder *tjs, SSLState * state)
JsonTlsLogClientCert(tjs, &state->client_connp, false, false); JsonTlsLogClientCert(tjs, &state->client_connp, false, false);
jb_close(tjs); 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, 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 */ /* log extended */
else if (tls_ctx->flags & LOG_TLS_EXTENDED) { else if (tls_ctx->flags & LOG_TLS_EXTENDED) {
JsonTlsLogJSONExtended(js, ssl_state); JsonTlsLogJSONExtendedAux(ssl_state, js);
} }
/* log basic */ /* log basic */
else { else {

@ -29,6 +29,6 @@ void JsonTlsLogRegister(void);
#include "app-layer-ssl.h" #include "app-layer-ssl.h"
void JsonTlsLogJSONBasic(JsonBuilder *js, SSLState *ssl_state); 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__ */ #endif /* __OUTPUT_JSON_TLS_H__ */

@ -67,6 +67,8 @@
#include "log-stats.h" #include "log-stats.h"
#include "output-json-nfs.h" #include "output-json-nfs.h"
#include "output-json-ftp.h" #include "output-json-ftp.h"
// for misplaced EveFTPDataAddMetadata
#include "app-layer-ftp.h"
#include "output-json-tftp.h" #include "output-json-tftp.h"
#include "output-json-smb.h" #include "output-json-smb.h"
#include "output-json-ike.h" #include "output-json-ike.h"
@ -1126,3 +1128,53 @@ void OutputRegisterLoggers(void)
/* BitTorrent DHT JSON logger */ /* BitTorrent DHT JSON logger */
JsonBitTorrentDHTLogRegister(); JsonBitTorrentDHTLogRegister();
} }
static EveJsonSimpleAppLayerLogger simple_json_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, (EveJsonSimpleTxLogFunc)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, (EveJsonSimpleTxLogFunc)rs_snmp_log_json_response },
{ ALPROTO_SIP, (EveJsonSimpleTxLogFunc)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, (EveJsonSimpleTxLogFunc)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 */
};
EveJsonSimpleAppLayerLogger *SCEveJsonSimpleGetLogger(AppProto alproto)
{
if (alproto < ALPROTO_MAX) {
BUG_ON(simple_json_applayer_loggers[alproto].proto != alproto);
return &simple_json_applayer_loggers[alproto];
}
return NULL;
}

@ -208,4 +208,13 @@ void OutputLoggerExitPrintStats(ThreadVars *, void *);
void OutputSetupActiveLoggers(void); void OutputSetupActiveLoggers(void);
void OutputClearActiveLoggers(void); void OutputClearActiveLoggers(void);
typedef bool (*EveJsonSimpleTxLogFunc)(void *, struct JsonBuilder *);
typedef struct EveJsonSimpleAppLayerLogger {
AppProto proto;
EveJsonSimpleTxLogFunc LogTx;
} EveJsonSimpleAppLayerLogger;
EveJsonSimpleAppLayerLogger *SCEveJsonSimpleGetLogger(AppProto alproto);
#endif /* ! __OUTPUT_H__ */ #endif /* ! __OUTPUT_H__ */

Loading…
Cancel
Save