summaryrefslogtreecommitdiffstats
path: root/rust/vendor/sawp
diff options
context:
space:
mode:
Diffstat (limited to 'rust/vendor/sawp')
-rw-r--r--rust/vendor/sawp/.cargo-checksum.json1
-rw-r--r--rust/vendor/sawp/Cargo.toml85
-rw-r--r--rust/vendor/sawp/LICENSE13
-rw-r--r--rust/vendor/sawp/README.md65
-rw-r--r--rust/vendor/sawp/src/error.rs153
-rw-r--r--rust/vendor/sawp/src/ffi.rs86
-rw-r--r--rust/vendor/sawp/src/lib.rs44
-rw-r--r--rust/vendor/sawp/src/parser.rs39
-rw-r--r--rust/vendor/sawp/src/probe.rs31
-rw-r--r--rust/vendor/sawp/src/protocol.rs8
10 files changed, 525 insertions, 0 deletions
diff --git a/rust/vendor/sawp/.cargo-checksum.json b/rust/vendor/sawp/.cargo-checksum.json
new file mode 100644
index 0000000..e5d8f1a
--- /dev/null
+++ b/rust/vendor/sawp/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"2cdc232981f722846f3d3bae61c4cae0b29c4471c50d29571ed8b92d98bea8da","LICENSE":"7495df8c571413e70cd6363c0c245221e7bf7b7beb640b2224d22bb6f3fa7457","README.md":"65104c252c3509cd6819217da3f3811ab8696dce198e23ec4ec277ff2ce482b3","src/error.rs":"11838323e2d6f73c3b6f5c24f9ce74df4805d6fd8b99757e37b9065af85c6c6f","src/ffi.rs":"95600a8f4d7411202bed3b545fa2e95f7809f5053794ececac967fa6235ce653","src/lib.rs":"cf5ba7e0dcb669196b188fba8dc75cd31e0a8aea367e822756a695896dc7dfea","src/parser.rs":"7405546ba6c587b83b5f7549df63053ac6eeeab8eacfe76795c903c2631b5bec","src/probe.rs":"c8f18daa98417d6ee29dc0272fa1fcd5d48e3ffa87771b22a537423d8ff049bd","src/protocol.rs":"fccd161dc331076b48d09cc54d0031f4372187572a0403770b08f1200c3177bc"},"package":"7e74f84d736420afcba72f689a494d275c97cf4775c3fe248f937e9d3bf83e30"} \ No newline at end of file
diff --git a/rust/vendor/sawp/Cargo.toml b/rust/vendor/sawp/Cargo.toml
new file mode 100644
index 0000000..fa2b088
--- /dev/null
+++ b/rust/vendor/sawp/Cargo.toml
@@ -0,0 +1,85 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2021"
+rust-version = "1.58.1"
+name = "sawp"
+version = "0.12.1"
+authors = ["Canadian Centre for Cyber Security <sa-sawp@cyber.gc.ca>"]
+include = [
+ "Cargo.toml",
+ "LICENSE",
+ "README.md",
+ "src/**/*.rs",
+]
+description = "Security Aware Wire Protocol parsing library"
+homepage = "https://github.com/CybercentreCanada/sawp"
+readme = "README.md"
+keywords = [
+ "parser",
+ "streaming",
+ "protocols",
+ "network",
+ "api",
+]
+categories = [
+ "parsing",
+ "network-programming",
+]
+license-file = "LICENSE"
+repository = "https://github.com/CybercentreCanada/sawp"
+
+[lib]
+crate-type = [
+ "staticlib",
+ "rlib",
+ "cdylib",
+]
+bench = false
+
+[[bench]]
+name = "modbus"
+path = "benches/modbus.rs"
+harness = false
+
+[dependencies.nom]
+version = "7.1.1"
+
+[dependencies.sawp-ffi]
+version = "^0.12.1"
+optional = true
+
+[dev-dependencies.clap]
+version = "~2.33"
+
+[dev-dependencies.criterion]
+version = "=0.3.4"
+
+[dev-dependencies.csv]
+version = "=1.1.6"
+
+[dev-dependencies.rayon]
+version = "=1.6.1"
+
+[dev-dependencies.rayon-core]
+version = "=1.10.2"
+
+[build-dependencies.cbindgen]
+version = "0.15"
+optional = true
+
+[features]
+ffi = [
+ "cbindgen",
+ "sawp-ffi",
+]
+verbose = []
diff --git a/rust/vendor/sawp/LICENSE b/rust/vendor/sawp/LICENSE
new file mode 100644
index 0000000..24a5028
--- /dev/null
+++ b/rust/vendor/sawp/LICENSE
@@ -0,0 +1,13 @@
+Copyright 2020 Crown Copyright, Government of Canada (Canadian Centre for Cyber Security / Communications Security Establishment)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files
+(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/rust/vendor/sawp/README.md b/rust/vendor/sawp/README.md
new file mode 100644
index 0000000..c8f735b
--- /dev/null
+++ b/rust/vendor/sawp/README.md
@@ -0,0 +1,65 @@
+# [Français](README.fr.md)
+
+# Security Aware Wire Protocol parsing library.
+
+This library contains parsers for various wire protocols,
+and is intended to be used in network security sensors.
+
+Each parser exposes a common interface that allows the sensor
+engine to feed bytes into the parser and receive parsed
+metadata back. The bytes are expected to be at the session layer,
+so the engine is responsible for assembling transport layer
+data into a session payload, which is then fed into this library.
+
+This library aims to be resilient and parse as many messages as
+possible that are seen in the wild. If a message is invalid or
+out-of-spec, it should not be discarded by the parser. Parsers
+will set flags on the message when it fails validation instead
+of returning an error.
+
+The interface to each parser is uniform and simple, consisting of
+only a few functions to:
+
+- test that a payload is or is not the protocol in question
+ (eg. is this modbus?)
+- provide more bytes to the parser
+- set callbacks to invoke on per-protocol metadata events (todo)
+- indicate that some bytes are unavailable (ie. notify of packet
+ loss) (todo)
+- indicate a session has ended (todo)
+
+The library exposes Rust and C bindings for easy integration into
+existing and future network security sensor platforms. (todo)
+
+# Usage
+Start using SAWP by including a parser in your project's `Cargo.toml`
+dependencies. The base library will also be required for using common
+types.
+
+**The minimum supported version of `rustc` is `1.58.1`.**
+
+## Example
+```
+[dependencies]
+sawp-modbus = "0.12.1"
+sawp = "0.12.1"
+```
+
+## FFI Support
+Some parsers have a foreign function interface for use in C/C++ projects.
+FFI Support can be enabled by building with the `ffi` feature.
+
+A [Makefile](Makefile) is also provided to ease the build process. Please refer to this file for more in-depth documentation.
+
+```
+# Install cbindgen which is required to generate headers
+cargo install --force cbindgen
+
+# Build headers and shared objects
+make
+```
+
+# Contributing
+
+This project is actively maintained and accepting open source
+contributions. See [CONTRIBUTING](CONTRIBUTING.md) for more details.
diff --git a/rust/vendor/sawp/src/error.rs b/rust/vendor/sawp/src/error.rs
new file mode 100644
index 0000000..d27717b
--- /dev/null
+++ b/rust/vendor/sawp/src/error.rs
@@ -0,0 +1,153 @@
+#[cfg(feature = "ffi")]
+use sawp_ffi::GenerateFFI;
+
+use std::num::NonZeroUsize;
+
+// Re-export types used for ErrorKind
+use nom::error::ErrorKind as NomErrorKind;
+use nom::Needed as NomNeeded;
+
+/// Helper that uses this module's error type
+pub type Result<T> = std::result::Result<T, Error>;
+
+/// Helper for nom's default error type
+pub type NomError<I> = nom::error::Error<I>;
+
+/// Common protocol or parsing error
+///
+/// This error type is meant to return the errors that
+/// are common across parsers and other sub packages.
+/// Sub packages may choose to implement their own error
+/// types if they wish to avoid adding extra dependencies
+/// to the base crate.
+#[derive(Debug, PartialEq)]
+#[cfg_attr(feature = "ffi", derive(GenerateFFI))]
+#[cfg_attr(feature = "ffi", sawp_ffi(prefix = "sawp"))]
+pub struct Error {
+ pub kind: ErrorKind,
+}
+
+impl Error {
+ pub fn new(kind: ErrorKind) -> Self {
+ Self { kind }
+ }
+
+ /// Helper for creating an error with a `ErrorKind::Incomplete` and a needed size.
+ pub fn incomplete_needed(size: usize) -> Self {
+ Error::new(ErrorKind::Incomplete(
+ NonZeroUsize::new(size)
+ .map(Needed::Size)
+ .unwrap_or(Needed::Unknown),
+ ))
+ }
+
+ /// Helper for creating an error with a `ErrorKind::Incomplete` and an unknown size.
+ pub fn incomplete() -> Self {
+ Error::new(ErrorKind::Incomplete(Needed::Unknown))
+ }
+
+ /// Helper for creating a parse error.
+ #[cfg(verbose)]
+ pub fn parse(msg: Option<String>) -> Self {
+ Error::new(ErrorKind::ParseError(msg))
+ }
+
+ /// Helper for creating a parse error.
+ #[cfg(not(verbose))]
+ pub fn parse(_msg: Option<String>) -> Self {
+ Error::new(ErrorKind::ParseError(None))
+ }
+}
+
+impl From<ErrorKind> for Error {
+ fn from(kind: ErrorKind) -> Self {
+ Self::new(kind)
+ }
+}
+
+/// Number of bytes needed for the next parsing attempt.
+///
+/// Used in `ErrorKind::Incomplete` to tell the caller how many bytes to wait
+/// for before calling the parser with more data.
+#[derive(Debug, PartialEq)]
+pub enum Needed {
+ Unknown,
+ Size(NonZeroUsize),
+}
+
+/// Kinds of common errors used by the parsers
+#[derive(Debug, PartialEq)]
+#[non_exhaustive]
+#[cfg_attr(feature = "ffi", derive(GenerateFFI))]
+#[cfg_attr(feature = "ffi", sawp_ffi(type_only, prefix = "sawp"))]
+pub enum ErrorKind {
+ /// Feature is not yet implemented.
+ Unimplemented,
+ /// Parser could not advance based on the data provided.
+ ///
+ /// Usually indicates the provided input bytes cannot be parsed
+ /// for the protocol.
+ //
+ // Developer note:
+ //
+ // This error should only be used as a last resort. Consider
+ // returning Ok and adding validation error flags to the
+ // parser's `Message` instead.
+ InvalidData,
+ /// Generic parsing error with optional message.
+ ParseError(Option<String>),
+ /// Parser did not advance because more data is required to
+ /// make a decision.
+ ///
+ /// The caller should gather more data and try again.
+ Incomplete(Needed),
+}
+
+impl From<NomErrorKind> for ErrorKind {
+ #[cfg(verbose)]
+ fn from(kind: NomErrorKind) -> Self {
+ Self::ParseError(Some(format!("{:?}", kind)))
+ }
+
+ #[cfg(not(verbose))]
+ fn from(_kind: NomErrorKind) -> Self {
+ Self::ParseError(None)
+ }
+}
+
+impl<I: std::fmt::Debug> From<nom::Err<NomError<I>>> for Error {
+ fn from(nom_err: nom::Err<NomError<I>>) -> Self {
+ match nom_err {
+ nom::Err::Error(err) | nom::Err::Failure(err) => Error::new(err.code.into()),
+ nom::Err::Incomplete(needed) => match needed {
+ NomNeeded::Unknown => Error::incomplete(),
+ NomNeeded::Size(size) => Error::incomplete_needed(size.into()),
+ },
+ }
+ }
+}
+
+impl std::fmt::Display for Error {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::result::Result<(), std::fmt::Error> {
+ match &self.kind {
+ ErrorKind::Unimplemented => write!(f, "Unimplemented feature"),
+ ErrorKind::InvalidData => write!(f, "Encountered invalid data"),
+ ErrorKind::ParseError(err) if err.is_some() => {
+ write!(f, "Parsing error: {}", err.clone().unwrap())
+ }
+ ErrorKind::ParseError(_) => write!(f, "Parsing error"),
+ ErrorKind::Incomplete(Needed::Unknown) => write!(f, "More bytes required to parse"),
+ ErrorKind::Incomplete(Needed::Size(n)) => {
+ write!(f, "{} more bytes required to parse", n)
+ }
+ }
+ }
+}
+
+impl std::error::Error for Error {}
+
+impl<I: std::fmt::Debug> From<NomError<I>> for Error {
+ fn from(nom_err: NomError<I>) -> Self {
+ Error::new(nom_err.code.into())
+ }
+}
diff --git a/rust/vendor/sawp/src/ffi.rs b/rust/vendor/sawp/src/ffi.rs
new file mode 100644
index 0000000..aeed1cc
--- /dev/null
+++ b/rust/vendor/sawp/src/ffi.rs
@@ -0,0 +1,86 @@
+use sawp_ffi::deref;
+
+/// Note this function only works for Vec<u8>
+/// for other types, use the field_ptr accessor
+/// # Safety
+/// function will panic if called with null
+#[no_mangle]
+pub unsafe extern "C" fn sawp_vector_get_data(vec: *const Vec<u8>) -> *const u8 {
+ deref!(vec).as_ptr()
+}
+
+/// # Safety
+/// function will panic if called with null
+#[no_mangle]
+pub unsafe extern "C" fn sawp_vector_get_size(vec: *const Vec<u8>) -> usize {
+ deref!(vec).len()
+}
+
+/// Note: Returned string is not null terminated
+/// # Safety
+/// function will panic if called with null
+#[no_mangle]
+pub unsafe extern "C" fn sawp_string_get_ptr(s: *const String) -> *const u8 {
+ deref!(s).as_ptr()
+}
+
+/// # Safety
+/// function will panic if called with null
+#[no_mangle]
+pub unsafe extern "C" fn sawp_string_get_size(s: *const String) -> usize {
+ deref!(s).len()
+}
+
+/// # Safety
+/// function will panic if called with null
+#[no_mangle]
+pub unsafe extern "C" fn sawp_ipv4addr_get_data(ip: *const std::net::Ipv4Addr) -> u32 {
+ u32::from_be_bytes(deref!(ip).octets())
+}
+
+/// # Safety
+/// function will panic if called with null
+#[no_mangle]
+pub unsafe extern "C" fn sawp_ipv6addr_get_data(ip: *const std::net::Ipv6Addr) -> *const u8 {
+ deref!(ip).octets().as_slice().as_ptr()
+}
+
+/// # Safety
+/// function will panic if called with null
+#[no_mangle]
+pub unsafe extern "C" fn sawp_ipaddr_is_v4(ip: *const std::net::IpAddr) -> bool {
+ deref!(ip).is_ipv4()
+}
+
+/// # Safety
+/// function will panic if called with null
+#[no_mangle]
+pub unsafe extern "C" fn sawp_ipaddr_is_v6(ip: *const std::net::IpAddr) -> bool {
+ deref!(ip).is_ipv6()
+}
+
+/// # Safety
+/// function will panic if called with null
+#[no_mangle]
+pub unsafe extern "C" fn sawp_ipaddr_as_v4(
+ ip: *const std::net::IpAddr,
+) -> *const std::net::Ipv4Addr {
+ if let std::net::IpAddr::V4(addr) = deref!(ip) {
+ addr
+ } else {
+ std::ptr::null()
+ }
+}
+
+/// # Safety
+/// function will panic if called with null
+#[no_mangle]
+pub unsafe extern "C" fn sawp_ipaddr_as_v6(
+ ip: *const std::net::IpAddr,
+) -> *const std::net::Ipv6Addr {
+ if let std::net::IpAddr::V6(addr) = deref!(ip) {
+ addr
+ } else {
+ std::ptr::null()
+ }
+}
diff --git a/rust/vendor/sawp/src/lib.rs b/rust/vendor/sawp/src/lib.rs
new file mode 100644
index 0000000..7c5940b
--- /dev/null
+++ b/rust/vendor/sawp/src/lib.rs
@@ -0,0 +1,44 @@
+/*!
+# SAWP: Security Aware Wire Protocol parsing library
+
+This library contains parsers for various wire protocols
+and is intended to be used in network security sensors.
+
+The base library contains all of the common types and traits
+used by the parsers.
+
+Usage documentation can be found in the [README](https://github.com/CybercentreCanada/sawp/blob/main/README.md).
+
+## Protocols
+
+Each protocol, along with certain features, are implemented
+in a separate package inside this workspace. This reduces the
+number dependencies needed for using various protocols or
+features. A practical use of this library can be found by
+referring to the protocol parser you wish to use:
+- [Diameter](/sawp-diameter)
+- [Json](/sawp-json)
+- [Modbus](/sawp-modbus)
+
+## Utility
+
+The following utility packages also exist:
+- [File](/sawp-file) Serializes API calls for debugging
+*/
+
+#![allow(clippy::unneeded_field_pattern)]
+
+/// Return common errors
+pub mod error;
+
+/// Parse Messages
+pub mod parser;
+
+/// Probe Bytes
+pub mod probe;
+
+/// Describe a Protocol
+pub mod protocol;
+
+#[cfg(feature = "ffi")]
+pub mod ffi;
diff --git a/rust/vendor/sawp/src/parser.rs b/rust/vendor/sawp/src/parser.rs
new file mode 100644
index 0000000..6909305
--- /dev/null
+++ b/rust/vendor/sawp/src/parser.rs
@@ -0,0 +1,39 @@
+use crate::error::Result;
+use crate::protocol::Protocol;
+
+/// Destination of the input byte stream.
+#[repr(C)]
+#[derive(Clone, Debug, PartialEq)]
+pub enum Direction {
+ /// Message is destined to the client
+ ToClient,
+ /// Message is destined to the server
+ ToServer,
+ /// Direction is not known
+ Unknown,
+}
+
+/// Trait for parsing message from an input byte stream.
+pub trait Parse<'a>: Protocol<'a> {
+ /// Returns a tuple containing the remaining unparsed data and the parsed `Message`.
+ ///
+ /// A return value of `Result::Ok` indicates that the parser has *made progress*
+ /// and should only be used when the remaining unparsed data is less than the input.
+ ///
+ /// A return value of `Result::Err` indicates that *no progress* was made
+ /// and the user may call the parse function again with the same input in
+ /// some scenarios:
+ /// - `ErrorKind::Incomplete`: call `parse` once more input data is available.
+ ///
+ /// Consequently, `Result::Ok(None)` is used to indicate the parser made
+ /// progress but needs more data to return a complete `Message`. Internal
+ /// buffering may occur depending on the implementation.
+ ///
+ /// `Result::Err(ErrorKind::Incomplete(_))` must be used instead of `Result::Ok(None)`
+ /// when no progress was made parsing the input.
+ fn parse(
+ &self,
+ input: &'a [u8],
+ direction: Direction,
+ ) -> Result<(&'a [u8], Option<Self::Message>)>;
+}
diff --git a/rust/vendor/sawp/src/probe.rs b/rust/vendor/sawp/src/probe.rs
new file mode 100644
index 0000000..3aa976d
--- /dev/null
+++ b/rust/vendor/sawp/src/probe.rs
@@ -0,0 +1,31 @@
+use crate::error::{Error, ErrorKind};
+use crate::parser::{Direction, Parse};
+use crate::protocol::Protocol;
+
+/// Result of probing the underlying bytes.
+#[derive(Debug, PartialEq)]
+pub enum Status {
+ /// Data matches this protocol
+ Recognized,
+ /// Data does not match this protocol
+ Unrecognized,
+ /// More data is needed to make a decision
+ Incomplete,
+}
+
+pub trait Probe<'a>: Protocol<'a> + Parse<'a> {
+ /// Probes the input to recognize if the underlying bytes likely match this
+ /// protocol.
+ ///
+ /// Returns a probe status. Probe again once more data is available when the
+ /// status is `Status::Incomplete`.
+ fn probe(&self, input: &'a [u8], direction: Direction) -> Status {
+ match self.parse(input, direction) {
+ Ok((_, _)) => Status::Recognized,
+ Err(Error {
+ kind: ErrorKind::Incomplete(_),
+ }) => Status::Incomplete,
+ Err(_) => Status::Unrecognized,
+ }
+ }
+}
diff --git a/rust/vendor/sawp/src/protocol.rs b/rust/vendor/sawp/src/protocol.rs
new file mode 100644
index 0000000..a24d7e2
--- /dev/null
+++ b/rust/vendor/sawp/src/protocol.rs
@@ -0,0 +1,8 @@
+/// Represents the basic elements of a protocol
+pub trait Protocol<'a> {
+ /// Type of message returned when parsing
+ type Message: 'a;
+
+ /// Protocol name string
+ fn name() -> &'static str;
+}