feat: added the beginnings of sparse-protocol

sparse protocol allows for composing of different "protocols" at
runtime, and will allow for DNS and TCP as well as different TCP
protocols like HTTP
This commit is contained in:
Andrew Rioux 2023-05-09 10:34:03 -04:00
parent 968df54f59
commit 8ad7127d4d
Signed by: andrew.rioux
GPG Key ID: 9B8BAC47C17ABB94
4 changed files with 91 additions and 1 deletions

7
Cargo.lock generated
View File

@ -575,6 +575,13 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "sparse-protocol"
version = "0.1.0"
dependencies = [
"pcap-sys",
]
[[package]] [[package]]
name = "subtle" name = "subtle"
version = "2.4.1" version = "2.4.1"

View File

@ -1,5 +1,9 @@
[workspace] [workspace]
members = ["pcap-sys", "nl-sys", "examples/*/*"] members = [
"pcap-sys", "nl-sys",
"examples/*/*",
"sparse-protocol"
]
[profile.release] [profile.release]
strip = true strip = true

View File

@ -0,0 +1,9 @@
[package]
name = "sparse-protocol"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
pcap-sys = { path = "../pcap-sys" }

View File

@ -0,0 +1,70 @@
use std::marker::PhantomData;
/// A composable protocol trait.
///
/// Can be reused to allow for composition of multiple compatible protocols
pub trait Protocol<I, T> {
/// Allows for handling incoming packets, and returning something up to the handler of the protocol as well
/// as packets to send out
///
/// Usually, this will take in a slice of bytes and return a Vec of some enum or another slice of bytes
/// to be consumed by another protocol
fn handle_event(&mut self, packet: I) -> (T, I);
/// Allows for composing multiple protocols on top of each other, for instance to use
/// TCP fragmenting to work with HTTP to form a complete packet, and then take the HTTP
/// conversation and encode Sparse messages into it
fn compose<P, U>(self, other: P) -> ProtocolCompose<Self, P, I, J, T, U>
where
J: From<T>,
P: Protocol<J, U> + Sized,
Self: Sized,
{
ProtocolCompose {
protocol1: self,
protocol2: other,
generic_i: PhantomData,
generic_j: PhantomData,
generic_t: PhantomData,
generic_u: PhantomData,
}
}
}
/// A struct to go along with the compose method from before. Represents two underlying protocols
/// which work together to act as one
pub struct ProtocolCompose<P1: Protocol<I, T>, P2: Protocol<J, U>, I, J: From<T>, T, U> {
protocol1: P1,
protocol2: P2,
generic_i: PhantomData<I>,
generic_j: PhantomData<J>,
generic_t: PhantomData<T>,
generic_u: PhantomData<U>,
}
impl<P1: Protocol<I, T>, P2: Protocol<J, U>, I, J: From<T>, T, U> Protocol<I, U>
for ProtocolCompose<P1, P2, I, J, T, U>
{
fn handle_event(&mut self, packet: I) -> U {
let elem1 = self.protocol1.handle_event(packet);
self.protocol2.handle_event(elem1)
}
}
/// High level protocol that used for the overall application
///
/// Is meant to be composed on top of other protocols
pub struct SparseProtocol {}
/// Protocol for embedding and extracting data in and from DNS requests
pub struct DnsProtocol {}
/// Protocol for raw TCP
pub struct TcpProtocol {}
/// Protocol for HTTP over TCP
///
/// Run for bind shells, this will likely be used even with an HTTP
/// server running, as the port can be "shared" with pcap
pub struct HttpProtocol {}