diff options
Diffstat (limited to 'framework/src/suricata/src/output-json-alert.c')
-rw-r--r-- | framework/src/suricata/src/output-json-alert.c | 700 |
1 files changed, 0 insertions, 700 deletions
diff --git a/framework/src/suricata/src/output-json-alert.c b/framework/src/suricata/src/output-json-alert.c deleted file mode 100644 index 2c0d0171..00000000 --- a/framework/src/suricata/src/output-json-alert.c +++ /dev/null @@ -1,700 +0,0 @@ -/* Copyright (C) 2013-2014 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 Tom DeCanio <td@npulsetech.com> - * - * Logs alerts in JSON format. - * - */ - -#include "suricata-common.h" -#include "debug.h" -#include "detect.h" -#include "flow.h" -#include "conf.h" - -#include "threads.h" -#include "tm-threads.h" -#include "threadvars.h" -#include "util-debug.h" - -#include "util-unittest.h" -#include "util-unittest-helper.h" - -#include "detect.h" -#include "detect-parse.h" -#include "detect-engine.h" -#include "detect-engine-mpm.h" -#include "detect-reference.h" -#include "app-layer-parser.h" -#include "app-layer-htp.h" -#include "app-layer-htp-xff.h" -#include "util-classification-config.h" -#include "util-syslog.h" -#include "util-logopenfile.h" - -#include "output.h" -#include "output-json.h" -#include "output-json-http.h" -#include "output-json-tls.h" -#include "output-json-ssh.h" -#include "output-json-smtp.h" -#include "output-json-email-common.h" - -#include "util-byte.h" -#include "util-privs.h" -#include "util-print.h" -#include "util-proto-name.h" -#include "util-optimize.h" -#include "util-buffer.h" -#include "util-crypt.h" - -#define MODULE_NAME "JsonAlertLog" - -#ifdef HAVE_LIBJANSSON - -#define LOG_JSON_PAYLOAD 1 -#define LOG_JSON_PACKET 2 -#define LOG_JSON_PAYLOAD_BASE64 4 -#define LOG_JSON_HTTP 8 -#define LOG_JSON_TLS 16 -#define LOG_JSON_SSH 32 -#define LOG_JSON_SMTP 64 - -#define JSON_STREAM_BUFFER_SIZE 4096 - -typedef struct AlertJsonOutputCtx_ { - LogFileCtx* file_ctx; - uint8_t flags; - HttpXFFCfg *xff_cfg; -} AlertJsonOutputCtx; - -typedef struct JsonAlertLogThread_ { - /** LogFileCtx has the pointer to the file and a mutex to allow multithreading */ - LogFileCtx* file_ctx; - MemBuffer *json_buffer; - MemBuffer *payload_buffer; - AlertJsonOutputCtx* json_output_ctx; -} JsonAlertLogThread; - -/* Callback function to pack payload contents from a stream into a buffer - * so we can report them in JSON output. */ -static int AlertJsonDumpStreamSegmentCallback(const Packet *p, void *data, uint8_t *buf, uint32_t buflen) -{ - MemBuffer *payload = (MemBuffer *)data; - MemBufferWriteRaw(payload, buf, buflen); - - return 1; -} - -static void AlertJsonTls(const Flow *f, json_t *js) -{ - SSLState *ssl_state = (SSLState *)FlowGetAppState(f); - if (ssl_state) { - json_t *tjs = json_object(); - if (unlikely(tjs == NULL)) - return; - - JsonTlsLogJSONBasic(tjs, ssl_state); - JsonTlsLogJSONExtended(tjs, ssl_state); - - json_object_set_new(js, "tls", tjs); - } - - return; -} - -static void AlertJsonSsh(const Flow *f, json_t *js) -{ - SshState *ssh_state = (SshState *)FlowGetAppState(f); - if (ssh_state) { - json_t *tjs = json_object(); - if (unlikely(tjs == NULL)) - return; - - JsonSshLogJSON(tjs, ssh_state); - - json_object_set_new(js, "ssh", tjs); - } - - return; -} - -void AlertJsonHeader(const Packet *p, const PacketAlert *pa, json_t *js) -{ - char *action = "allowed"; - if (pa->action & (ACTION_REJECT|ACTION_REJECT_DST|ACTION_REJECT_BOTH)) { - action = "blocked"; - } else if ((pa->action & ACTION_DROP) && EngineModeIsIPS()) { - action = "blocked"; - } - - /* Add tx_id to root element for correlation with other events. */ - json_object_del(js, "tx_id"); - if (pa->flags & PACKET_ALERT_FLAG_TX) - json_object_set_new(js, "tx_id", json_integer(pa->tx_id)); - - json_t *ajs = json_object(); - if (ajs == NULL) { - json_decref(js); - return; - } - - json_object_set_new(ajs, "action", json_string(action)); - json_object_set_new(ajs, "gid", json_integer(pa->s->gid)); - json_object_set_new(ajs, "signature_id", json_integer(pa->s->id)); - json_object_set_new(ajs, "rev", json_integer(pa->s->rev)); - json_object_set_new(ajs, "signature", - json_string((pa->s->msg) ? pa->s->msg : "")); - json_object_set_new(ajs, "category", - json_string((pa->s->class_msg) ? pa->s->class_msg : "")); - json_object_set_new(ajs, "severity", json_integer(pa->s->prio)); - - if (p->tenant_id > 0) - json_object_set_new(ajs, "tenant_id", json_integer(p->tenant_id)); - - /* alert */ - json_object_set_new(js, "alert", ajs); -} - -static int AlertJson(ThreadVars *tv, JsonAlertLogThread *aft, const Packet *p) -{ - MemBuffer *payload = aft->payload_buffer; - AlertJsonOutputCtx *json_output_ctx = aft->json_output_ctx; - json_t *hjs = NULL; - - int i; - - if (p->alerts.cnt == 0) - return TM_ECODE_OK; - - json_t *js = CreateJSONHeader((Packet *)p, 0, "alert"); - if (unlikely(js == NULL)) - return TM_ECODE_OK; - - for (i = 0; i < p->alerts.cnt; i++) { - const PacketAlert *pa = &p->alerts.alerts[i]; - if (unlikely(pa->s == NULL)) { - continue; - } - - MemBufferReset(aft->json_buffer); - - /* alert */ - AlertJsonHeader(p, pa, js); - - if (json_output_ctx->flags & LOG_JSON_HTTP) { - if (p->flow != NULL) { - FLOWLOCK_RDLOCK(p->flow); - uint16_t proto = FlowGetAppProtocol(p->flow); - - /* http alert */ - if (proto == ALPROTO_HTTP) { - hjs = JsonHttpAddMetadata(p->flow, pa->tx_id); - if (hjs) - json_object_set_new(js, "http", hjs); - } - - FLOWLOCK_UNLOCK(p->flow); - } - } - - if (json_output_ctx->flags & LOG_JSON_TLS) { - if (p->flow != NULL) { - FLOWLOCK_RDLOCK(p->flow); - uint16_t proto = FlowGetAppProtocol(p->flow); - - /* http alert */ - if (proto == ALPROTO_TLS) - AlertJsonTls(p->flow, js); - - FLOWLOCK_UNLOCK(p->flow); - } - } - - if (json_output_ctx->flags & LOG_JSON_SSH) { - if (p->flow != NULL) { - FLOWLOCK_RDLOCK(p->flow); - uint16_t proto = FlowGetAppProtocol(p->flow); - - /* http alert */ - if (proto == ALPROTO_SSH) - AlertJsonSsh(p->flow, js); - - FLOWLOCK_UNLOCK(p->flow); - } - } - - if (json_output_ctx->flags & LOG_JSON_SMTP) { - if (p->flow != NULL) { - FLOWLOCK_RDLOCK(p->flow); - uint16_t proto = FlowGetAppProtocol(p->flow); - - /* http alert */ - if (proto == ALPROTO_SMTP) { - hjs = JsonSMTPAddMetadata(p->flow, pa->tx_id); - if (hjs) - json_object_set_new(js, "smtp", hjs); - - hjs = JsonEmailAddMetadata(p->flow, pa->tx_id); - if (hjs) - json_object_set_new(js, "email", hjs); - } - - FLOWLOCK_UNLOCK(p->flow); - } - } - - /* payload */ - if (json_output_ctx->flags & (LOG_JSON_PAYLOAD | LOG_JSON_PAYLOAD_BASE64)) { - int stream = (p->proto == IPPROTO_TCP) ? - (pa->flags & (PACKET_ALERT_FLAG_STATE_MATCH | PACKET_ALERT_FLAG_STREAM_MATCH) ? - 1 : 0) : 0; - - /* Is this a stream? If so, pack part of it into the payload field */ - if (stream) { - uint8_t flag; - - MemBufferReset(payload); - - if (!EngineModeIsIPS()) { - if (p->flowflags & FLOW_PKT_TOSERVER) { - flag = FLOW_PKT_TOCLIENT; - } else { - flag = FLOW_PKT_TOSERVER; - } - } else { - if (p->flowflags & FLOW_PKT_TOSERVER) { - flag = FLOW_PKT_TOSERVER; - } else { - flag = FLOW_PKT_TOCLIENT; - } - } - - StreamSegmentForEach((const Packet *)p, flag, - AlertJsonDumpStreamSegmentCallback, - (void *)payload); - - if (json_output_ctx->flags & LOG_JSON_PAYLOAD_BASE64) { - unsigned long len = JSON_STREAM_BUFFER_SIZE * 2; - uint8_t encoded[len]; - Base64Encode(payload->buffer, payload->offset, encoded, &len); - json_object_set_new(js, "payload", json_string((char *)encoded)); - } - - if (json_output_ctx->flags & LOG_JSON_PAYLOAD) { - uint8_t printable_buf[payload->offset + 1]; - uint32_t offset = 0; - PrintStringsToBuffer(printable_buf, &offset, - sizeof(printable_buf), - payload->buffer, payload->offset); - json_object_set_new(js, "payload_printable", - json_string((char *)printable_buf)); - } - } else { - /* This is a single packet and not a stream */ - if (json_output_ctx->flags & LOG_JSON_PAYLOAD_BASE64) { - unsigned long len = p->payload_len * 2 + 1; - uint8_t encoded[len]; - Base64Encode(p->payload, p->payload_len, encoded, &len); - json_object_set_new(js, "payload", json_string((char *)encoded)); - } - - if (json_output_ctx->flags & LOG_JSON_PAYLOAD) { - uint8_t printable_buf[p->payload_len + 1]; - uint32_t offset = 0; - PrintStringsToBuffer(printable_buf, &offset, - p->payload_len + 1, - p->payload, p->payload_len); - json_object_set_new(js, "payload_printable", json_string((char *)printable_buf)); - } - } - - json_object_set_new(js, "stream", json_integer(stream)); - } - - /* base64-encoded full packet */ - if (json_output_ctx->flags & LOG_JSON_PACKET) { - unsigned long len = GET_PKT_LEN(p) * 2; - uint8_t encoded_packet[len]; - Base64Encode((unsigned char*) GET_PKT_DATA(p), GET_PKT_LEN(p), encoded_packet, &len); - json_object_set_new(js, "packet", json_string((char *)encoded_packet)); - } - - HttpXFFCfg *xff_cfg = json_output_ctx->xff_cfg; - - /* xff header */ - if (!(xff_cfg->flags & XFF_DISABLED) && p->flow != NULL) { - int have_xff_ip = 0; - char buffer[XFF_MAXLEN]; - - FLOWLOCK_RDLOCK(p->flow); - if (FlowGetAppProtocol(p->flow) == ALPROTO_HTTP) { - if (pa->flags & PACKET_ALERT_FLAG_TX) { - have_xff_ip = HttpXFFGetIPFromTx(p, pa->tx_id, xff_cfg, buffer, XFF_MAXLEN); - } else { - have_xff_ip = HttpXFFGetIP(p, xff_cfg, buffer, XFF_MAXLEN); - } - } - FLOWLOCK_UNLOCK(p->flow); - - if (have_xff_ip) { - if (xff_cfg->flags & XFF_EXTRADATA) { - json_object_set_new(js, "xff", json_string(buffer)); - } - else if (xff_cfg->flags & XFF_OVERWRITE) { - if (p->flowflags & FLOW_PKT_TOCLIENT) { - json_object_set(js, "dest_ip", json_string(buffer)); - } else { - json_object_set(js, "src_ip", json_string(buffer)); - } - } - } - } - - OutputJSONBuffer(js, aft->file_ctx, aft->json_buffer); - json_object_del(js, "alert"); - } - json_object_clear(js); - json_decref(js); - - return TM_ECODE_OK; -} - -static int AlertJsonDecoderEvent(ThreadVars *tv, JsonAlertLogThread *aft, const Packet *p) -{ - MemBuffer *buffer = (MemBuffer *)aft->json_buffer; - int i; - char timebuf[64]; - json_t *js; - - if (p->alerts.cnt == 0) - return TM_ECODE_OK; - - CreateIsoTimeString(&p->ts, timebuf, sizeof(timebuf)); - - for (i = 0; i < p->alerts.cnt; i++) { - MemBufferReset(buffer); - - const PacketAlert *pa = &p->alerts.alerts[i]; - if (unlikely(pa->s == NULL)) { - continue; - } - - char *action = "allowed"; - if (pa->action & (ACTION_REJECT|ACTION_REJECT_DST|ACTION_REJECT_BOTH)) { - action = "blocked"; - } else if ((pa->action & ACTION_DROP) && EngineModeIsIPS()) { - action = "blocked"; - } - - char buf[(32 * 3) + 1]; - PrintRawLineHexBuf(buf, sizeof(buf), GET_PKT_DATA(p), GET_PKT_LEN(p) < 32 ? GET_PKT_LEN(p) : 32); - - js = json_object(); - if (js == NULL) - return TM_ECODE_OK; - - json_t *ajs = json_object(); - if (ajs == NULL) { - json_decref(js); - return TM_ECODE_OK; - } - - /* time & tx */ - json_object_set_new(js, "timestamp", json_string(timebuf)); - - /* tuple */ - //json_object_set_new(js, "srcip", json_string(srcip)); - //json_object_set_new(js, "sp", json_integer(p->sp)); - //json_object_set_new(js, "dstip", json_string(dstip)); - //json_object_set_new(js, "dp", json_integer(p->dp)); - //json_object_set_new(js, "proto", json_integer(proto)); - - json_object_set_new(ajs, "action", json_string(action)); - json_object_set_new(ajs, "gid", json_integer(pa->s->gid)); - json_object_set_new(ajs, "signature_id", json_integer(pa->s->id)); - json_object_set_new(ajs, "rev", json_integer(pa->s->rev)); - json_object_set_new(ajs, "signature", - json_string((pa->s->msg) ? pa->s->msg : "")); - json_object_set_new(ajs, "category", - json_string((pa->s->class_msg) ? pa->s->class_msg : "")); - json_object_set_new(ajs, "severity", json_integer(pa->s->prio)); - - if (p->tenant_id > 0) - json_object_set_new(ajs, "tenant_id", json_integer(p->tenant_id)); - - /* alert */ - json_object_set_new(js, "alert", ajs); - OutputJSONBuffer(js, aft->file_ctx, buffer); - json_object_clear(js); - json_decref(js); - } - - return TM_ECODE_OK; -} - -static int JsonAlertLogger(ThreadVars *tv, void *thread_data, const Packet *p) -{ - JsonAlertLogThread *aft = thread_data; - - if (PKT_IS_IPV4(p) || PKT_IS_IPV6(p)) { - return AlertJson(tv, aft, p); - } else if (p->alerts.cnt > 0) { - return AlertJsonDecoderEvent(tv, aft, p); - } - return 0; -} - -static int JsonAlertLogCondition(ThreadVars *tv, const Packet *p) -{ - return (p->alerts.cnt ? TRUE : FALSE); -} - -#define OUTPUT_BUFFER_SIZE 65535 -static TmEcode JsonAlertLogThreadInit(ThreadVars *t, void *initdata, void **data) -{ - JsonAlertLogThread *aft = SCMalloc(sizeof(JsonAlertLogThread)); - if (unlikely(aft == NULL)) - return TM_ECODE_FAILED; - memset(aft, 0, sizeof(JsonAlertLogThread)); - if(initdata == NULL) - { - SCLogDebug("Error getting context for AlertFastLog. \"initdata\" argument NULL"); - SCFree(aft); - return TM_ECODE_FAILED; - } - - aft->json_buffer = MemBufferCreateNew(OUTPUT_BUFFER_SIZE); - if (aft->json_buffer == NULL) { - SCFree(aft); - return TM_ECODE_FAILED; - } - - aft->payload_buffer = MemBufferCreateNew(JSON_STREAM_BUFFER_SIZE); - if (aft->payload_buffer == NULL) { - SCFree(aft); - return TM_ECODE_FAILED; - } - - /** Use the Output Context (file pointer and mutex) */ - AlertJsonOutputCtx *json_output_ctx = ((OutputCtx *)initdata)->data; - aft->file_ctx = json_output_ctx->file_ctx; - aft->json_output_ctx = json_output_ctx; - - *data = (void *)aft; - return TM_ECODE_OK; -} - -static TmEcode JsonAlertLogThreadDeinit(ThreadVars *t, void *data) -{ - JsonAlertLogThread *aft = (JsonAlertLogThread *)data; - if (aft == NULL) { - return TM_ECODE_OK; - } - - MemBufferFree(aft->json_buffer); - MemBufferFree(aft->payload_buffer); - - /* clear memory */ - memset(aft, 0, sizeof(JsonAlertLogThread)); - - SCFree(aft); - return TM_ECODE_OK; -} - -static void JsonAlertLogDeInitCtx(OutputCtx *output_ctx) -{ - SCLogDebug("cleaning up output_ctx"); - LogFileCtx *logfile_ctx = (LogFileCtx *)output_ctx->data; - LogFileFreeCtx(logfile_ctx); - SCFree(output_ctx); -} - -static void JsonAlertLogDeInitCtxSub(OutputCtx *output_ctx) -{ - SCLogDebug("cleaning up sub output_ctx %p", output_ctx); - - AlertJsonOutputCtx *json_output_ctx = (AlertJsonOutputCtx *) output_ctx->data; - - if (json_output_ctx != NULL) { - HttpXFFCfg *xff_cfg = json_output_ctx->xff_cfg; - if (xff_cfg != NULL) { - SCFree(xff_cfg); - } - - SCFree(json_output_ctx); - } - SCFree(output_ctx); -} - -#define DEFAULT_LOG_FILENAME "alert.json" - -/** - * \brief Create a new LogFileCtx for "fast" output style. - * \param conf The configuration node for this output. - * \return A LogFileCtx pointer on success, NULL on failure. - */ -static OutputCtx *JsonAlertLogInitCtx(ConfNode *conf) -{ - LogFileCtx *logfile_ctx = LogFileNewCtx(); - if (logfile_ctx == NULL) { - SCLogDebug("AlertFastLogInitCtx2: Could not create new LogFileCtx"); - return NULL; - } - - if (SCConfLogOpenGeneric(conf, logfile_ctx, DEFAULT_LOG_FILENAME, 1) < 0) { - LogFileFreeCtx(logfile_ctx); - return NULL; - } - - OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx)); - if (unlikely(output_ctx == NULL)) - return NULL; - output_ctx->data = logfile_ctx; - output_ctx->DeInit = JsonAlertLogDeInitCtx; - - return output_ctx; -} - -/** - * \brief Create a new LogFileCtx for "fast" output style. - * \param conf The configuration node for this output. - * \return A LogFileCtx pointer on success, NULL on failure. - */ -static OutputCtx *JsonAlertLogInitCtxSub(ConfNode *conf, OutputCtx *parent_ctx) -{ - OutputJsonCtx *ajt = parent_ctx->data; - AlertJsonOutputCtx *json_output_ctx = NULL; - HttpXFFCfg *xff_cfg = NULL; - - OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx)); - if (unlikely(output_ctx == NULL)) - return NULL; - - json_output_ctx = SCMalloc(sizeof(AlertJsonOutputCtx)); - if (unlikely(json_output_ctx == NULL)) { - goto error; - } - memset(json_output_ctx, 0, sizeof(AlertJsonOutputCtx)); - - xff_cfg = SCMalloc(sizeof(HttpXFFCfg)); - if (unlikely(xff_cfg == NULL)) { - goto error; - } - memset(xff_cfg, 0, sizeof(HttpXFFCfg)); - - json_output_ctx->file_ctx = ajt->file_ctx; - json_output_ctx->xff_cfg = xff_cfg; - - if (conf != NULL) { - const char *payload = ConfNodeLookupChildValue(conf, "payload"); - const char *packet = ConfNodeLookupChildValue(conf, "packet"); - const char *payload_printable = ConfNodeLookupChildValue(conf, "payload-printable"); - const char *http = ConfNodeLookupChildValue(conf, "http"); - const char *tls = ConfNodeLookupChildValue(conf, "tls"); - const char *ssh = ConfNodeLookupChildValue(conf, "ssh"); - const char *smtp = ConfNodeLookupChildValue(conf, "smtp"); - - if (ssh != NULL) { - if (ConfValIsTrue(ssh)) { - json_output_ctx->flags |= LOG_JSON_SSH; - } - } - if (tls != NULL) { - if (ConfValIsTrue(tls)) { - json_output_ctx->flags |= LOG_JSON_TLS; - } - } - if (http != NULL) { - if (ConfValIsTrue(http)) { - json_output_ctx->flags |= LOG_JSON_HTTP; - } - } - if (smtp != NULL) { - if (ConfValIsTrue(smtp)) { - json_output_ctx->flags |= LOG_JSON_SMTP; - } - } - if (payload_printable != NULL) { - if (ConfValIsTrue(payload_printable)) { - json_output_ctx->flags |= LOG_JSON_PAYLOAD; - } - } - if (payload != NULL) { - if (ConfValIsTrue(payload)) { - json_output_ctx->flags |= LOG_JSON_PAYLOAD_BASE64; - } - } - if (packet != NULL) { - if (ConfValIsTrue(packet)) { - json_output_ctx->flags |= LOG_JSON_PACKET; - } - } - - HttpXFFGetCfg(conf, xff_cfg); - } - - output_ctx->data = json_output_ctx; - output_ctx->DeInit = JsonAlertLogDeInitCtxSub; - - return output_ctx; - -error: - if (json_output_ctx != NULL) { - SCFree(json_output_ctx); - } - if (output_ctx != NULL) { - SCFree(output_ctx); - } - - return NULL; -} - -void TmModuleJsonAlertLogRegister (void) -{ - tmm_modules[TMM_JSONALERTLOG].name = MODULE_NAME; - tmm_modules[TMM_JSONALERTLOG].ThreadInit = JsonAlertLogThreadInit; - tmm_modules[TMM_JSONALERTLOG].ThreadDeinit = JsonAlertLogThreadDeinit; - tmm_modules[TMM_JSONALERTLOG].cap_flags = 0; - tmm_modules[TMM_JSONALERTLOG].flags = TM_FLAG_LOGAPI_TM; - - OutputRegisterPacketModule(MODULE_NAME, "alert-json-log", - JsonAlertLogInitCtx, JsonAlertLogger, JsonAlertLogCondition); - OutputRegisterPacketSubModule("eve-log", MODULE_NAME, "eve-log.alert", - JsonAlertLogInitCtxSub, JsonAlertLogger, JsonAlertLogCondition); -} - -#else - -static TmEcode OutputJsonThreadInit(ThreadVars *t, void *initdata, void **data) -{ - SCLogInfo("Can't init JSON output - JSON support was disabled during build."); - return TM_ECODE_FAILED; -} - -void TmModuleJsonAlertLogRegister (void) -{ - tmm_modules[TMM_JSONALERTLOG].name = MODULE_NAME; - tmm_modules[TMM_JSONALERTLOG].ThreadInit = OutputJsonThreadInit; -} - -#endif - |