diff --git a/common/gateway-requests/src/types/error.rs b/common/gateway-requests/src/types/error.rs index 0a785e60ecd..edd8e41b22c 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 6015beb8ad4..6c4c8849574 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 84d01817dea..3f161750a12 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" @@ -1522,18 +1529,18 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.25" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.217" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] @@ -1558,9 +1565,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.217" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", @@ -1777,9 +1784,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.37" +version = "0.3.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" +checksum = "dad298b01a40a23aac4580b67e3dbedb7cc8402f3592d7f49469de2ea4aecdd8" dependencies = [ "deranged", "itoa", @@ -1794,15 +1801,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" +checksum = "765c97a5b985b7c11d7bc27fa927dc4fe6af3a6dfb021d28deb60d3bf51e76ef" [[package]] name = "time-macros" -version = "0.2.19" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" +checksum = "e8093bc3e81c3bc5f7879de09619d06c9a5a5e45ca44dfeeb7225bae38005c5c" dependencies = [ "num-conv", "time-core", @@ -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 1f6db8f0b85..363ddbb88e5 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 a5711178951..8347cb007e8 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 bd1f9fd6014..f7f210791e9 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 a582a247354..c13df9f2413 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 c5a4a542ed8..0fcf54d9dd5 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 a56e0442e0b..0dae4e17dba 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, }, ) } diff --git a/nym-wallet/Cargo.lock b/nym-wallet/Cargo.lock index b2a22e4a9da..3e23655033e 100644 --- a/nym-wallet/Cargo.lock +++ b/nym-wallet/Cargo.lock @@ -1583,9 +1583,9 @@ dependencies = [ [[package]] name = "ff" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" dependencies = [ "rand_core 0.6.4", "subtle", @@ -5063,18 +5063,18 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.25" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.217" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] @@ -5090,18 +5090,18 @@ dependencies = [ [[package]] name = "serde_bytes" -version = "0.11.16" +version = "0.11.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "364fec0df39c49a083c9a8a18a23a6bcfd9af130fe9fe321d18520a0d113e09e" +checksum = "8437fd221bde2d4ca316d61b90e337e9e702b3820b87d63caa9ba6c02bd06d96" dependencies = [ "serde", ] [[package]] name = "serde_derive" -version = "1.0.217" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", @@ -6056,9 +6056,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.37" +version = "0.3.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" +checksum = "dad298b01a40a23aac4580b67e3dbedb7cc8402f3592d7f49469de2ea4aecdd8" dependencies = [ "deranged", "itoa 1.0.9", @@ -6073,15 +6073,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" +checksum = "765c97a5b985b7c11d7bc27fa927dc4fe6af3a6dfb021d28deb60d3bf51e76ef" [[package]] name = "time-macros" -version = "0.2.19" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" +checksum = "e8093bc3e81c3bc5f7879de09619d06c9a5a5e45ca44dfeeb7225bae38005c5c" dependencies = [ "num-conv", "time-core", @@ -6114,9 +6114,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.43.0" +version = "1.44.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" +checksum = "9975ea0f48b5aa3972bf2d888c238182458437cc2a19374b81b25cdf1023fb3a" dependencies = [ "backtrace", "bytes",