libFenrir/src/connection/handshake/mod.rs
Luca Fulchir e71167224c
Track auth and service connections client side
Signed-off-by: Luca Fulchir <luca.fulchir@runesauth.com>
2023-05-26 15:02:21 +02:00

157 lines
4.1 KiB
Rust

//! Handhsake handling
pub mod dirsync;
use crate::{
connection::{self, ProtocolVersion},
enc::sym::{HeadLen, TagLen},
};
use ::num_traits::FromPrimitive;
use ::std::{rc::Rc, sync::Arc};
/// Handshake errors
#[derive(::thiserror::Error, Debug, Copy, Clone)]
pub enum Error {
/// Error while parsing the handshake packet
/// TODO: more detailed parsing errors
#[error("not an handshake packet")]
Parsing,
/// No such Key ID
#[error("unknown key id")]
UnknownKeyID,
/// Key error
#[error("key: {0:?}")]
Key(#[from] crate::enc::Error),
/// Not enough data
#[error("not enough data")]
NotEnoughData,
}
pub(crate) struct HandshakeServer {
pub id: crate::enc::asym::KeyID,
pub key: crate::enc::asym::PrivKey,
}
#[derive(Clone)]
pub(crate) struct HandshakeClient {
pub id: crate::enc::asym::KeyID,
pub key: crate::enc::asym::PrivKey,
pub service_id: crate::auth::ServiceID,
pub service_conn_id: connection::IDRecv,
pub connection: Rc<crate::connection::Connection>,
}
/// Parsed handshake
#[derive(Debug, Clone)]
pub enum HandshakeData {
/// Directory synchronized handhsake
DirSync(dirsync::DirSync),
}
impl HandshakeData {
/// actual length of the handshake data
pub fn len(&self) -> usize {
match self {
HandshakeData::DirSync(d) => d.len(),
}
}
/// Serialize into raw bytes
/// NOTE: assumes that there is exactly asa much buffer as needed
pub fn serialize(
&self,
head_len: HeadLen,
tag_len: TagLen,
out: &mut [u8],
) {
match self {
HandshakeData::DirSync(d) => d.serialize(head_len, tag_len, out),
}
}
}
/// Kind of handshake
#[derive(::num_derive::FromPrimitive, Debug, Clone, Copy)]
#[repr(u8)]
pub enum Kind {
/// 1-RTT, Directory synchronized handshake
/// Request
DirSyncReq = 0,
/// 1-RTT, Directory synchronized handshake
/// Response
DirSyncResp,
/*
/// 2-RTT, Stateful connection
Stateful,
...
/// 3 RTT, Stateless connection
Stateless,
....
*/
}
/// Parsed handshake
#[derive(Debug, Clone)]
pub struct Handshake {
/// Fenrir Protocol version
pub fenrir_version: ProtocolVersion,
/// enum for the parsed data
pub data: HandshakeData,
}
impl Handshake {
/// Build new handshake from the data
pub fn new(data: HandshakeData) -> Self {
Handshake {
fenrir_version: ProtocolVersion::V0,
data,
}
}
/// return the total length of the handshake
pub fn len(&self) -> usize {
ProtocolVersion::len() + self.data.len()
}
const MIN_PKT_LEN: usize = 8;
/// Parse the packet and return the parsed handshake
pub fn deserialize(raw: &[u8]) -> Result<Self, Error> {
if raw.len() < Self::MIN_PKT_LEN {
return Err(Error::NotEnoughData);
}
let fenrir_version = match ProtocolVersion::from_u8(raw[0]) {
Some(fenrir_version) => fenrir_version,
None => return Err(Error::Parsing),
};
let handshake_kind = match Kind::from_u8(raw[1]) {
Some(handshake_kind) => handshake_kind,
None => return Err(Error::Parsing),
};
let data = match handshake_kind {
Kind::DirSyncReq => dirsync::Req::deserialize(&raw[2..])?,
Kind::DirSyncResp => dirsync::Resp::deserialize(&raw[2..])?,
};
Ok(Self {
fenrir_version,
data,
})
}
/// serialize the handshake into bytes
/// NOTE: assumes that there is exactly as much buffer as needed
pub fn serialize(
&self,
head_len: HeadLen,
tag_len: TagLen,
out: &mut [u8],
) {
assert!(out.len() > 1, "Handshake: not enough buffer to serialize");
self.fenrir_version.serialize(&mut out[0]);
self.data.serialize(head_len, tag_len, &mut out[1..]);
}
pub(crate) fn work(&self, keys: &[HandshakeServer]) -> Result<(), Error> {
todo!()
}
}
trait HandshakeParsing {
fn deserialize(raw: &[u8]) -> Result<HandshakeData, Error>;
}