Check both version and type in message header (#4918)

* Move client type to the client code

* Check both version and type in header
This commit is contained in:
Bogdan-Ștefan Neacşu
2024-09-23 17:57:03 +02:00
committed by GitHub
parent 2a94ce6443
commit 179d214e21
9 changed files with 34 additions and 38 deletions
Generated
+1
View File
@@ -4236,6 +4236,7 @@ dependencies = [
"nym-id",
"nym-network-defaults",
"nym-sdk",
"nym-service-provider-requests-common",
"nym-service-providers-common",
"nym-sphinx",
"nym-task",
+1 -1
View File
@@ -5,7 +5,7 @@ pub mod registration;
pub mod request;
pub mod response;
pub use registration::{ClientMac, ClientMessage, GatewayClient, InitMessage, Nonce};
pub use registration::{ClientMac, GatewayClient, InitMessage, Nonce};
#[cfg(feature = "verify")]
pub use registration::HmacSha256;
@@ -28,14 +28,6 @@ pub type Taken = Option<SystemTime>;
pub const BANDWIDTH_CAP_PER_DAY: u64 = 1024 * 1024 * 1024; // 1 GB
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(tag = "type", rename_all = "camelCase")]
pub enum ClientMessage {
Initial(InitMessage),
Final(GatewayClient),
Query(PeerPublicKey),
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct InitMessage {
/// Base64 encoded x25519 public key
@@ -29,14 +29,6 @@ pub type Taken = Option<SystemTime>;
pub const BANDWIDTH_CAP_PER_DAY: u64 = 1024 * 1024 * 1024; // 1 GB
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(tag = "type", rename_all = "camelCase")]
pub enum ClientMessage {
Initial(InitMessage),
Final(GatewayClient),
Query(PeerPublicKey),
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct InitMessage {
/// Base64 encoded x25519 public key
@@ -100,20 +100,17 @@ mod tests {
use std::str::FromStr;
#[test]
fn check_first_byte_version() {
fn check_first_bytes_protocol() {
let version = 2;
let data = AuthenticatorRequest {
protocol: Protocol {
version,
service_provider_type: ServiceProviderType::Authenticator,
},
protocol: Protocol { version, service_provider_type: ServiceProviderType::Authenticator },
data: AuthenticatorRequestData::Initial(InitMessage::new(
PeerPublicKey::from_str("yvNUDpT5l7W/xDhiu6HkqTHDQwbs/B3J5UrLmORl1EQ=").unwrap(),
)),
reply_to: Recipient::try_from_base58_string("D1rrpsysCGCYXy9saP8y3kmNpGtJZUXN9SvFoUcqAsM9.9Ssso1ea5NfkbMASdiseDSjTN1fSWda5SgEVjdSN4CvV@GJqd3ZxpXWSNxTfx7B1pPtswpetH4LnJdFeLeuY5KUuN").unwrap(),
request_id: 1,
};
let bytes = data.to_bytes().unwrap();
assert_eq!(*bytes.first().unwrap(), version);
let bytes = *data.to_bytes().unwrap().first_chunk::<2>().unwrap();
assert_eq!(bytes, [version, ServiceProviderType::Authenticator as u8]);
}
}
@@ -4,10 +4,11 @@
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Serialize, Deserialize)]
#[repr(u8)]
pub enum ServiceProviderType {
Authenticator,
IpPacketRouter,
NetworkRequester,
NetworkRequester = 0,
IpPacketRouter = 1,
Authenticator = 2,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
@@ -44,6 +44,7 @@ nym-id = { path = "../../common/nym-id" }
nym-network-defaults = { path = "../../common/network-defaults" }
nym-sdk = { path = "../../sdk/rust/nym-sdk" }
nym-service-providers-common = { path = "../common" }
nym-service-provider-requests-common = { path = "../../common/service-provider-requests-common" }
nym-sphinx = { path = "../../common/nymsphinx" }
nym-task = { path = "../../common/task" }
nym-types = { path = "../../common/types" }
+5 -2
View File
@@ -20,8 +20,8 @@ pub enum AuthenticatorError {
#[error("the entity wrapping the network requester has disconnected")]
DisconnectedParent,
#[error("received empty packet")]
EmptyPacket,
#[error("received too short packet")]
ShortPacket,
#[error("failed local version check, client and config mismatch")]
FailedLocalVersionCheck,
@@ -50,6 +50,9 @@ pub enum AuthenticatorError {
#[error("internal error: {0}")]
InternalError(String),
#[error("received packet has an invalid type: {0}")]
InvalidPacketType(u8),
#[error("received packet has an invalid version: {0}")]
InvalidPacketVersion(u8),
@@ -32,6 +32,7 @@ use nym_crypto::asymmetric::x25519::KeyPair;
use nym_gateway_requests::models::CredentialSpendingRequest;
use nym_gateway_storage::Storage;
use nym_sdk::mixnet::{InputMessage, MixnetMessageSender, Recipient, TransmissionLane};
use nym_service_provider_requests_common::ServiceProviderType;
use nym_sphinx::receiver::ReconstructedMessage;
use nym_task::TaskHandle;
use nym_wireguard::WireguardGatewayData;
@@ -432,20 +433,28 @@ impl<S: Storage + Clone + 'static> MixnetListener<S> {
fn deserialize_request(reconstructed: &ReconstructedMessage) -> Result<AuthenticatorRequest> {
let request_version = *reconstructed
.message
.first()
.ok_or(AuthenticatorError::EmptyPacket)?;
.first_chunk::<2>()
.ok_or(AuthenticatorError::ShortPacket)?;
// Check version of the request and convert to the latest version if necessary
match request_version {
1 => v1::request::AuthenticatorRequest::from_reconstructed_message(reconstructed)
[1, _] => v1::request::AuthenticatorRequest::from_reconstructed_message(reconstructed)
.map_err(|err| AuthenticatorError::FailedToDeserializeTaggedPacket { source: err })
.map(Into::into),
2 => v2::request::AuthenticatorRequest::from_reconstructed_message(reconstructed)
.map_err(|err| AuthenticatorError::FailedToDeserializeTaggedPacket { source: err })
.map(Into::into),
_ => {
log::info!("Received packet with invalid version: v{request_version}");
Err(AuthenticatorError::InvalidPacketVersion(request_version))
[2, request_type] => {
if request_type == ServiceProviderType::Authenticator as u8 {
v2::request::AuthenticatorRequest::from_reconstructed_message(reconstructed)
.map_err(|err| AuthenticatorError::FailedToDeserializeTaggedPacket {
source: err,
})
.map(Into::into)
} else {
Err(AuthenticatorError::InvalidPacketType(request_type))
}
}
[version, _] => {
log::info!("Received packet with invalid version: v{version}");
Err(AuthenticatorError::InvalidPacketVersion(version))
}
}
}