//! Payload for ad hoc authentication method for clients that don't support SNI. //! See the `impl` for [`super::backend::BackendType`]. //! Read more: . //! UPDATE (Mon Aug 8 13:20:34 UTC 2022): the payload format has been simplified. use bstr::ByteSlice; pub struct PasswordHackPayload { pub endpoint: String, pub password: Vec, } impl PasswordHackPayload { pub fn parse(bytes: &[u8]) -> Option { // The format is `project=;`. let mut iter = bytes.splitn_str(2, ";"); let endpoint = iter.next()?.to_str().ok()?; let endpoint = parse_endpoint_param(endpoint)?.to_owned(); let password = iter.next()?.to_owned(); Some(Self { endpoint, password }) } } pub fn parse_endpoint_param(bytes: &str) -> Option<&str> { bytes .strip_prefix("project=") .or_else(|| bytes.strip_prefix("endpoint=")) } #[cfg(test)] mod tests { use super::*; #[test] fn parse_endpoint_param_fn() { let input = ""; assert!(parse_endpoint_param(input).is_none()); let input = "project="; assert_eq!(parse_endpoint_param(input), Some("")); let input = "project=foobar"; assert_eq!(parse_endpoint_param(input), Some("foobar")); let input = "endpoint="; assert_eq!(parse_endpoint_param(input), Some("")); let input = "endpoint=foobar"; assert_eq!(parse_endpoint_param(input), Some("foobar")); let input = "other_option=foobar"; assert!(parse_endpoint_param(input).is_none()); } #[test] fn parse_password_hack_payload_project() { let bytes = b""; assert!(PasswordHackPayload::parse(bytes).is_none()); let bytes = b"project="; assert!(PasswordHackPayload::parse(bytes).is_none()); let bytes = b"project=;"; let payload: PasswordHackPayload = PasswordHackPayload::parse(bytes).expect("parsing failed"); assert_eq!(payload.endpoint, ""); assert_eq!(payload.password, b""); let bytes = b"project=foobar;pass;word"; let payload = PasswordHackPayload::parse(bytes).expect("parsing failed"); assert_eq!(payload.endpoint, "foobar"); assert_eq!(payload.password, b"pass;word"); } #[test] fn parse_password_hack_payload_endpoint() { let bytes = b""; assert!(PasswordHackPayload::parse(bytes).is_none()); let bytes = b"endpoint="; assert!(PasswordHackPayload::parse(bytes).is_none()); let bytes = b"endpoint=;"; let payload = PasswordHackPayload::parse(bytes).expect("parsing failed"); assert_eq!(payload.endpoint, ""); assert_eq!(payload.password, b""); let bytes = b"endpoint=foobar;pass;word"; let payload = PasswordHackPayload::parse(bytes).expect("parsing failed"); assert_eq!(payload.endpoint, "foobar"); assert_eq!(payload.password, b"pass;word"); } }