TLA Line data Source code
1 : //! Payload for ad hoc authentication method for clients that don't support SNI.
2 : //! See the `impl` for [`super::backend::BackendType<ClientCredentials>`].
3 : //! Read more: <https://github.com/neondatabase/cloud/issues/1620#issuecomment-1165332290>.
4 : //! UPDATE (Mon Aug 8 13:20:34 UTC 2022): the payload format has been simplified.
5 :
6 : use bstr::ByteSlice;
7 :
8 : pub struct PasswordHackPayload {
9 : pub endpoint: String,
10 : pub password: Vec<u8>,
11 : }
12 :
13 : impl PasswordHackPayload {
14 CBC 15 : pub fn parse(bytes: &[u8]) -> Option<Self> {
15 15 : // The format is `project=<utf-8>;<password-bytes>` or `project=<utf-8>$<password-bytes>`.
16 15 : let separators = [";", "$"];
17 31 : for sep in separators {
18 24 : if let Some((endpoint, password)) = bytes.split_once_str(sep) {
19 8 : let endpoint = endpoint.to_str().ok()?;
20 : return Some(Self {
21 8 : endpoint: parse_endpoint_param(endpoint)?.to_owned(),
22 8 : password: password.to_owned(),
23 : });
24 16 : }
25 : }
26 :
27 7 : None
28 15 : }
29 : }
30 :
31 133 : pub fn parse_endpoint_param(bytes: &str) -> Option<&str> {
32 133 : bytes
33 133 : .strip_prefix("project=")
34 133 : .or_else(|| bytes.strip_prefix("endpoint="))
35 133 : }
36 :
37 : #[cfg(test)]
38 : mod tests {
39 : use super::*;
40 :
41 1 : #[test]
42 1 : fn parse_endpoint_param_fn() {
43 1 : let input = "";
44 1 : assert!(parse_endpoint_param(input).is_none());
45 :
46 1 : let input = "project=";
47 1 : assert_eq!(parse_endpoint_param(input), Some(""));
48 :
49 1 : let input = "project=foobar";
50 1 : assert_eq!(parse_endpoint_param(input), Some("foobar"));
51 :
52 1 : let input = "endpoint=";
53 1 : assert_eq!(parse_endpoint_param(input), Some(""));
54 :
55 1 : let input = "endpoint=foobar";
56 1 : assert_eq!(parse_endpoint_param(input), Some("foobar"));
57 :
58 1 : let input = "other_option=foobar";
59 1 : assert!(parse_endpoint_param(input).is_none());
60 1 : }
61 :
62 1 : #[test]
63 1 : fn parse_password_hack_payload_project() {
64 1 : let bytes = b"";
65 1 : assert!(PasswordHackPayload::parse(bytes).is_none());
66 :
67 1 : let bytes = b"project=";
68 1 : assert!(PasswordHackPayload::parse(bytes).is_none());
69 :
70 1 : let bytes = b"project=;";
71 1 : let payload: PasswordHackPayload =
72 1 : PasswordHackPayload::parse(bytes).expect("parsing failed");
73 1 : assert_eq!(payload.endpoint, "");
74 1 : assert_eq!(payload.password, b"");
75 :
76 1 : let bytes = b"project=foobar;pass;word";
77 1 : let payload = PasswordHackPayload::parse(bytes).expect("parsing failed");
78 1 : assert_eq!(payload.endpoint, "foobar");
79 1 : assert_eq!(payload.password, b"pass;word");
80 1 : }
81 :
82 1 : #[test]
83 1 : fn parse_password_hack_payload_endpoint() {
84 1 : let bytes = b"";
85 1 : assert!(PasswordHackPayload::parse(bytes).is_none());
86 :
87 1 : let bytes = b"endpoint=";
88 1 : assert!(PasswordHackPayload::parse(bytes).is_none());
89 :
90 1 : let bytes = b"endpoint=;";
91 1 : let payload = PasswordHackPayload::parse(bytes).expect("parsing failed");
92 1 : assert_eq!(payload.endpoint, "");
93 1 : assert_eq!(payload.password, b"");
94 :
95 1 : let bytes = b"endpoint=foobar;pass;word";
96 1 : let payload = PasswordHackPayload::parse(bytes).expect("parsing failed");
97 1 : assert_eq!(payload.endpoint, "foobar");
98 1 : assert_eq!(payload.password, b"pass;word");
99 1 : }
100 :
101 1 : #[test]
102 1 : fn parse_password_hack_payload_dollar() {
103 1 : let bytes = b"";
104 1 : assert!(PasswordHackPayload::parse(bytes).is_none());
105 :
106 1 : let bytes = b"endpoint=";
107 1 : assert!(PasswordHackPayload::parse(bytes).is_none());
108 :
109 1 : let bytes = b"endpoint=$";
110 1 : let payload = PasswordHackPayload::parse(bytes).expect("parsing failed");
111 1 : assert_eq!(payload.endpoint, "");
112 1 : assert_eq!(payload.password, b"");
113 :
114 1 : let bytes = b"endpoint=foobar$pass$word";
115 1 : let payload = PasswordHackPayload::parse(bytes).expect("parsing failed");
116 1 : assert_eq!(payload.endpoint, "foobar");
117 1 : assert_eq!(payload.password, b"pass$word");
118 1 : }
119 : }
|