diff --git a/src/api/core/ciphers.rs b/src/api/core/ciphers.rs index 92499b9f..329a53f9 100644 --- a/src/api/core/ciphers.rs +++ b/src/api/core/ciphers.rs @@ -159,15 +159,20 @@ async fn sync(data: SyncData, headers: Headers, client_version: Option = Send::find_by_user(&headers.user.uuid, &conn).await.iter().map(Send::to_json).collect(); - let policies_json: Vec = + let mut policies_json: Vec = OrgPolicy::find_confirmed_by_user(&headers.user.uuid, &conn).await.iter().map(OrgPolicy::to_json).collect(); - let policies_new_json: Vec = OrgPolicy::find_accepted_and_confirmed_by_user(&headers.user.uuid, &conn) + let mut policies_new_json: Vec = OrgPolicy::find_accepted_and_confirmed_by_user(&headers.user.uuid, &conn) .await .iter() .map(OrgPolicy::to_json) .collect(); + if let Some(global_policy) = OrgPolicy::global_master_password_policy() { + policies_json.push(global_policy.clone()); + policies_new_json.push(global_policy); + } + let domains_json = if data.exclude_domains { Value::Null } else { diff --git a/src/db/models/org_policy.rs b/src/db/models/org_policy.rs index 554f51fc..25f57e15 100644 --- a/src/db/models/org_policy.rs +++ b/src/db/models/org_policy.rs @@ -29,6 +29,9 @@ pub struct OrgPolicy { pub revision_date: NaiveDateTime, } +// Fake organization id for the synthetic server-wide policy, analogous to FAKE_SSO_IDENTIFIER +pub static FAKE_GLOBAL_POLICY_ORG_ID: &str = "00000000-01DC-01DC-01DC-000000000001"; + // https://github.com/bitwarden/server/blob/9ebe16587175b1c0e9208f84397bb75d0d595510/src/Core/AdminConsole/Enums/PolicyType.cs #[derive(Copy, Clone, Eq, PartialEq, num_derive::FromPrimitive)] pub enum OrgPolicyType { @@ -120,6 +123,16 @@ impl OrgPolicy { policy } + + // Synthetic policy built from the MASTER_PASSWORD_POLICY setting. Serving it alongside the + // organization policies makes the clients enforce it on password changes as well, without + // requiring an organization. + pub fn global_master_password_policy() -> Option { + CONFIG.master_password_policy_value().map(|data| { + OrgPolicy::new(FAKE_GLOBAL_POLICY_ORG_ID.into(), OrgPolicyType::MasterPassword, true, data.to_string()) + .to_json() + }) + } } /// Database methods