diff --git a/crates/matrix-sdk-common/src/deserialized_responses.rs b/crates/matrix-sdk-common/src/deserialized_responses.rs index c63a0e42968..ea41fd2f3b2 100644 --- a/crates/matrix-sdk-common/src/deserialized_responses.rs +++ b/crates/matrix-sdk-common/src/deserialized_responses.rs @@ -176,6 +176,7 @@ pub enum VerificationLevel { /// The message was sent by a user identity we have not verified, but the /// user was previously verified. + #[serde(alias = "PreviouslyVerified")] VerificationViolation, /// The message was sent by a device not linked to (signed by) any user @@ -259,6 +260,7 @@ pub enum ShieldStateCode { /// An unencrypted event in an encrypted room. SentInClear, /// The sender was previously verified but changed their identity. + #[serde(alias = "PreviouslyVerified")] VerificationViolation, } @@ -808,7 +810,7 @@ mod tests { TimelineEventKind, UnableToDecryptInfo, UnableToDecryptReason, UnsignedDecryptionResult, UnsignedEventLocation, VerificationState, }; - use crate::deserialized_responses::{DeviceLinkProblem, VerificationLevel}; + use crate::deserialized_responses::{DeviceLinkProblem, ShieldStateCode, VerificationLevel}; fn example_event() -> serde_json::Value { json!({ @@ -883,6 +885,74 @@ mod tests { ); } + #[test] + fn test_verification_level_deserializes() { + // Given a JSON VerificationLevel + #[derive(Deserialize)] + struct Container { + verification_level: VerificationLevel, + } + let container = json!({ "verification_level": "VerificationViolation" }); + + // When we deserialize it + let deserialized: Container = serde_json::from_value(container) + .expect("We can deserialize the old PreviouslyVerified value"); + + // Then it is populated correctly + assert_eq!(deserialized.verification_level, VerificationLevel::VerificationViolation); + } + + #[test] + fn test_verification_level_deserializes_from_old_previously_verified_value() { + // Given a JSON VerificationLevel with the old value PreviouslyVerified + #[derive(Deserialize)] + struct Container { + verification_level: VerificationLevel, + } + let container = json!({ "verification_level": "PreviouslyVerified" }); + + // When we deserialize it + let deserialized: Container = serde_json::from_value(container) + .expect("We can deserialize the old PreviouslyVerified value"); + + // Then it is migrated to the new value + assert_eq!(deserialized.verification_level, VerificationLevel::VerificationViolation); + } + + #[test] + fn test_shield_state_code_deserializes() { + // Given a JSON ShieldStateCode with value VerificationViolation + #[derive(Deserialize)] + struct Container { + shield_state_code: ShieldStateCode, + } + let container = json!({ "shield_state_code": "VerificationViolation" }); + + // When we deserialize it + let deserialized: Container = serde_json::from_value(container) + .expect("We can deserialize the old PreviouslyVerified value"); + + // Then it is populated correctly + assert_eq!(deserialized.shield_state_code, ShieldStateCode::VerificationViolation); + } + + #[test] + fn test_shield_state_code_deserializes_from_old_previously_verified_value() { + // Given a JSON ShieldStateCode with the old value PreviouslyVerified + #[derive(Deserialize)] + struct Container { + shield_state_code: ShieldStateCode, + } + let container = json!({ "shield_state_code": "PreviouslyVerified" }); + + // When we deserialize it + let deserialized: Container = serde_json::from_value(container) + .expect("We can deserialize the old PreviouslyVerified value"); + + // Then it is migrated to the new value + assert_eq!(deserialized.shield_state_code, ShieldStateCode::VerificationViolation); + } + #[test] fn sync_timeline_event_serialisation() { let room_event = SyncTimelineEvent { diff --git a/crates/matrix-sdk-crypto/src/identities/user.rs b/crates/matrix-sdk-crypto/src/identities/user.rs index bbfdf54c4ee..be1f54e4011 100644 --- a/crates/matrix-sdk-crypto/src/identities/user.rs +++ b/crates/matrix-sdk-crypto/src/identities/user.rs @@ -911,6 +911,7 @@ enum OwnUserIdentityVerifiedState { NeverVerified, /// We previously verified this identity, but it has changed. + #[serde(alias = "PreviouslyVerifiedButNoLonger")] VerificationViolation, /// We have verified the current identity. @@ -1530,26 +1531,10 @@ pub(crate) mod tests { /// that we can deserialize boolean values. #[test] fn test_deserialize_own_user_identity_bool_verified() { - let mut json = json!({ - "user_id": "@example:localhost", - "master_key": { - "user_id":"@example:localhost", - "usage":["master"], - "keys":{"ed25519:rJ2TAGkEOP6dX41Ksll6cl8K3J48l8s/59zaXyvl2p0":"rJ2TAGkEOP6dX41Ksll6cl8K3J48l8s/59zaXyvl2p0"}, - }, - "self_signing_key": { - "user_id":"@example:localhost", - "usage":["self_signing"], - "keys":{"ed25519:0C8lCBxrvrv/O7BQfsKnkYogHZX3zAgw3RfJuyiq210":"0C8lCBxrvrv/O7BQfsKnkYogHZX3zAgw3RfJuyiq210"} - }, - "user_signing_key": { - "user_id":"@example:localhost", - "usage":["user_signing"], - "keys":{"ed25519:DU9z4gBFKFKCk7a13sW9wjT0Iyg7Hqv5f0BPM7DEhPo":"DU9z4gBFKFKCk7a13sW9wjT0Iyg7Hqv5f0BPM7DEhPo"} - }, - "verified": false - }); + let mut json = own_user_identity_data(); + // Set `"verified": false` + *json.get_mut("verified").unwrap() = false.into(); let id: OwnUserIdentityData = serde_json::from_value(json.clone()).unwrap(); assert_eq!(*id.verified.read().unwrap(), OwnUserIdentityVerifiedState::NeverVerified); @@ -1559,6 +1544,38 @@ pub(crate) mod tests { assert_eq!(*id.verified.read().unwrap(), OwnUserIdentityVerifiedState::Verified); } + #[test] + fn test_own_user_identity_verified_state_verification_violation_deserializes() { + // Given data containing verified: VerificationViolation + let mut json = own_user_identity_data(); + *json.get_mut("verified").unwrap() = "VerificationViolation".into(); + + // When we deserialize + let id: OwnUserIdentityData = serde_json::from_value(json.clone()).unwrap(); + + // Then the value is correctly populated + assert_eq!( + *id.verified.read().unwrap(), + OwnUserIdentityVerifiedState::VerificationViolation + ); + } + + #[test] + fn test_own_user_identity_verified_state_previously_verified_deserializes() { + // Given data containing verified: PreviouslyVerifiedButNoLonger + let mut json = own_user_identity_data(); + *json.get_mut("verified").unwrap() = "PreviouslyVerifiedButNoLonger".into(); + + // When we deserialize + let id: OwnUserIdentityData = serde_json::from_value(json.clone()).unwrap(); + + // Then the old value is re-interpreted as VerificationViolation + assert_eq!( + *id.verified.read().unwrap(), + OwnUserIdentityVerifiedState::VerificationViolation + ); + } + #[test] fn own_identity_check_signatures() { let response = own_key_query(); @@ -1895,4 +1912,26 @@ pub(crate) mod tests { assert!(!own_identity.was_previously_verified()); assert!(!own_identity.has_verification_violation()); } + + fn own_user_identity_data() -> Value { + json!({ + "user_id": "@example:localhost", + "master_key": { + "user_id":"@example:localhost", + "usage":["master"], + "keys":{"ed25519:rJ2TAGkEOP6dX41Ksll6cl8K3J48l8s/59zaXyvl2p0":"rJ2TAGkEOP6dX41Ksll6cl8K3J48l8s/59zaXyvl2p0"}, + }, + "self_signing_key": { + "user_id":"@example:localhost", + "usage":["self_signing"], + "keys":{"ed25519:0C8lCBxrvrv/O7BQfsKnkYogHZX3zAgw3RfJuyiq210":"0C8lCBxrvrv/O7BQfsKnkYogHZX3zAgw3RfJuyiq210"} + }, + "user_signing_key": { + "user_id":"@example:localhost", + "usage":["user_signing"], + "keys":{"ed25519:DU9z4gBFKFKCk7a13sW9wjT0Iyg7Hqv5f0BPM7DEhPo":"DU9z4gBFKFKCk7a13sW9wjT0Iyg7Hqv5f0BPM7DEhPo"} + }, + "verified": false + }) + } } diff --git a/crates/matrix-sdk-crypto/src/olm/group_sessions/sender_data.rs b/crates/matrix-sdk-crypto/src/olm/group_sessions/sender_data.rs index df54390e580..0be07403e00 100644 --- a/crates/matrix-sdk-crypto/src/olm/group_sessions/sender_data.rs +++ b/crates/matrix-sdk-crypto/src/olm/group_sessions/sender_data.rs @@ -215,6 +215,7 @@ enum SenderDataReader { legacy_session: bool, }, + #[serde(alias = "SenderUnverifiedButPreviouslyVerified")] VerificationViolation(KnownSenderData), SenderUnverified(KnownSenderData), @@ -286,7 +287,10 @@ mod tests { use vodozemac::Ed25519PublicKey; use super::SenderData; - use crate::types::{DeviceKeys, Signatures}; + use crate::{ + olm::KnownSenderData, + types::{DeviceKeys, Signatures}, + }; #[test] fn serializing_unknown_device_correctly_preserves_owner_check_failed_if_true() { @@ -360,6 +364,47 @@ mod tests { assert_let!(SenderData::SenderVerified { .. } = end); } + #[test] + fn deserializing_sender_unverified_but_previously_verified_migrates_to_verification_violation() + { + let json = r#" + { + "SenderUnverifiedButPreviouslyVerified":{ + "user_id":"@u:s.co", + "master_key":[ + 150,140,249,139,141,29,63,230,179,14,213,175,176,61,11,255, + 26,103,10,51,100,154,183,47,181,117,87,204,33,215,241,92 + ], + "master_key_verified":true + } + } + "#; + + let end: SenderData = serde_json::from_str(json).expect("Failed to parse!"); + assert_let!(SenderData::VerificationViolation(KnownSenderData { user_id, .. }) = end); + assert_eq!(user_id, owned_user_id!("@u:s.co")); + } + + #[test] + fn deserializing_verification_violation() { + let json = r#" + { + "VerificationViolation":{ + "user_id":"@u:s.co", + "master_key":[ + 150,140,249,139,141,29,63,230,179,14,213,175,176,61,11,255, + 26,103,10,51,100,154,183,47,181,117,87,204,33,215,241,92 + ], + "master_key_verified":true + } + } + "#; + + let end: SenderData = serde_json::from_str(json).expect("Failed to parse!"); + assert_let!(SenderData::VerificationViolation(KnownSenderData { user_id, .. }) = end); + assert_eq!(user_id, owned_user_id!("@u:s.co")); + } + #[test] fn equal_sessions_have_same_trust_level() { let unknown = SenderData::unknown();