Check timestamp

This commit is contained in:
Jon Häggblad
2024-05-28 15:10:45 +02:00
parent d4d3041816
commit a374bca601
6 changed files with 41 additions and 16 deletions
Generated
+1
View File
@@ -4826,6 +4826,7 @@ dependencies = [
"serde_json",
"tap",
"thiserror",
"time",
"tokio",
"tokio-tun",
"tokio-util",
@@ -257,6 +257,10 @@ impl SignedRequest for SignedStaticConnectRequest {
fn signature(&self) -> Option<&Vec<u8>> {
self.signature.as_ref()
}
fn timestamp(&self) -> OffsetDateTime {
self.request.timestamp
}
}
// A dynamic connect request is when the client does not provide the internal IP address it will use
@@ -314,6 +318,10 @@ impl SignedRequest for SignedDynamicConnectRequest {
fn signature(&self) -> Option<&Vec<u8>> {
self.signature.as_ref()
}
fn timestamp(&self) -> OffsetDateTime {
self.request.timestamp
}
}
// A disconnect request is when the client wants to disconnect from the ip packet router and free
@@ -359,6 +367,10 @@ impl SignedRequest for SignedDisconnectRequest {
fn signature(&self) -> Option<&Vec<u8>> {
self.signature.as_ref()
}
fn timestamp(&self) -> OffsetDateTime {
self.request.timestamp
}
}
// A data request is when the client wants to send an IP packet to a destination.
@@ -277,6 +277,8 @@ pub enum StaticConnectFailureReason {
RequestedIpAlreadyInUse,
#[error("requested nym-address is already in use")]
RequestedNymAddressAlreadyInUse,
#[error("request timestamp is out of date")]
OutOfDateTimestamp,
#[error("{0}")]
Other(String),
}
@@ -1,3 +1,5 @@
use std::time::Duration;
use nym_crypto::asymmetric::{ed25519::Ed25519RecoveryError, identity};
#[derive(thiserror::Error, Debug)]
@@ -17,6 +19,9 @@ pub enum SignatureError {
error: Box<bincode::ErrorKind>,
},
#[error("signature verification failed: request out of date")]
RequestOutOfDate,
#[error("signature verification failed")]
VerificationFailed {
message: String,
@@ -31,8 +36,15 @@ pub trait SignedRequest {
fn signature(&self) -> Option<&Vec<u8>>;
fn timestamp(&self) -> time::OffsetDateTime;
fn verify(&self) -> Result<(), SignatureError> {
if let Some(signature) = self.signature() {
// First check that the request is recent enough
if time::OffsetDateTime::now_utc() - self.timestamp() > Duration::from_secs(10) {
return Err(SignatureError::RequestOutOfDate);
}
let request_as_bytes = self.request()?;
let signature = identity::Signature::from_bytes(signature).map_err(|error| {
SignatureError::SignatureParseError {
@@ -22,6 +22,7 @@ nym-client-core = { path = "../../common/client-core" }
nym-config = { path = "../../common/config" }
nym-crypto = { path = "../../common/crypto" }
nym-exit-policy = { path = "../../common/exit-policy" }
nym-id = { path = "../../common/nym-id" }
nym-ip-packet-requests = { path = "../../common/ip-packet-requests" }
nym-network-defaults = { path = "../../common/network-defaults" }
nym-network-requester = { path = "../network-requester" }
@@ -33,13 +34,13 @@ nym-tun = { path = "../../common/tun" }
nym-types = { path = "../../common/types" }
nym-wireguard = { path = "../../common/wireguard" }
nym-wireguard-types = { path = "../../common/wireguard-types" }
nym-id = { path = "../../common/nym-id" }
rand = "0.8.5"
reqwest.workspace = true
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
tap.workspace = true
thiserror = { workspace = true }
time = { workspace = true }
tokio = { workspace = true, features = ["rt-multi-thread", "net", "io-util"] }
tokio-util = { workspace = true, features = ["codec"] }
url.workspace = true
@@ -575,29 +575,17 @@ impl MixnetListener {
match request.data {
IpPacketRequestData::StaticConnect(signed_connect_request) => {
if let Err(err) = signed_connect_request.verify() {
if !matches!(err, SignatureError::MissingSignature) {
return Err(IpPacketRouterError::FailedToVerifyRequest { source: err });
}
}
verify_signed_request(&signed_connect_request)?;
let connect_request = signed_connect_request.request;
Ok(vec![self.on_static_connect_request(connect_request).await])
}
IpPacketRequestData::DynamicConnect(signed_connect_request) => {
if let Err(err) = signed_connect_request.verify() {
if !matches!(err, SignatureError::MissingSignature) {
return Err(IpPacketRouterError::FailedToVerifyRequest { source: err });
}
}
verify_signed_request(&signed_connect_request)?;
let connect_request = signed_connect_request.request;
Ok(vec![self.on_dynamic_connect_request(connect_request).await])
}
IpPacketRequestData::Disconnect(signed_disconnect_request) => {
if let Err(err) = signed_disconnect_request.verify() {
if !matches!(err, SignatureError::MissingSignature) {
return Err(IpPacketRouterError::FailedToVerifyRequest { source: err });
}
}
verify_signed_request(&signed_disconnect_request)?;
let disconnect_request = signed_disconnect_request.request;
Ok(vec![self.on_disconnect_request(disconnect_request)])
}
@@ -715,6 +703,15 @@ impl MixnetListener {
}
}
fn verify_signed_request(request: &impl SignedRequest) -> Result<()> {
if let Err(err) = request.verify() {
if !matches!(err, SignatureError::MissingSignature) {
return Err(IpPacketRouterError::FailedToVerifyRequest { source: err });
}
}
Ok(())
}
pub(crate) enum ConnectedClientEvent {
Disconnect(DisconnectEvent),
Connect(Box<ConnectEvent>),