+++ /dev/null
-/* 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.
- */
-
-//! Expose portions of the libjansson API to Rust so Rust code can
-//! populate a json_t and return it for logging by Suricata.
-
-use std::ffi::CString;
-use std::os::raw::c_char;
-use std::os::raw::c_int;
-
-/// The Rust place holder for the json_t pointer.
-pub enum JsonT {}
-
-/// Expose the jansson functions we need.
-extern {
- fn json_object() -> *mut JsonT;
- fn json_object_set_new(js: *mut JsonT, key: *const c_char,
- val: *mut JsonT) -> u32;
-
- fn json_array() -> *mut JsonT;
- fn json_array_append_new(array: *mut JsonT, value: *mut JsonT);
-
- fn json_string(value: *const c_char) -> *mut JsonT;
- fn json_integer(val: u64) -> *mut JsonT;
- fn SCJsonDecref(value: *mut JsonT);
- fn SCJsonBool(val: bool) -> *mut JsonT;
- pub fn json_dumps(js: *mut JsonT, flags: c_int) -> *const c_char;
-}
-
-pub struct Json {
- pub js: *mut JsonT,
-}
-
-impl Json {
-
- pub fn decref(val: Json) {
- unsafe{SCJsonDecref(val.js)};
- }
-
- pub fn object() -> Json {
- return Json{
- js: unsafe{json_object()},
- }
- }
-
- pub fn array() -> Json {
- return Json{
- js: unsafe{json_array()},
- }
- }
-
- pub fn string(val: &str) -> Json {
- return Json{
- js: unsafe{json_string(to_cstring(val.as_bytes()).as_ptr())}
- };
- }
-
- pub fn string_from_bytes(val: &[u8]) -> Json {
- return Json{
- js: unsafe{json_string(to_cstring(val).as_ptr())}
- };
- }
-
- pub fn unwrap(&self) -> *mut JsonT {
- return self.js;
- }
-
- pub fn set(&self, key: &str, val: Json) {
- unsafe {
- json_object_set_new(self.js,
- CString::new(key).unwrap().as_ptr(),
- val.js);
- }
- }
-
- pub fn set_string_from_bytes(&self, key: &str, val: &[u8]) {
- unsafe {
- json_object_set_new(self.js,
- CString::new(key).unwrap().as_ptr(),
- json_string(to_cstring(val).as_ptr()));
- }
- }
-
- pub fn set_string(&self, key: &str, val: &str) {
- unsafe {
- json_object_set_new(self.js,
- CString::new(key).unwrap().as_ptr(),
- json_string(to_cstring(val.as_bytes()).as_ptr()));
- }
- }
-
- pub fn set_integer(&self, key: &str, val: u64) {
- unsafe {
- json_object_set_new(self.js,
- CString::new(key).unwrap().as_ptr(),
- json_integer(val));
- }
- }
-
- pub fn set_boolean(&self, key: &str, val: bool) {
- unsafe {
- json_object_set_new(self.js,
- CString::new(key).unwrap().as_ptr(),
- SCJsonBool(val));
- }
- }
-
- pub fn array_append(&self, val: Json) {
- unsafe {
- json_array_append_new(self.js, val.js);
- }
- }
- pub fn array_append_string(&self, val: &str) {
- unsafe {
- json_array_append_new(self.js, json_string(to_cstring(val.as_bytes()).as_ptr()));
- }
- }
-}
-
-/// Convert an array of bytes into an ascii printable string replacing
-/// non-printable characters (including NULL) with hex value.
-///
-/// Newer versions of Jansson have a json_stringn that will allow us
-/// to create a string out of a byte array of unicode compliant bytes,
-/// but until we can use it across all platforms this is probably the
-/// best we can do.
-fn to_cstring(val: &[u8]) -> CString {
- let mut safe = Vec::with_capacity(val.len());
- for c in val {
- if *c < 0x20 || *c > 0x7e {
- safe.extend(format!("\\x{:02x}", *c).as_bytes());
- } else {
- safe.push(*c);
- }
- }
- match CString::new(safe) {
- Ok(cstr) => cstr,
- _ => {
- CString::new("<failed to encode string>").unwrap()
- }
- }
-}
-
-#[cfg(test)]
-mod tests {
-
- use crate::json::to_cstring;
-
- #[test]
- fn test_to_string() {
- assert_eq!("A\\x00A",
- to_cstring(&[0x41, 0x00, 0x41]).into_string().unwrap());
- assert_eq!("", to_cstring(&[]).into_string().unwrap());
- assert_eq!("\\x80\\xf1\\xf2\\xf3",
- to_cstring(&[0x80, 0xf1, 0xf2, 0xf3]).into_string().unwrap());
- }
-
-}
#![allow(clippy::missing_safety_doc)]
-use crate::json;
use std::ffi::CStr;
use std::os::raw::c_char;
use std::str::Utf8Error;
Ok(self)
}
- pub fn set_jsont(
- &mut self, key: &str, jsont: &mut json::JsonT,
- ) -> Result<&mut Self, JsonError> {
- match self.current_state() {
- State::ObjectNth => self.buf.push(','),
- State::ObjectFirst => self.set_state(State::ObjectNth),
- _ => {
- debug_validate_fail!("invalid state");
- return Err(JsonError::InvalidState);
- }
- }
- self.buf.push('"');
- self.buf.push_str(key);
- self.buf.push_str("\":");
- self.append_jsont(jsont)?;
- Ok(self)
- }
-
- fn append_jsont(&mut self, jsont: &mut json::JsonT) -> Result<&mut Self, JsonError> {
- unsafe {
- let raw = json::json_dumps(jsont, 0);
- let rendered = std::ffi::CStr::from_ptr(raw).to_str()?;
- self.buf.push_str(rendered);
- libc::free(raw as *mut std::os::raw::c_void);
- Ok(self)
- }
- }
-
/// Set a key and string value type on an object.
#[inline(always)]
pub fn set_string(&mut self, key: &str, val: &str) -> Result<&mut Self, JsonError> {
return false;
}
-#[no_mangle]
-pub unsafe extern "C" fn jb_set_jsont(
- jb: &mut JsonBuilder, key: *const c_char, jsont: &mut json::JsonT,
-) -> bool {
- if let Ok(key) = CStr::from_ptr(key).to_str() {
- return jb.set_jsont(key, jsont).is_ok();
- }
- return false;
-}
-
#[no_mangle]
pub unsafe extern "C" fn jb_append_object(jb: &mut JsonBuilder, obj: &JsonBuilder) -> bool {
jb.append_object(obj).is_ok()
#[macro_use]
pub mod common;
pub mod conf;
-pub mod json;
pub mod jsonbuilder;
#[macro_use]
pub mod applayer;
}
}
-/**
- * \brief Add five tuple from packet to JSON object
- *
- * \param p Packet
- * \param dir log direction (packet or flow)
- * \param js JSON object
- */
-void JsonFiveTuple(const Packet *p, enum OutputJsonLogDirection dir, json_t *js)
-{
- char srcip[46] = {0}, dstip[46] = {0};
- Port sp, dp;
-
- switch (dir) {
- case LOG_DIR_PACKET:
- if (PKT_IS_IPV4(p)) {
- PrintInet(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p),
- srcip, sizeof(srcip));
- PrintInet(AF_INET, (const void *)GET_IPV4_DST_ADDR_PTR(p),
- dstip, sizeof(dstip));
- } else if (PKT_IS_IPV6(p)) {
- PrintInet(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p),
- srcip, sizeof(srcip));
- PrintInet(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p),
- dstip, sizeof(dstip));
- } else {
- /* Not an IP packet so don't do anything */
- return;
- }
- sp = p->sp;
- dp = p->dp;
- break;
- case LOG_DIR_FLOW:
- case LOG_DIR_FLOW_TOSERVER:
- if ((PKT_IS_TOSERVER(p))) {
- if (PKT_IS_IPV4(p)) {
- PrintInet(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p),
- srcip, sizeof(srcip));
- PrintInet(AF_INET, (const void *)GET_IPV4_DST_ADDR_PTR(p),
- dstip, sizeof(dstip));
- } else if (PKT_IS_IPV6(p)) {
- PrintInet(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p),
- srcip, sizeof(srcip));
- PrintInet(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p),
- dstip, sizeof(dstip));
- }
- sp = p->sp;
- dp = p->dp;
- } else {
- if (PKT_IS_IPV4(p)) {
- PrintInet(AF_INET, (const void *)GET_IPV4_DST_ADDR_PTR(p),
- srcip, sizeof(srcip));
- PrintInet(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p),
- dstip, sizeof(dstip));
- } else if (PKT_IS_IPV6(p)) {
- PrintInet(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p),
- srcip, sizeof(srcip));
- PrintInet(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p),
- dstip, sizeof(dstip));
- }
- sp = p->dp;
- dp = p->sp;
- }
- break;
- case LOG_DIR_FLOW_TOCLIENT:
- if ((PKT_IS_TOCLIENT(p))) {
- if (PKT_IS_IPV4(p)) {
- PrintInet(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p),
- srcip, sizeof(srcip));
- PrintInet(AF_INET, (const void *)GET_IPV4_DST_ADDR_PTR(p),
- dstip, sizeof(dstip));
- } else if (PKT_IS_IPV6(p)) {
- PrintInet(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p),
- srcip, sizeof(srcip));
- PrintInet(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p),
- dstip, sizeof(dstip));
- }
- sp = p->sp;
- dp = p->dp;
- } else {
- if (PKT_IS_IPV4(p)) {
- PrintInet(AF_INET, (const void *)GET_IPV4_DST_ADDR_PTR(p),
- srcip, sizeof(srcip));
- PrintInet(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p),
- dstip, sizeof(dstip));
- } else if (PKT_IS_IPV6(p)) {
- PrintInet(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p),
- srcip, sizeof(srcip));
- PrintInet(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p),
- dstip, sizeof(dstip));
- }
- sp = p->dp;
- dp = p->sp;
- }
- break;
- default:
- DEBUG_VALIDATE_BUG_ON(1);
- return;
- }
-
-
- json_object_set_new(js, "src_ip", json_string(srcip));
-
- switch(p->proto) {
- case IPPROTO_ICMP:
- break;
- case IPPROTO_UDP:
- case IPPROTO_TCP:
- case IPPROTO_SCTP:
- json_object_set_new(js, "src_port", json_integer(sp));
- break;
- }
-
- json_object_set_new(js, "dest_ip", json_string(dstip));
-
- switch(p->proto) {
- case IPPROTO_ICMP:
- break;
- case IPPROTO_UDP:
- case IPPROTO_TCP:
- case IPPROTO_SCTP:
- json_object_set_new(js, "dest_port", json_integer(dp));
- break;
- }
-
- if (SCProtoNameValid(IP_GET_IPPROTO(p))) {
- json_object_set_new(js, "proto", json_string(known_proto[IP_GET_IPPROTO(p)]));
- } else {
- char proto[4];
- snprintf(proto, sizeof(proto), "%"PRIu32"", IP_GET_IPPROTO(p));
- json_object_set_new(js, "proto", json_string(proto));
- }
-}
-
#define COMMUNITY_ID_BUF_SIZE 64
static bool CalculateCommunityFlowIdv4(const Flow *f,
}
}
-void CreateJSONFlowId(json_t *js, const Flow *f)
-{
- if (f == NULL)
- return;
- int64_t flow_id = FlowGetId(f);
- json_object_set_new(js, "flow_id", json_integer(flow_id));
- if (f->parent_id) {
- json_object_set_new(js, "parent_id", json_integer(f->parent_id));
- }
-}
-
void CreateEveFlowId(JsonBuilder *js, const Flow *f)
{
if (f == NULL) {
}
}
-json_t *CreateJSONHeader(const Packet *p, enum OutputJsonLogDirection dir,
- const char *event_type, JsonAddrInfo *addr)
-{
- char timebuf[64];
- const Flow *f = (const Flow *)p->flow;
-
- json_t *js = json_object();
- if (unlikely(js == NULL))
- return NULL;
-
- CreateIsoTimeString(&p->ts, timebuf, sizeof(timebuf));
-
- /* time & tx */
- json_object_set_new(js, "timestamp", json_string(timebuf));
-
- CreateJSONFlowId(js, f);
-
- /* sensor id */
- if (sensor_id >= 0)
- json_object_set_new(js, "sensor_id", json_integer(sensor_id));
-
- /* input interface */
- if (p->livedev) {
- json_object_set_new(js, "in_iface", json_string(p->livedev->dev));
- }
-
- /* pcap_cnt */
- if (p->pcap_cnt != 0) {
- json_object_set_new(js, "pcap_cnt", json_integer(p->pcap_cnt));
- }
-
- if (event_type) {
- json_object_set_new(js, "event_type", json_string(event_type));
- }
-
- /* vlan */
- if (p->vlan_idx > 0) {
- json_t *js_vlan = json_array();
- if (js_vlan) {
- json_array_append_new(js_vlan, json_integer(p->vlan_id[0]));
- if (p->vlan_idx > 1) {
- json_array_append_new(js_vlan, json_integer(p->vlan_id[1]));
- }
- json_object_set_new(js, "vlan", js_vlan);
- }
- }
-
- /* 5-tuple */
- JsonAddrInfo addr_info = json_addr_info_zero;
- if (addr == NULL) {
- JsonAddrInfoInit(p, dir, &addr_info);
- addr = &addr_info;
- }
- json_object_set_new(js, "src_ip", json_string(addr->src_ip));
- json_object_set_new(js, "src_port", json_integer(addr->sp));
- json_object_set_new(js, "dest_ip", json_string(addr->dst_ip));
- json_object_set_new(js, "dest_port", json_integer(addr->dp));
- json_object_set_new(js, "proto", json_string(addr->proto));
-
- /* icmp */
- switch (p->proto) {
- case IPPROTO_ICMP:
- if (p->icmpv4h) {
- json_object_set_new(js, "icmp_type",
- json_integer(p->icmpv4h->type));
- json_object_set_new(js, "icmp_code",
- json_integer(p->icmpv4h->code));
- }
- break;
- case IPPROTO_ICMPV6:
- if (p->icmpv6h) {
- json_object_set_new(js, "icmp_type",
- json_integer(p->icmpv6h->type));
- json_object_set_new(js, "icmp_code",
- json_integer(p->icmpv6h->code));
- }
- break;
- }
-
- return js;
-}
-
JsonBuilder *CreateEveHeader(const Packet *p, enum OutputJsonLogDirection dir,
const char *event_type, JsonAddrInfo *addr)
{
int OutputJSONMemBufferCallback(const char *str, size_t size, void *data);
-void CreateJSONFlowId(json_t *js, const Flow *f);
void CreateEveFlowId(JsonBuilder *js, const Flow *f);
void EveFileInfo(JsonBuilder *js, const File *file, const bool stored);
void EveTcpFlags(uint8_t flags, JsonBuilder *js);
void EvePacket(const Packet *p, JsonBuilder *js, unsigned long max_length);
-void JsonFiveTuple(const Packet *, enum OutputJsonLogDirection, json_t *);
-json_t *CreateJSONHeader(const Packet *p,
- enum OutputJsonLogDirection dir, const char *event_type,
- JsonAddrInfo *addr);
JsonBuilder *CreateEveHeader(const Packet *p,
enum OutputJsonLogDirection dir, const char *event_type,
JsonAddrInfo *addr);