rust/tftp: add tftp parsing and logging

TFTP parsing and logging written in Rust.
Log on eve.json the type of request (read or write), the name of the file and
the mode.

Example of output:
    "tftp":{"packet":"read","file":"rfc1350.txt","mode":"octet"}
pull/3201/head
Clement Galland 7 years ago committed by Victor Julien
parent 0ff60f65ec
commit b9cf49e933

@ -80,6 +80,8 @@ type_map = {
"NFSTransaction": "NFSTransaction",
"NTPState": "NTPState",
"NTPTransaction": "NTPTransaction",
"TFTPTransaction": "TFTPTransaction",
"TFTPState": "TFTPState",
"JsonT": "json_t",
"DetectEngineState": "DetectEngineState",
"core::DetectEngineState": "DetectEngineState",

@ -47,3 +47,4 @@ pub mod ftp;
#[cfg(feature = "experimental")]
pub mod ntp;
pub mod tftp;

@ -0,0 +1,37 @@
/* Copyright (C) 2017 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.
*/
// written by Clément Galland <clement.galland@epita.fr>
extern crate libc;
use json::*;
use tftp::tftp::*;
#[no_mangle]
pub extern "C" fn rs_tftp_log_json_request(tx: &mut TFTPTransaction) -> *mut JsonT
{
let js = Json::object();
match tx.opcode {
1 => js.set_string("packet", "read"),
2 => js.set_string("packet", "write"),
_ => js.set_string("packet", "error")
};
js.set_string("file", tx.filename.as_str());
js.set_string("mode", tx.mode.as_str());
js.unwrap()
}

@ -0,0 +1,21 @@
/* Copyright (C) 2017 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.
*/
// written by Clément Galland <clement.galland@epita.fr>
pub mod tftp;
pub mod log;

@ -0,0 +1,145 @@
/* Copyright (C) 2017 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.
*/
// written by Clément Galland <clement.galland@epita.fr>
extern crate libc;
extern crate nom;
use std::str;
use std;
use std::mem::transmute;
use applayer::LoggerFlags;
#[derive(Debug)]
pub struct TFTPTransaction {
pub opcode : u8,
pub filename : String,
pub mode : String,
pub logged : LoggerFlags
}
pub struct TFTPState {
pub transactions : Vec<TFTPTransaction>
}
impl TFTPTransaction {
pub fn new(opcode : u8, filename : String, mode : String) -> TFTPTransaction {
TFTPTransaction {
opcode : opcode,
filename : filename,
mode : mode.to_lowercase(),
logged : LoggerFlags::new(),
}
}
pub fn is_mode_ok(&self) -> bool {
match self.mode.as_str() {
"netascii" | "mail" | "octet" => true,
_ => false
}
}
}
#[no_mangle]
pub extern "C" fn rs_tftp_state_alloc() -> *mut libc::c_void {
let state = TFTPState { transactions : Vec::new() };
let boxed = Box::new(state);
return unsafe{transmute(boxed)};
}
#[no_mangle]
pub extern "C" fn rs_tftp_state_free(state: *mut libc::c_void) {
let _state : Box<TFTPState> = unsafe{transmute(state)};
}
#[no_mangle]
pub extern "C" fn rs_tftp_state_tx_free(state: &mut TFTPState,
tx_id: libc::uint32_t) {
state.transactions.remove(tx_id as usize);
}
#[no_mangle]
pub extern "C" fn rs_tftp_get_tx(state: &mut TFTPState,
tx_id: libc::uint64_t) -> *mut libc::c_void {
if state.transactions.len() <= tx_id as usize {
return std::ptr::null_mut();
}
return unsafe{transmute(&state.transactions[tx_id as usize])};
}
#[no_mangle]
pub extern "C" fn rs_tftp_get_tx_logged(_state: &mut TFTPState,
tx: &mut TFTPTransaction,
logger: libc::uint32_t) -> i8 {
if tx.logged.is_logged(logger) {
1
} else {
0
}
}
#[no_mangle]
pub extern "C" fn rs_tftp_set_tx_logged(_state: &mut TFTPState,
tx: &mut TFTPTransaction,
logger: libc::uint32_t) {
tx.logged.set_logged(logger);
}
#[no_mangle]
pub extern "C" fn rs_tftp_has_event(state: &mut TFTPState) -> i64 {
return state.transactions.len() as i64;
}
#[no_mangle]
pub extern "C" fn rs_tftp_get_tx_cnt(state: &mut TFTPState) -> u64 {
return state.transactions.len() as u64;
}
named!(getstr<&str>, map_res!(
take_while!(call!(|c| c != 0)),
str::from_utf8
)
);
named!(pub tftp_request<TFTPTransaction>,
do_parse!(
tag!([0]) >>
opcode: take!(1) >>
filename: getstr >>
tag!([0]) >>
mode : getstr >>
(
TFTPTransaction::new(opcode[0], String::from(filename), String::from(mode))
)
)
);
#[no_mangle]
pub extern "C" fn rs_tftp_request(state: &mut TFTPState,
input: *const libc::uint8_t,
len: libc::uint32_t) -> i64 {
let buf = unsafe{std::slice::from_raw_parts(input, len as usize)};
return match tftp_request(buf) {
nom::IResult::Done(_, rqst) => {
state.transactions.push(rqst);
1
},
_ => 0
}
}

@ -44,6 +44,7 @@ app-layer-nfs-tcp.c app-layer-nfs-tcp.h \
app-layer-nfs-udp.c app-layer-nfs-udp.h \
app-layer-ntp.c app-layer-ntp.h \
app-layer-register.c app-layer-register.h \
app-layer-tftp.c app-layer-tftp.h \
app-layer-template.c app-layer-template.h \
app-layer-ssh.c app-layer-ssh.h \
app-layer-ssl.c app-layer-ssl.h \
@ -308,6 +309,7 @@ output-json-ssh.c output-json-ssh.h \
output-json-stats.c output-json-stats.h \
output-json-tls.c output-json-tls.h \
output-json-nfs.c output-json-nfs.h \
output-json-tftp.c output-json-tftp.h \
output-json-template.c output-json-template.h \
output-json-vars.c output-json-vars.h \
output-lua.c output-lua.h \

@ -723,6 +723,8 @@ static void AppLayerProtoDetectPrintProbingParsers(AppLayerProtoDetectProbingPar
printf(" alproto: ALPROTO_NFS\n");
else if (pp_pe->alproto == ALPROTO_NTP)
printf(" alproto: ALPROTO_NTP\n");
else if (pp_pe->alproto == ALPROTO_TFTP)
printf(" alproto: ALPROTO_TFTP\n");
else if (pp_pe->alproto == ALPROTO_TEMPLATE)
printf(" alproto: ALPROTO_TEMPLATE\n");
else if (pp_pe->alproto == ALPROTO_DNP3)
@ -786,6 +788,8 @@ static void AppLayerProtoDetectPrintProbingParsers(AppLayerProtoDetectProbingPar
printf(" alproto: ALPROTO_NFS\n");
else if (pp_pe->alproto == ALPROTO_NTP)
printf(" alproto: ALPROTO_NTP\n");
else if (pp_pe->alproto == ALPROTO_TFTP)
printf(" alproto: ALPROTO_TFTP\n");
else if (pp_pe->alproto == ALPROTO_TEMPLATE)
printf(" alproto: ALPROTO_TEMPLATE\n");
else if (pp_pe->alproto == ALPROTO_DNP3)

@ -63,6 +63,7 @@
#include "app-layer-nfs-tcp.h"
#include "app-layer-nfs-udp.h"
#include "app-layer-ntp.h"
#include "app-layer-tftp.h"
#include "app-layer-template.h"
#include "conf.h"
@ -1389,6 +1390,7 @@ void AppLayerParserRegisterProtocolParsers(void)
RegisterNFSTCPParsers();
RegisterNFSUDPParsers();
RegisterNTPParsers();
RegisterTFTPParsers();
RegisterTemplateParsers();
/** IMAP */

@ -89,6 +89,8 @@ const char *AppProtoToString(AppProto alproto)
break;
case ALPROTO_FTPDATA:
proto_name = "ftp-data";
case ALPROTO_TFTP:
proto_name = "tftp";
break;
case ALPROTO_TEMPLATE:
proto_name = "template";

@ -47,6 +47,7 @@ enum AppProtoEnum {
ALPROTO_NFS,
ALPROTO_NTP,
ALPROTO_FTPDATA,
ALPROTO_TFTP,
ALPROTO_TEMPLATE,
/* used by the probing parser when alproto detection fails

@ -0,0 +1,331 @@
/* Copyright (C) 2017 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.
*
*/
/**
* \file
*
* \author Clément Galland <clement.galland@epita.fr>
*
* Parser for NTP application layer running on UDP port 69.
*/
#include "suricata-common.h"
#include "stream.h"
#include "conf.h"
#include "util-unittest.h"
#include "app-layer-detect-proto.h"
#include "app-layer-parser.h"
#include "app-layer-tftp.h"
#ifndef HAVE_RUST
void RegisterTFTPParsers(void)
{
}
#else
#include "rust-tftp-tftp-gen.h"
/* The default port to probe if not provided in the configuration file. */
#define TFTP_DEFAULT_PORT "69"
/* The minimum size for an message. For some protocols this might
* be the size of a header. */
#define TFTP_MIN_FRAME_LEN 4
/* Enum of app-layer events for an echo protocol. Normally you might
* have events for errors in parsing data, like unexpected data being
* received. For echo we'll make something up, and log an app-layer
* level alert if an empty message is received.
*
* Example rule:
*
* alert tftp any any -> any any (msg:"SURICATA TFTP empty message"; \
* app-layer-event:tftp.empty_message; sid:X; rev:Y;)
*/
enum {
TFTP_DECODER_EVENT_EMPTY_MESSAGE,
};
SCEnumCharMap tftp_decoder_event_table[] = {
{"EMPTY_MESSAGE", TFTP_DECODER_EVENT_EMPTY_MESSAGE},
// event table must be NULL-terminated
{ NULL, -1 },
};
static void *TFTPStateAlloc(void)
{
return rs_tftp_state_alloc();
}
static void TFTPStateFree(void *state)
{
rs_tftp_state_free(state);
}
/**
* \brief Callback from the application layer to have a transaction freed.
*
* \param state a void pointer to the TFTPState object.
* \param tx_id the transaction ID to free.
*/
static void TFTPStateTxFree(void *state, uint64_t tx_id)
{
rs_tftp_state_tx_free(state, tx_id);
}
static int TFTPStateGetEventInfo(const char *event_name, int *event_id,
AppLayerEventType *event_type)
{
return -1;
}
static AppLayerDecoderEvents *TFTPGetEvents(void *state, uint64_t tx_id)
{
return NULL;
}
static int TFTPHasEvents(void *state)
{
return rs_tftp_has_event(state);
}
/**
* \brief Probe the input to see if it looks like echo.
*
* \retval ALPROTO_TFTP if it looks like echo, otherwise
* ALPROTO_UNKNOWN.
*/
static AppProto TFTPProbingParser(Flow *f, uint8_t *input, uint32_t input_len,
uint32_t *offset)
{
/* Very simple test - if there is input, this is echo.
* Also check if it's starting by a zero */
if (input_len >= TFTP_MIN_FRAME_LEN && *input == 0) {
SCLogDebug("Detected as ALPROTO_TFTP.");
return ALPROTO_TFTP;
}
SCLogDebug("Protocol not detected as ALPROTO_TFTP.");
return ALPROTO_UNKNOWN;
}
static int TFTPParseRequest(Flow *f, void *state,
AppLayerParserState *pstate, uint8_t *input, uint32_t input_len,
void *local_data)
{
SCLogDebug("Parsing echo request: len=%"PRIu32, input_len);
/* Likely connection closed, we can just return here. */
if ((input == NULL || input_len == 0) &&
AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF)) {
return 0;
}
/* Probably don't want to create a transaction in this case
* either. */
if (input == NULL || input_len == 0) {
return 0;
}
return rs_tftp_request(state, input, input_len);
}
/**
* \brief Response parsing is not implemented
*/
static int TFTPParseResponse(Flow *f, void *state, AppLayerParserState *pstate,
uint8_t *input, uint32_t input_len, void *local_data)
{
return 0;
}
static uint64_t TFTPGetTxCnt(void *state)
{
return rs_tftp_get_tx_cnt(state);
}
static void *TFTPGetTx(void *state, uint64_t tx_id)
{
return rs_tftp_get_tx(state, tx_id);
}
static void TFTPSetTxLogged(void *state, void *vtx, uint32_t logger)
{
rs_tftp_set_tx_logged(state, vtx, logger);
}
static int TFTPGetTxLogged(void *state, void *vtx, uint32_t logger)
{
return rs_tftp_get_tx_logged(state, vtx, logger);
}
/**
* \brief Called by the application layer.
*
* In most cases 1 can be returned here.
*/
static int TFTPGetAlstateProgressCompletionStatus(uint8_t direction) {
return 1;
}
/**
* \brief Return the state of a transaction in a given direction.
*
* In the case of the echo protocol, the existence of a transaction
* means that the request is done. However, some protocols that may
* need multiple chunks of data to complete the request may need more
* than just the existence of a transaction for the request to be
* considered complete.
*
* For the response to be considered done, the response for a request
* needs to be seen. The response_done flag is set on response for
* checking here.
*/
static int TFTPGetStateProgress(void *tx, uint8_t direction)
{
return 1;
}
static DetectEngineState *TFTPGetTxDetectState(void *vtx)
{
return NULL;
}
static int TFTPSetTxDetectState(void *state, void *vtx,
DetectEngineState *s)
{
return 0;
}
void RegisterTFTPParsers(void)
{
const char *proto_name = "tftp";
/* Check if TFTP UDP detection is enabled. If it does not exist in
* the configuration file then it will be enabled by default. */
if (AppLayerProtoDetectConfProtoDetectionEnabled("udp", proto_name)) {
SCLogDebug("TFTP UDP protocol detection enabled.");
AppLayerProtoDetectRegisterProtocol(ALPROTO_TFTP, proto_name);
if (RunmodeIsUnittests()) {
SCLogDebug("Unittest mode, registeringd default configuration.");
AppLayerProtoDetectPPRegister(IPPROTO_UDP, TFTP_DEFAULT_PORT,
ALPROTO_TFTP, 0, TFTP_MIN_FRAME_LEN,
STREAM_TOSERVER, TFTPProbingParser,
NULL);
} else {
if (!AppLayerProtoDetectPPParseConfPorts("udp", IPPROTO_UDP,
proto_name, ALPROTO_TFTP,
0, TFTP_MIN_FRAME_LEN,
TFTPProbingParser, NULL)) {
SCLogDebug("No echo app-layer configuration, enabling echo"
" detection UDP detection on port %s.",
TFTP_DEFAULT_PORT);
AppLayerProtoDetectPPRegister(IPPROTO_UDP,
TFTP_DEFAULT_PORT, ALPROTO_TFTP,
0, TFTP_MIN_FRAME_LEN,
STREAM_TOSERVER,TFTPProbingParser,
NULL);
}
}
} else {
SCLogDebug("Protocol detecter and parser disabled for TFTP.");
return;
}
if (AppLayerParserConfParserEnabled("udp", proto_name)) {
SCLogDebug("Registering TFTP protocol parser.");
/* Register functions for state allocation and freeing. A
* state is allocated for every new TFTP flow. */
AppLayerParserRegisterStateFuncs(IPPROTO_UDP, ALPROTO_TFTP,
TFTPStateAlloc, TFTPStateFree);
/* Register request parser for parsing frame from server to client. */
AppLayerParserRegisterParser(IPPROTO_UDP, ALPROTO_TFTP,
STREAM_TOSERVER, TFTPParseRequest);
/* Register response parser for parsing frames from server to client. */
AppLayerParserRegisterParser(IPPROTO_UDP, ALPROTO_TFTP,
STREAM_TOCLIENT, TFTPParseResponse);
/* Register a function to be called by the application layer
* when a transaction is to be freed. */
AppLayerParserRegisterTxFreeFunc(IPPROTO_UDP, ALPROTO_TFTP,
TFTPStateTxFree);
AppLayerParserRegisterLoggerFuncs(IPPROTO_UDP, ALPROTO_TFTP,
TFTPGetTxLogged, TFTPSetTxLogged);
/* Register a function to return the current transaction count. */
AppLayerParserRegisterGetTxCnt(IPPROTO_UDP, ALPROTO_TFTP,
TFTPGetTxCnt);
/* Transaction handling. */
AppLayerParserRegisterGetStateProgressCompletionStatus(ALPROTO_TFTP,
TFTPGetAlstateProgressCompletionStatus);
AppLayerParserRegisterGetStateProgressFunc(IPPROTO_UDP,
ALPROTO_TFTP,
TFTPGetStateProgress);
AppLayerParserRegisterGetTx(IPPROTO_UDP, ALPROTO_TFTP,
TFTPGetTx);
/* Application layer event handling. */
AppLayerParserRegisterHasEventsFunc(IPPROTO_UDP, ALPROTO_TFTP,
TFTPHasEvents);
/* What is this being registered for? */
AppLayerParserRegisterDetectStateFuncs(IPPROTO_UDP, ALPROTO_TFTP,
NULL, TFTPGetTxDetectState,
TFTPSetTxDetectState);
AppLayerParserRegisterGetEventInfo(IPPROTO_UDP, ALPROTO_TFTP,
TFTPStateGetEventInfo);
AppLayerParserRegisterGetEventsFunc(IPPROTO_UDP, ALPROTO_TFTP,
TFTPGetEvents);
}
else {
SCLogDebug("TFTP protocol parsing disabled.");
}
#ifdef UNITTESTS
AppLayerParserRegisterProtocolUnittests(IPPROTO_UDP, ALPROTO_TFTP,
TFTPParserRegisterTests);
#endif
}
#ifdef UNITTESTS
#endif
void TFTPParserRegisterTests(void)
{
#ifdef UNITTESTS
#endif
}
#endif /* HAVE_RUST */

@ -0,0 +1,38 @@
/* Copyright (C) 2017 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.
*/
/**
* \file
*
* \author Clément Galland <clement.galland@epita.fr>
*/
#ifndef __APP_LAYER_TFTP_H__
#define __APP_LAYER_TFTP_H__
#include "detect-engine-state.h"
#include "queue.h"
void RegisterTFTPParsers(void);
void TFTPParserRegisterTests(void);
/** Opaque Rust types. */
typedef struct TFTPState_ TFTPState;
typedef struct TFTPTransaction_ TFTPTransaction;
#endif /* __APP_LAYER_TFTP_H__ */

@ -0,0 +1,197 @@
/* Copyright (C) 2017 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.
*/
/**
* \file
*
* \author Clément Galland <clement.galland@epita.fr>
*
* Implement JSON/eve logging app-layer TFTP.
*/
//#ifdef HAVE_RUST
#include "suricata-common.h"
#include "debug.h"
#include "detect.h"
#include "pkt-var.h"
#include "conf.h"
#include "threads.h"
#include "threadvars.h"
#include "tm-threads.h"
#include "util-unittest.h"
#include "util-buffer.h"
#include "util-debug.h"
#include "util-byte.h"
#include "output.h"
#include "output-json.h"
#include "app-layer.h"
#include "app-layer-parser.h"
#include "app-layer-tftp.h"
#include "output-json-tftp.h"
#ifdef HAVE_RUST
#include "rust.h"
#include "rust-tftp-log-gen.h"
#ifdef HAVE_LIBJANSSON
typedef struct LogTFTPFileCtx_ {
LogFileCtx *file_ctx;
uint32_t flags;
} LogTFTPFileCtx;
typedef struct LogTFTPLogThread_ {
LogTFTPFileCtx *tftplog_ctx;
uint32_t count;
MemBuffer *buffer;
} LogTFTPLogThread;
static int JsonTFTPLogger(ThreadVars *tv, void *thread_data,
const Packet *p, Flow *f, void *state, void *tx, uint64_t tx_id)
{
LogTFTPLogThread *thread = thread_data;
json_t *js, *tftpjs;
js = CreateJSONHeader((Packet *)p, 0, "tftp");
if (unlikely(js == NULL)) {
return TM_ECODE_FAILED;
}
tftpjs = rs_tftp_log_json_request(tx);
if (unlikely(tftpjs == NULL)) {
goto error;
}
json_object_set_new(js, "tftp", tftpjs);
MemBufferReset(thread->buffer);
OutputJSONBuffer(js, thread->tftplog_ctx->file_ctx, &thread->buffer);
json_decref(js);
return TM_ECODE_OK;
error:
json_decref(js);
return TM_ECODE_FAILED;
}
static void OutputTFTPLogDeInitCtxSub(OutputCtx *output_ctx)
{
LogTFTPFileCtx *tftplog_ctx = (LogTFTPFileCtx *)output_ctx->data;
SCFree(tftplog_ctx);
SCFree(output_ctx);
}
static OutputCtx *OutputTFTPLogInitSub(ConfNode *conf,
OutputCtx *parent_ctx)
{
OutputJsonCtx *ajt = parent_ctx->data;
LogTFTPFileCtx *tftplog_ctx = SCCalloc(1, sizeof(*tftplog_ctx));
if (unlikely(tftplog_ctx == NULL)) {
return NULL;
}
tftplog_ctx->file_ctx = ajt->file_ctx;
OutputCtx *output_ctx = SCCalloc(1, sizeof(*output_ctx));
if (unlikely(output_ctx == NULL)) {
SCFree(tftplog_ctx);
return NULL;
}
output_ctx->data = tftplog_ctx;
output_ctx->DeInit = OutputTFTPLogDeInitCtxSub;
SCLogDebug("TFTP log sub-module initialized.");
AppLayerParserRegisterLogger(IPPROTO_UDP, ALPROTO_TFTP);
return output_ctx;
}
#define OUTPUT_BUFFER_SIZE 65535
static TmEcode JsonTFTPLogThreadInit(ThreadVars *t, const void *initdata, void **data)
{
LogTFTPLogThread *thread = SCCalloc(1, sizeof(*thread));
if (unlikely(thread == NULL)) {
return TM_ECODE_FAILED;
}
if (initdata == NULL) {
SCLogDebug("Error getting context for EveLogTFTP. \"initdata\" is NULL.");
SCFree(thread);
return TM_ECODE_FAILED;
}
thread->buffer = MemBufferCreateNew(OUTPUT_BUFFER_SIZE);
if (unlikely(thread->buffer == NULL)) {
SCFree(thread);
return TM_ECODE_FAILED;
}
thread->tftplog_ctx = ((OutputCtx *)initdata)->data;
*data = (void *)thread;
return TM_ECODE_OK;
}
static TmEcode JsonTFTPLogThreadDeinit(ThreadVars *t, void *data)
{
LogTFTPLogThread *thread = (LogTFTPLogThread *)data;
if (thread == NULL) {
return TM_ECODE_OK;
}
if (thread->buffer != NULL) {
MemBufferFree(thread->buffer);
}
SCFree(thread);
return TM_ECODE_OK;
}
void JsonTFTPLogRegister(void)
{
/* Register as an eve sub-module. */
OutputRegisterTxSubModule(LOGGER_JSON_TFTP, "eve-log", "JsonTFTPLog",
"eve-log.tftp", OutputTFTPLogInitSub,
ALPROTO_TFTP, JsonTFTPLogger,
JsonTFTPLogThreadInit, JsonTFTPLogThreadDeinit,
NULL);
SCLogDebug("TFTP JSON logger registered.");
}
#else /* HAVE_RUST */
void JsonTFTPLogRegister(void)
{
}
#endif /* HAVE_RUST */
#else /* HAVE_LIBJANSSON */
void JsonTFTPLogRegister(void)
{
}
#endif /* HAVE_LIBJANSSON */

@ -0,0 +1,29 @@
/* Copyright (C) 2017 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.
*/
/**
* \file
*
* \author Clément Galland <clement.galland@epita.fr>
*/
#ifndef __OUTPUT_JSON_TFTP_H__
#define __OUTPUT_JSON_TFTP_H__
void JsonTFTPLogRegister(void);
#endif /* __OUTPUT_JSON_TFTP_H__ */

@ -69,6 +69,7 @@
#include "log-stats.h"
#include "output-json.h"
#include "output-json-nfs.h"
#include "output-json-tftp.h"
#include "output-json-template.h"
#include "output-lua.h"
#include "output-json-dnp3.h"
@ -1089,6 +1090,8 @@ void OutputRegisterLoggers(void)
/* NFS JSON logger. */
JsonNFSLogRegister();
/* TFTP JSON logger. */
JsonTFTPLogRegister();
/* Template JSON logger. */
JsonTemplateLogRegister();
}

@ -408,6 +408,7 @@ typedef enum {
LOGGER_JSON_SMTP,
LOGGER_JSON_TLS,
LOGGER_JSON_NFS,
LOGGER_JSON_TFTP,
LOGGER_JSON_DNP3_TS,
LOGGER_JSON_DNP3_TC,
LOGGER_JSON_SSH,

Loading…
Cancel
Save