tests.rs (19506B)
1 use super::{ClientDataJsonParser as _, CollectedClientDataErr, LimitedVerificationParser}; 2 #[test] 3 fn parse_string() { 4 assert!( 5 LimitedVerificationParser::<true>::parse_string(br#"abc""#) 6 .is_ok_and(|tup| { tup.0 == "abc" && tup.1 == b"" }) 7 ); 8 assert!( 9 LimitedVerificationParser::<false>::parse_string(br#"abc"23"#) 10 .is_ok_and(|tup| { tup.0 == "abc" && tup.1 == b"23" }) 11 ); 12 assert!( 13 LimitedVerificationParser::<true>::parse_string(br#"ab\"c"23"#) 14 .is_ok_and(|tup| { tup.0 == r#"ab"c"# && tup.1 == b"23" }) 15 ); 16 assert!( 17 LimitedVerificationParser::<false>::parse_string(br#"ab\\c"23"#) 18 .is_ok_and(|tup| { tup.0 == r"ab\c" && tup.1 == b"23" }) 19 ); 20 assert!( 21 LimitedVerificationParser::<true>::parse_string(br#"ab\u001fc"23"#) 22 .is_ok_and(|tup| { tup.0 == "ab\u{001f}c" && tup.1 == b"23" }) 23 ); 24 assert!( 25 LimitedVerificationParser::<false>::parse_string(br#"ab\u000dc"23"#) 26 .is_ok_and(|tup| { tup.0 == "ab\u{000d}c" && tup.1 == b"23" }) 27 ); 28 assert!( 29 LimitedVerificationParser::<true>::parse_string(b"\\\\\\\\\\\\a\\\\\\\\a\\\\\"") 30 .is_ok_and(|tup| { tup.0 == "\\\\\\a\\\\a\\" && tup.1.is_empty() }) 31 ); 32 assert!( 33 LimitedVerificationParser::<false>::parse_string(b"\\\\\\\\\\a\\\\\\\\a\\\\\"") 34 .is_err_and(|e| matches!(e, CollectedClientDataErr::InvalidEscapedString),) 35 ); 36 assert!( 37 LimitedVerificationParser::<true>::parse_string(br#"ab\u0020c"23"#) 38 .is_err_and(|err| matches!(err, CollectedClientDataErr::InvalidEscapedString),) 39 ); 40 assert!( 41 LimitedVerificationParser::<false>::parse_string(br#"ab\ac"23"#) 42 .is_err_and(|err| matches!(err, CollectedClientDataErr::InvalidEscapedString),) 43 ); 44 assert!( 45 LimitedVerificationParser::<true>::parse_string(br#"ab\""#) 46 .is_err_and(|err| matches!(err, CollectedClientDataErr::InvalidObject),) 47 ); 48 assert!( 49 LimitedVerificationParser::<false>::parse_string(br#"ab\u001Fc"23"#) 50 .is_err_and(|err| matches!(err, CollectedClientDataErr::InvalidEscapedString),) 51 ); 52 assert!( 53 LimitedVerificationParser::<true>::parse_string([0, b'"'].as_slice()) 54 .is_err_and(|err| matches!(err, CollectedClientDataErr::InvalidEscapedString),) 55 ); 56 assert!( 57 LimitedVerificationParser::<false>::parse_string([b'a', 255, b'"'].as_slice()) 58 .is_err_and(|err| matches!(err, CollectedClientDataErr::Utf8(_))) 59 ); 60 assert!( 61 LimitedVerificationParser::<true>::parse_string([b'a', b'"', 255].as_slice()) 62 .is_ok_and(|tup| tup.0 == "a" && tup.1 == [255]) 63 ); 64 assert!( 65 LimitedVerificationParser::<false>::parse_string(br#"""#) 66 .is_ok_and(|tup| tup.0.is_empty() && tup.1.is_empty()) 67 ); 68 } 69 #[expect(clippy::cognitive_complexity, reason = "a lot of things to test")] 70 #[test] 71 fn c_data_json() { 72 assert!(LimitedVerificationParser::<true>::parse(br#"{"type":"webauthn.create","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://example.com","crossOrigin":false}"#.as_slice()).is_ok_and(|val| val.challenge.0 == 0 && val.origin.0 == "https://example.com" && !val.cross_origin && val.top_origin.is_none())); 73 assert!(LimitedVerificationParser::<true>::parse(br#"{"type":"webauthn.create","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://example.com","crossOrigin":false,{}}"#.as_slice()).is_ok_and(|val| val.challenge.0 == 0 && val.origin.0 == "https://example.com" && !val.cross_origin && val.top_origin.is_none())); 74 assert!(LimitedVerificationParser::<true>::parse(br#"{"type":"webauthn.create","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://example.com","crossOrigin":true}"#.as_slice()).is_ok_and(|val| val.challenge.0 == 0 && val.origin.0 == "https://example.com" && val.cross_origin && val.top_origin.is_none())); 75 assert!(LimitedVerificationParser::<true>::parse(br#"{"type":"webauthn.create","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://example.com","crossOrigin":true,"topOrigin":"bob"}"#.as_slice()).is_ok_and(|val| val.challenge.0 == 0 && val.origin.0 == "https://example.com" && val.cross_origin && val.top_origin.is_some_and(|v| v == "bob"))); 76 assert!(LimitedVerificationParser::<true>::parse(br#"{"type":"webauthn.create","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://example.com","crossOrigin":true,"topOrigin":"bob",a}"#.as_slice()).is_ok_and(|val| val.challenge.0 == 0 && val.origin.0 == "https://example.com" && val.cross_origin && val.top_origin.is_some_and(|v| v == "bob"))); 77 assert!(LimitedVerificationParser::<true>::parse(br#"{"type":"webauthn.create","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://example.com","crossOrigin":true,"topOrigin":"bob"a}"#.as_slice()).is_err_and(|e| matches!(e, CollectedClientDataErr::InvalidObject))); 78 assert!(LimitedVerificationParser::<true>::parse(br#"{"type":"webauthn.create","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://example.com","crossOrigin":false,"topOrigin":""}"#.as_slice()).is_err_and(|e| matches!(e, CollectedClientDataErr::TopOriginWithoutCrossOrigin))); 79 assert!(LimitedVerificationParser::<true>::parse(br#"{"type":"webauthn.create","challenge":"AAAAAAAAAAAAAAAAAAAAA","origin":"https://example.com","crossOrigin":false,"topOrigin":""}"#.as_slice()).is_err_and(|e| matches!(e, CollectedClientDataErr::Challenge))); 80 assert!(LimitedVerificationParser::<true>::parse(br#"{"type":"webauthn.create","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"","crossOrigin":false}"#.as_slice()).is_ok_and(|val| val.challenge.0 == 0 && val.origin.0.is_empty() && !val.cross_origin && val.top_origin.is_none())); 81 assert!(LimitedVerificationParser::<true>::parse(br#"{"type":"webauthn.get","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://example.com","crossOrigin":false}"#.as_slice()).is_err_and(|e| matches!(e, CollectedClientDataErr::Type))); 82 assert!(LimitedVerificationParser::<true>::parse(br#"{"type":"webauthn.create", "challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://example.com","crossOrigin":false}"#.as_slice()).is_err_and(|e| matches!(e, CollectedClientDataErr::ChallengeKey))); 83 assert!(LimitedVerificationParser::<true>::parse(br#"{"type":"webauthn.create","challenge":"AAAAAAAAAAAAAAAAAAAAAA","crossOrigin":false}"#.as_slice()).is_err_and(|e| matches!(e, CollectedClientDataErr::OriginKey))); 84 assert!(LimitedVerificationParser::<true>::parse(br#"{"type":"webauthn.create","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://exampl\\e.com","crossOrigin":false}"#.as_slice()).is_ok_and(|val| val.challenge.0 == 0 && val.origin.0 == "https://exampl\\e.com" && !val.cross_origin && val.top_origin.is_none())); 85 assert!(LimitedVerificationParser::<true>::parse(br#"{"type":"webauthn.create","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://exampl\"e.com","crossOrigin":false}"#.as_slice()).is_ok_and(|val| val.challenge.0 == 0 && val.origin.0 == "https://exampl\"e.com" && !val.cross_origin && val.top_origin.is_none())); 86 assert!(LimitedVerificationParser::<true>::parse(br#"{"type":"webauthn.create","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://exampl\u0013e.com","crossOrigin":false}"#.as_slice()).is_ok_and(|val| val.challenge.0 == 0 && val.origin.0 == "https://exampl\u{0013}e.com" && !val.cross_origin && val.top_origin.is_none())); 87 assert!(LimitedVerificationParser::<true>::parse(br#"{"type":"webauthn.create","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://exampl\3e.com","crossOrigin":false}"#.as_slice()).is_err_and(|e| matches!(e, CollectedClientDataErr::InvalidEscapedString))); 88 assert!(LimitedVerificationParser::<true>::parse(br#"{"type":"webauthn.create","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://exampl\e.com","crossOrigin":false}"#.as_slice()).is_err_and(|e| matches!(e, CollectedClientDataErr::InvalidEscapedString))); 89 assert!(LimitedVerificationParser::<true>::parse(br#"{"type":"webauthn.create","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://exampl\u0020.com","crossOrigin":false}"#.as_slice()).is_err_and(|e| matches!(e, CollectedClientDataErr::InvalidEscapedString))); 90 assert!(LimitedVerificationParser::<true>::parse(br#"{"type":"webauthn.create","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://exampl\u000A.com","crossOrigin":false}"#.as_slice()).is_err_and(|e| matches!(e, CollectedClientDataErr::InvalidEscapedString))); 91 assert!( 92 LimitedVerificationParser::<true>::parse([].as_slice()) 93 .is_err_and(|e| matches!(e, CollectedClientDataErr::Len)) 94 ); 95 assert!(LimitedVerificationParser::<true>::parse(br#"{"type":"abc","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://example.com","crossOrigin":false}"#.as_slice()).is_err_and(|e| matches!(e, CollectedClientDataErr::InvalidStart))); 96 assert!(LimitedVerificationParser::<true>::parse(br#"{"type":"webauthn.create","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://example.com","crossOrigin":false"#.as_slice()).is_err_and(|e| matches!(e, CollectedClientDataErr::InvalidObject))); 97 assert!(LimitedVerificationParser::<true>::parse(br#"{"type":"webauthn.create","challenge":"AAAAAAAAAAAAAAAAAAAAAA","crossOrigin":false,"origin":"example.com"}"#.as_slice()).is_err_and(|e| matches!(e, CollectedClientDataErr::OriginKey))); 98 assert!(LimitedVerificationParser::<true>::parse(br#"{"type":"webauthn.create","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://example.com","topOrigin":"bob","crossOrigin":true}"#.as_slice()).is_err_and(|e| matches!(e, CollectedClientDataErr::CrossOriginKey))); 99 assert!(LimitedVerificationParser::<true>::parse(br#"{"type":"webauthn.create","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://example.com","crossOrigin":"abc"}"#.as_slice()).is_err_and(|e| matches!(e, CollectedClientDataErr::CrossOrigin))); 100 assert!(LimitedVerificationParser::<true>::parse(br#"{"type":"webauthn.create","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://example.com","crossOrigin":true"a}"#.as_slice()).is_err_and(|e| matches!(e, CollectedClientDataErr::InvalidObject))); 101 assert!(LimitedVerificationParser::<true>::parse(br#"{"type":"webauthn.create","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://example.com","crossOrigin":true","topOrigin":"https://abc.com"a}"#.as_slice()).is_err_and(|e| matches!(e, CollectedClientDataErr::InvalidObject))); 102 assert!(LimitedVerificationParser::<false>::parse(br#"{"type":"webauthn.get","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://example.com","crossOrigin":false}"#.as_slice()).is_ok_and(|val| val.challenge.0 == 0 && val.origin.0 == "https://example.com" && !val.cross_origin && val.top_origin.is_none())); 103 assert!(LimitedVerificationParser::<false>::parse(b"{\"type\":\"webauthn.get\",\"challenge\":\"AAAAAAAAAAAAAAAAAAAAAA\",\"origin\":\"https://example.com\",\"crossOrigin\":false,\xff}".as_slice()).is_ok_and(|val| val.challenge.0 == 0 && val.origin.0 == "https://example.com" && !val.cross_origin && val.top_origin.is_none())); 104 assert!(LimitedVerificationParser::<false>::parse(br#"{"type":"webauthn.get","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://example.com","crossOrigin":true}"#.as_slice()).is_ok_and(|val| val.challenge.0 == 0 && val.origin.0 == "https://example.com" && val.cross_origin && val.top_origin.is_none())); 105 assert!(LimitedVerificationParser::<false>::parse(br#"{"type":"webauthn.get","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://example.com","crossOrigin":true,"topOrigin":"bob"}"#.as_slice()).is_ok_and(|val| val.challenge.0 == 0 && val.origin.0 == "https://example.com" && val.cross_origin && val.top_origin.is_some_and(|v| v == "bob"))); 106 assert!(LimitedVerificationParser::<false>::parse(br#"{"type":"webauthn.get","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://example.com","crossOrigin":false,"topOrigin":""}"#.as_slice()).is_err_and(|e| matches!(e, CollectedClientDataErr::TopOriginWithoutCrossOrigin))); 107 assert!(LimitedVerificationParser::<false>::parse(br#"{"type":"webauthn.get","challenge":"AAAAAAAAAAAAAAAAAAAAA","origin":"https://example.com","crossOrigin":false,"topOrigin":""}"#.as_slice()).is_err_and(|e| matches!(e, CollectedClientDataErr::Challenge))); 108 assert!(LimitedVerificationParser::<false>::parse(br#"{"type":"webauthn.get","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"","crossOrigin":false}"#.as_slice()).is_ok_and(|val| val.challenge.0 == 0 && val.origin.0.is_empty() && !val.cross_origin && val.top_origin.is_none())); 109 assert!(LimitedVerificationParser::<false>::parse(br#"{"type":"webauthn.create","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://example.com","crossOrigin":false}"#.as_slice()).is_err_and(|e| matches!(e, CollectedClientDataErr::Type))); 110 assert!(LimitedVerificationParser::<false>::parse(br#"{"type":"webauthn.get", "challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://example.com","crossOrigin":false}"#.as_slice()).is_err_and(|e| matches!(e, CollectedClientDataErr::ChallengeKey))); 111 assert!( 112 LimitedVerificationParser::<false>::parse( 113 br#"{"type":"webauthn.get","challenge":"AAAAAAAAAAAAAAAAAAAAAA","crossOrigin":false}"# 114 .as_slice() 115 ) 116 .is_err_and(|e| matches!(e, CollectedClientDataErr::OriginKey)) 117 ); 118 assert!(LimitedVerificationParser::<false>::parse(br#"{"type":"webauthn.get","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://exampl\\e.com","crossOrigin":false}"#.as_slice()).is_ok_and(|val| val.challenge.0 == 0 && val.origin.0 == "https://exampl\\e.com" && !val.cross_origin && val.top_origin.is_none())); 119 assert!(LimitedVerificationParser::<false>::parse(br#"{"type":"webauthn.get","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://exampl\"e.com","crossOrigin":false}"#.as_slice()).is_ok_and(|val| val.challenge.0 == 0 && val.origin.0 == "https://exampl\"e.com" && !val.cross_origin && val.top_origin.is_none())); 120 assert!(LimitedVerificationParser::<false>::parse(br#"{"type":"webauthn.get","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://exampl\u0013e.com","crossOrigin":false}"#.as_slice()).is_ok_and(|val| val.challenge.0 == 0 && val.origin.0 == "https://exampl\u{0013}e.com" && !val.cross_origin && val.top_origin.is_none())); 121 assert!(LimitedVerificationParser::<false>::parse(br#"{"type":"webauthn.get","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://exampl\3e.com","crossOrigin":false}"#.as_slice()).is_err_and(|e| matches!(e, CollectedClientDataErr::InvalidEscapedString))); 122 assert!(LimitedVerificationParser::<false>::parse(br#"{"type":"webauthn.get","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://exampl\e.com","crossOrigin":false}"#.as_slice()).is_err_and(|e| matches!(e, CollectedClientDataErr::InvalidEscapedString))); 123 assert!(LimitedVerificationParser::<false>::parse(br#"{"type":"webauthn.get","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://exampl\u0020.com","crossOrigin":false}"#.as_slice()).is_err_and(|e| matches!(e, CollectedClientDataErr::InvalidEscapedString))); 124 assert!(LimitedVerificationParser::<false>::parse(br#"{"type":"webauthn.get","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://exampl\u000A.com","crossOrigin":false}"#.as_slice()).is_err_and(|e| matches!(e, CollectedClientDataErr::InvalidEscapedString))); 125 assert!( 126 LimitedVerificationParser::<false>::parse([].as_slice()) 127 .is_err_and(|e| matches!(e, CollectedClientDataErr::Len)) 128 ); 129 assert!(LimitedVerificationParser::<false>::parse(br#"{"type":"abc","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://example.com","crossOrigin":false}"#.as_slice()).is_err_and(|e| matches!(e, CollectedClientDataErr::InvalidStart))); 130 assert!(LimitedVerificationParser::<false>::parse(br#"{"type":"webauthn.get","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://example.com","crossOrigin":false"#.as_slice()).is_err_and(|e| matches!(e, CollectedClientDataErr::InvalidObject))); 131 assert!(LimitedVerificationParser::<false>::parse(br#"{"type":"webauthn.get","challenge":"AAAAAAAAAAAAAAAAAAAAAA","crossOrigin":false,"origin":"example.com"}"#.as_slice()).is_err_and(|e| matches!(e, CollectedClientDataErr::OriginKey))); 132 assert!(LimitedVerificationParser::<false>::parse(br#"{"type":"webauthn.get","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://example.com","topOrigin":"bob","crossOrigin":true}"#.as_slice()).is_err_and(|e| matches!(e, CollectedClientDataErr::CrossOriginKey))); 133 assert!(LimitedVerificationParser::<false>::parse(br#"{"type":"webauthn.get","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://example.com","crossOrigin":"abc"}"#.as_slice()).is_err_and(|e| matches!(e, CollectedClientDataErr::CrossOrigin))); 134 assert!(LimitedVerificationParser::<false>::parse(br#"{"type":"webauthn.get","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://example.com","crossOrigin":true"a}"#.as_slice()).is_err_and(|e| matches!(e, CollectedClientDataErr::InvalidObject))); 135 assert!(LimitedVerificationParser::<true>::parse(br#"{"type":"webauthn.create","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://example.com","crossOrigin":true,"topOrigin":"https://example.com"}"#.as_slice()).is_err_and(|e| matches!(e, CollectedClientDataErr::TopOriginSameAsOrigin))); 136 assert!(LimitedVerificationParser::<true>::parse(br#"{"type":"webauthn.create","challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://example.com","crossOrigin":false,"foo":true}"#.as_slice()).is_ok_and(|val| val.challenge.0 == 0 && val.origin.0 == "https://example.com" && !val.cross_origin && val.top_origin.is_none())); 137 assert!(LimitedVerificationParser::<false>::parse(br#"{"type":"webauthn.get","challengE":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://example.com","crossOrigin":false,"foo":true}"#.as_slice()).is_err_and(|e| matches!(e, CollectedClientDataErr::ChallengeKey))); 138 assert!(LimitedVerificationParser::<true>::parse(br#"{"type":"webauthn.create"challenge":"AAAAAAAAAAAAAAAAAAAAAA","origin":"https://example.com","crossorigin":false,"foo":true}"#.as_slice()).is_err_and(|e| matches!(e, CollectedClientDataErr::ChallengeKey))); 139 } 140 #[test] 141 fn c_data_challenge() { 142 assert!( 143 LimitedVerificationParser::<false>::get_sent_challenge([].as_slice()) 144 .is_err_and(|e| matches!(e, CollectedClientDataErr::Len)) 145 ); 146 assert!( 147 LimitedVerificationParser::<true>::get_sent_challenge([].as_slice()) 148 .is_err_and(|e| matches!(e, CollectedClientDataErr::Len)) 149 ); 150 assert!( 151 LimitedVerificationParser::<true>::get_sent_challenge( 152 b"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBB" 153 ) 154 .is_err_and(|e| matches!(e, CollectedClientDataErr::Challenge)) 155 ); 156 assert!( 157 LimitedVerificationParser::<false>::get_sent_challenge( 158 b"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBB" 159 ) 160 .is_err_and(|e| matches!(e, CollectedClientDataErr::Challenge)) 161 ); 162 assert!( 163 LimitedVerificationParser::<true>::get_sent_challenge( 164 b"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA".as_slice() 165 ) 166 .is_ok_and(|c| c.0 == 0) 167 ); 168 assert!( 169 LimitedVerificationParser::<false>::get_sent_challenge( 170 b"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA".as_slice() 171 ) 172 .is_ok_and(|c| c.0 == 0) 173 ); 174 }