diff --git a/rust/Cargo.toml.in b/rust/Cargo.toml.in index 2f873e7a1a..3f484c339e 100644 --- a/rust/Cargo.toml.in +++ b/rust/Cargo.toml.in @@ -53,6 +53,7 @@ sha-1 = "~0.9.2" md-5 = "~0.9.1" regex = "~1.4.2" lazy_static = "~1.4.0" +base64 = "~0.13.0" suricata-derive = { path = "./derive" } diff --git a/rust/src/jsonbuilder.rs b/rust/src/jsonbuilder.rs index 82636176a3..993186c9ee 100644 --- a/rust/src/jsonbuilder.rs +++ b/rust/src/jsonbuilder.rs @@ -304,6 +304,30 @@ impl JsonBuilder { } } + /// Add a string to an array. + pub fn append_base64(&mut self, val: &[u8]) -> Result<&mut Self, JsonError> { + match self.current_state() { + State::ArrayFirst => { + self.buf.push('"'); + base64::encode_config_buf(val, base64::STANDARD, &mut self.buf); + self.buf.push('"'); + self.set_state(State::ArrayNth); + Ok(self) + } + State::ArrayNth => { + self.buf.push(','); + self.buf.push('"'); + base64::encode_config_buf(val, base64::STANDARD, &mut self.buf); + self.buf.push('"'); + Ok(self) + } + _ => { + debug_validate_fail!("invalid state"); + Err(JsonError::InvalidState) + } + } + } + /// Add an unsigned integer to an array. pub fn append_uint(&mut self, val: u64) -> Result<&mut Self, JsonError> { match self.current_state() { @@ -427,6 +451,29 @@ impl JsonBuilder { } } + /// Set a key and a string field as the base64 encoded string of the value. + pub fn set_base64(&mut self, key: &str, val: &[u8]) -> 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("\":\""); + base64::encode_config_buf(val, base64::STANDARD, &mut self.buf); + self.buf.push('"'); + + Ok(self) + } + /// Set a key and an unsigned integer type on an object. pub fn set_uint(&mut self, key: &str, val: u64) -> Result<&mut Self, JsonError> { match self.current_state() { @@ -655,6 +702,20 @@ pub unsafe extern "C" fn jb_set_string_from_bytes( return false; } +#[no_mangle] +pub unsafe extern "C" fn jb_set_base64( + js: &mut JsonBuilder, key: *const c_char, bytes: *const u8, len: u32, +) -> bool { + if bytes == std::ptr::null() || len == 0 { + return false; + } + if let Ok(key) = CStr::from_ptr(key).to_str() { + let val = std::slice::from_raw_parts(bytes, len as usize); + return js.set_base64(key, val).is_ok(); + } + return false; +} + #[no_mangle] pub unsafe extern "C" fn jb_set_formatted(js: &mut JsonBuilder, formatted: *const c_char) -> bool { if let Ok(formatted) = CStr::from_ptr(formatted).to_str() { @@ -700,6 +761,17 @@ pub unsafe extern "C" fn jb_append_string_from_bytes( return js.append_string_from_bytes(val).is_ok(); } +#[no_mangle] +pub unsafe extern "C" fn jb_append_base64( + js: &mut JsonBuilder, bytes: *const u8, len: u32, +) -> bool { + if bytes == std::ptr::null() || len == 0 { + return false; + } + let val = std::slice::from_raw_parts(bytes, len as usize); + return js.append_base64(val).is_ok(); +} + #[no_mangle] pub unsafe extern "C" fn jb_append_uint(js: &mut JsonBuilder, val: u64) -> bool { return js.append_uint(val).is_ok();