bitwarden_core/client/
gov_mode.rs1use crate::client::internal::InternalClient;
2
3pub(crate) fn is_gov_mode(internal: &InternalClient) -> bool {
15 url::Url::parse(&internal.api_configurations.api_config.base_path)
16 .ok()
17 .and_then(|u| u.host_str().map(str::to_lowercase))
18 .map(|h| h == "bitwarden-gov.com" || h.ends_with(".bitwarden-gov.com"))
19 .unwrap_or(false)
20}
21
22#[cfg(test)]
23mod tests {
24 use crate::{Client, ClientSettings};
25
26 fn gov_mode_for(url: &str) -> bool {
27 Client::new(Some(ClientSettings {
28 api_url: url.into(),
29 ..Default::default()
30 }))
31 .gov_mode()
32 }
33
34 #[test]
35 fn true_for_canonical_gov_host() {
36 assert!(gov_mode_for("https://api.bitwarden-gov.com"));
37 }
38
39 #[test]
40 fn true_for_alternate_subdomain_on_gov_domain() {
41 assert!(gov_mode_for("https://vault.bitwarden-gov.com"));
42 }
43
44 #[test]
45 fn false_for_us_and_eu_hosts() {
46 assert!(!gov_mode_for("https://api.bitwarden.com"));
47 assert!(!gov_mode_for("https://api.bitwarden.eu"));
48 }
49
50 #[test]
51 fn false_for_self_hosted_with_bitwarden_in_name() {
52 assert!(!gov_mode_for("https://bitwarden.example.com/api"));
53 assert!(!gov_mode_for("https://my-bitwarden.eu/api"));
54 }
55
56 #[test]
57 fn false_for_spoofed_subdomain() {
58 assert!(!gov_mode_for("https://api.bitwarden-gov.com.evil.example/"));
59 assert!(!gov_mode_for("https://bitwarden-gov.com.evil.example/"));
60 }
61
62 #[test]
63 fn false_for_path_only_match() {
64 assert!(!gov_mode_for("https://example.com/bitwarden-gov.com/api"));
65 }
66
67 #[test]
68 fn case_insensitive() {
69 assert!(gov_mode_for("https://API.BITWARDEN-GOV.COM"));
70 }
71
72 #[test]
73 fn false_for_invalid_url() {
74 assert!(!gov_mode_for("not a url"));
75 assert!(!gov_mode_for(""));
76 }
77}