diff --git a/common/gateway-requests/src/types/error.rs b/common/gateway-requests/src/types/error.rs index 0a785e60ec..edd8e41b22 100644 --- a/common/gateway-requests/src/types/error.rs +++ b/common/gateway-requests/src/types/error.rs @@ -10,6 +10,7 @@ use nym_sphinx::params::packet_sizes::PacketSize; use serde::{Deserialize, Serialize}; use std::string::FromUtf8Error; use thiserror::Error; +use time::OffsetDateTime; // specific errors (that should not be nested!!) for clients to match on #[derive(Debug, Copy, Clone, Error, Serialize, Deserialize)] @@ -112,15 +113,15 @@ pub enum AuthenticationFailure { #[error("failed to verify request signature")] InvalidSignature(#[from] SignatureError), - #[error("provided request timestamp is in the future")] - RequestTimestampInFuture, - #[error("the client is not registered")] NotRegistered, - #[error("the provided request is too stale to process")] - StaleRequest, + #[error("the provided request timestamp is excessively skewed. got {received} whilst the server time is {server}")] + ExcessiveTimestampSkew { + received: OffsetDateTime, + server: OffsetDateTime, + }, - #[error("the provided request timestamp is smaller or equal to a one previously used")] + #[error("the provided request timestamp is smaller or equal to one previously used")] RequestReuse, } diff --git a/common/gateway-requests/src/types/text_request/authenticate.rs b/common/gateway-requests/src/types/text_request/authenticate.rs index 6015beb8ad..6c4c884957 100644 --- a/common/gateway-requests/src/types/text_request/authenticate.rs +++ b/common/gateway-requests/src/types/text_request/authenticate.rs @@ -38,13 +38,22 @@ impl AuthenticateRequest { }) } - pub fn verify_timestamp(&self, max_request_age: Duration) -> Result<(), AuthenticationFailure> { + pub fn verify_timestamp( + &self, + max_request_timestamp_skew: Duration, + ) -> Result<(), AuthenticationFailure> { let now = OffsetDateTime::now_utc(); - if self.content.request_timestamp() + max_request_age < now { - return Err(AuthenticationFailure::StaleRequest); + if self.content.request_timestamp() < now - max_request_timestamp_skew { + return Err(AuthenticationFailure::ExcessiveTimestampSkew { + received: self.content.request_timestamp(), + server: now, + }); } - if self.content.request_timestamp() > now { - return Err(AuthenticationFailure::RequestTimestampInFuture); + if self.content.request_timestamp() - max_request_timestamp_skew > now { + return Err(AuthenticationFailure::ExcessiveTimestampSkew { + received: self.content.request_timestamp(), + server: now, + }); } Ok(()) } diff --git a/contracts/Cargo.lock b/contracts/Cargo.lock index af830109c4..3f161750a1 100644 --- a/contracts/Cargo.lock +++ b/contracts/Cargo.lock @@ -1185,6 +1185,7 @@ name = "nym-pemstore" version = "0.3.0" dependencies = [ "pem", + "tracing", ] [[package]] @@ -1251,6 +1252,12 @@ dependencies = [ "regex", ] +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + [[package]] name = "pkcs8" version = "0.9.0" @@ -1840,6 +1847,37 @@ dependencies = [ "winnow", ] +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + +[[package]] +name = "tracing-core" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +dependencies = [ + "once_cell", +] + [[package]] name = "typenum" version = "1.18.0" diff --git a/gateway/src/config.rs b/gateway/src/config.rs index 1f6db8f0b8..363ddbb88e 100644 --- a/gateway/src/config.rs +++ b/gateway/src/config.rs @@ -102,8 +102,8 @@ pub struct Debug { pub zk_nym_tickets: ZkNymTicketHandlerDebug, - /// Defines the maximum age of a signed authentication request before it's deemed too stale to process. - pub maximum_auth_request_age: Duration, + /// Defines the timestamp skew of a signed authentication request before it's deemed too excessive to process. + pub max_request_timestamp_skew: Duration, } #[derive(Debug, Clone)] diff --git a/gateway/src/node/client_handling/websocket/common_state.rs b/gateway/src/node/client_handling/websocket/common_state.rs index a571117895..8347cb007e 100644 --- a/gateway/src/node/client_handling/websocket/common_state.rs +++ b/gateway/src/node/client_handling/websocket/common_state.rs @@ -14,7 +14,7 @@ use std::time::Duration; #[derive(Clone)] pub(crate) struct Config { pub(crate) enforce_zk_nym: bool, - pub(crate) max_auth_request_age: Duration, + pub(crate) max_request_timestamp_skew: Duration, pub(crate) bandwidth: BandwidthFlushingBehaviourConfig, } diff --git a/gateway/src/node/client_handling/websocket/connection_handler/fresh.rs b/gateway/src/node/client_handling/websocket/connection_handler/fresh.rs index bd1f9fd601..f7f210791e 100644 --- a/gateway/src/node/client_handling/websocket/connection_handler/fresh.rs +++ b/gateway/src/node/client_handling/websocket/connection_handler/fresh.rs @@ -641,7 +641,7 @@ impl FreshHandler { // do cheap checks first // is the provided timestamp relatively recent (and not in the future?) - request.verify_timestamp(self.shared_state.cfg.max_auth_request_age)?; + request.verify_timestamp(self.shared_state.cfg.max_request_timestamp_skew)?; // does the message signature verify? request.verify_signature()?; diff --git a/gateway/src/node/mod.rs b/gateway/src/node/mod.rs index a582a24735..c13df9f241 100644 --- a/gateway/src/node/mod.rs +++ b/gateway/src/node/mod.rs @@ -251,7 +251,7 @@ impl GatewayTasksBuilder { let shared_state = websocket::CommonHandlerState { cfg: websocket::Config { enforce_zk_nym: self.config.gateway.enforce_zk_nyms, - max_auth_request_age: self.config.debug.maximum_auth_request_age, + max_request_timestamp_skew: self.config.debug.max_request_timestamp_skew, bandwidth: (&self.config).into(), }, ecash_verifier: self.ecash_manager().await?, diff --git a/nym-node/src/config/gateway_tasks.rs b/nym-node/src/config/gateway_tasks.rs index c5a4a542ed..0fcf54d9dd 100644 --- a/nym-node/src/config/gateway_tasks.rs +++ b/nym-node/src/config/gateway_tasks.rs @@ -54,8 +54,9 @@ pub struct Debug { /// of the services providers pub minimum_mix_performance: u8, - /// Defines the maximum age of a signed authentication request before it's deemed too stale to process. - pub maximum_auth_request_age: Duration, + /// Defines the timestamp skew of a signed authentication request before it's deemed too excessive to process. + #[serde(alias = "maximum_auth_request_age")] + pub max_request_timestamp_skew: Duration, pub stale_messages: StaleMessageDebug, @@ -67,7 +68,7 @@ pub struct Debug { impl Debug { pub const DEFAULT_MESSAGE_RETRIEVAL_LIMIT: i64 = 100; pub const DEFAULT_MINIMUM_MIX_PERFORMANCE: u8 = 50; - pub const DEFAULT_MAXIMUM_AUTH_REQUEST_AGE: Duration = Duration::from_secs(30); + pub const DEFAULT_MAXIMUM_AUTH_REQUEST_TIMESTAMP_SKEW: Duration = Duration::from_secs(120); pub const DEFAULT_MAXIMUM_OPEN_CONNECTIONS: usize = 8192; } @@ -76,7 +77,7 @@ impl Default for Debug { Debug { message_retrieval_limit: Self::DEFAULT_MESSAGE_RETRIEVAL_LIMIT, maximum_open_connections: Self::DEFAULT_MAXIMUM_OPEN_CONNECTIONS, - maximum_auth_request_age: Self::DEFAULT_MAXIMUM_AUTH_REQUEST_AGE, + max_request_timestamp_skew: Self::DEFAULT_MAXIMUM_AUTH_REQUEST_TIMESTAMP_SKEW, minimum_mix_performance: Self::DEFAULT_MINIMUM_MIX_PERFORMANCE, stale_messages: Default::default(), client_bandwidth: Default::default(), diff --git a/nym-node/src/config/helpers.rs b/nym-node/src/config/helpers.rs index a56e0442e0..0dae4e17db 100644 --- a/nym-node/src/config/helpers.rs +++ b/nym-node/src/config/helpers.rs @@ -60,7 +60,7 @@ fn ephemeral_gateway_config(config: &Config) -> nym_gateway::config::Config { .zk_nym_tickets .maximum_time_between_redemption, }, - maximum_auth_request_age: config.gateway_tasks.debug.maximum_auth_request_age, + max_request_timestamp_skew: config.gateway_tasks.debug.max_request_timestamp_skew, }, ) }