1
0
Fork 0
mirror of https://github.com/dani-garcia/vaultwarden.git synced 2025-06-15 07:10:07 +00:00

More API Response fixes

- Some 2fa checks
- Some org checks
- Reconfigured the experimental flags and noted which are deprecated
  Also removed some hard-coded defaults.
- Updated crates

Signed-off-by: BlackDex <black.dex@gmail.com>
This commit is contained in:
BlackDex 2025-04-25 23:09:57 +02:00
parent bdb46fee2d
commit 42b5964790
No known key found for this signature in database
GPG key ID: 58C80A2AA6C765E1
9 changed files with 80 additions and 23 deletions

41
Cargo.lock generated
View file

@ -490,9 +490,9 @@ checksum = "ade8366b8bd5ba243f0a58f036cc0ca8a2f069cff1a2351ef1cac6b083e16fc0"
[[package]]
name = "cc"
version = "1.2.19"
version = "1.2.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e3a13707ac958681c13b39b458c073d0d9bc8a22cb1b2f4c8e55eb72c13f362"
checksum = "04da6a0d40b948dfc4fa8f5bbf402b0fc1a64a28dbf7d12ffd683550f2c1b63a"
dependencies = [
"shlex",
]
@ -1340,7 +1340,7 @@ dependencies = [
"futures-sink",
"futures-timer",
"futures-util",
"getrandom 0.3.3",
"getrandom 0.3.2",
"hashbrown 0.15.3",
"nonzero_ext",
"parking_lot",
@ -2699,7 +2699,7 @@ version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
dependencies = [
"zerocopy",
"zerocopy 0.8.25",
]
[[package]]
@ -3011,9 +3011,9 @@ dependencies = [
[[package]]
name = "resolv-conf"
version = "0.7.4"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95325155c684b1c89f7765e30bc1c42e4a6da51ca513615660cb8a62ef9a88e3"
checksum = "fc7c8f7f733062b66dc1c63f9db168ac0b97a9210e247fa90fdc9ad08f51b302"
[[package]]
name = "ring"
@ -3934,7 +3934,8 @@ dependencies = [
"serde",
"serde_spanned",
"toml_datetime",
"winnow 0.7.7",
"toml_write",
"winnow 0.7.8",
]
[[package]]
@ -4811,9 +4812,9 @@ dependencies = [
[[package]]
name = "winnow"
version = "0.7.7"
version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6cb8234a863ea0e8cd7284fcdd4f145233eb00fee02bbdd9861aec44e6477bc5"
checksum = "9e27d6ad3dac991091e4d35de9ba2d2d00647c5d0fc26c5496dee55984ae111b"
dependencies = [
"memchr",
]
@ -4904,7 +4905,27 @@ version = "0.8.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb"
dependencies = [
"zerocopy-derive",
"zerocopy-derive 0.7.35",
]
[[package]]
name = "zerocopy"
version = "0.8.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb"
dependencies = [
"zerocopy-derive 0.8.25",
]
[[package]]
name = "zerocopy-derive"
version = "0.8.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]

View file

@ -199,12 +199,14 @@ fn get_api_webauthn(_headers: Headers) -> Json<Value> {
#[get("/config")]
fn config() -> Json<Value> {
let domain = crate::CONFIG.domain();
// Official available feature flags can be found here:
// Server (v2025.4.2): https://github.com/bitwarden/server/blob/9ad96375153113abff36d28a3465f1c51ea604a0/src/Core/Constants.cs#L102
// Client (v2025.4.0): https://github.com/bitwarden/clients/blob/c86c73563140412ca8359cad0fedc6f74b29db84/libs/common/src/enums/feature-flag.enum.ts#L10
// Android (v2025.2.0): https://github.com/bitwarden/android/blob/8cd289cc89f729062f094d47b92c98b09c605e71/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/model/FlagKey.kt#L27
let mut feature_states =
parse_experimental_client_feature_flags(&crate::CONFIG.experimental_client_feature_flags());
// Force the new key rotation feature
feature_states.insert("key-rotation-improvements".to_string(), true);
feature_states.insert("duo-redirect".to_string(), true);
feature_states.insert("flexible-collections-v-1".to_string(), false);
feature_states.insert("email-verification".to_string(), true);
feature_states.insert("unauth-ui-refresh".to_string(), true);
@ -217,7 +219,6 @@ fn config() -> Json<Value> {
// - Individual cipher key encryption: 2024.2.0
"version": "2025.1.0",
"gitHash": option_env!("GIT_REV"),
"cloudRegion": null,
"server": {
"name": "Vaultwarden",
"url": "https://github.com/dani-garcia/vaultwarden"
@ -231,6 +232,7 @@ fn config() -> Json<Value> {
"identity": format!("{domain}/identity"),
"notifications": format!("{domain}/notifications"),
"sso": "",
"cloudRegion": null,
},
// Bitwarden uses this for the self-hosted servers to indicate the default push technology
"push": {

View file

@ -34,6 +34,10 @@ async fn generate_authenticator(data: Json<PasswordOrOtpData>, headers: Headers,
_ => (false, crypto::encode_random_bytes::<20>(BASE32)),
};
// Upstream seems to also return `userVerificationToken`, but doesn't seem to be used at all.
// It should help prevent TOTP disclosure if someone keeps there vault unlocked.
// Since it doesn't seem to be used, and also does not causes any issues, lets leave it out of the response.
// See: https://github.com/bitwarden/server/blob/b00f11fc43c0d5f20a8e224a8f9e3fc4dc23e60e/src/Api/Auth/Controllers/TwoFactorController.cs#L94
Ok(Json(json!({
"enabled": enabled,
"key": key,

View file

@ -118,6 +118,9 @@ async fn get_duo(data: Json<PasswordOrOtpData>, headers: Headers, mut conn: DbCo
} else {
json!({
"enabled": enabled,
"host": null,
"clientSecret": null,
"clientId": null,
"object": "twoFactorDuo"
})
};

View file

@ -579,7 +579,7 @@ make_config! {
authenticator_disable_time_drift: bool, true, def, false;
/// Customize the enabled feature flags on the clients |> This is a comma separated list of feature flags to enable.
experimental_client_feature_flags: String, false, def, "fido2-vault-credentials".to_string();
experimental_client_feature_flags: String, false, def, String::new();
/// Require new device emails |> When a user logs in an email is required to be sent.
/// If sending the email fails the login attempt will fail.
@ -834,20 +834,30 @@ fn validate_config(cfg: &ConfigItems) -> Result<(), Error> {
}
// TODO: deal with deprecated flags so they can be removed from this list, cf. #4263
// Server (v2025.4.2): https://github.com/bitwarden/server/blob/9ad96375153113abff36d28a3465f1c51ea604a0/src/Core/Constants.cs#L102
// Client (v2025.4.0): https://github.com/bitwarden/clients/blob/c86c73563140412ca8359cad0fedc6f74b29db84/libs/common/src/enums/feature-flag.enum.ts#L10
// Android (v2025.2.0): https://github.com/bitwarden/android/blob/8cd289cc89f729062f094d47b92c98b09c605e71/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/model/FlagKey.kt#L27
const KNOWN_FLAGS: &[&str] = &[
// Start Deprecated
"autofill-overlay",
"autofill-v2",
"browser-fileless-import",
"extension-refresh",
"fido2-vault-credentials",
// End Deprecated
// Autofill Team
"inline-menu-positioning-improvements",
"ssh-key-vault-item",
"inline-menu-totp",
"ssh-agent",
// Key Management Team
"ssh-key-vault-item",
// Tools
"export-attachments",
// Mobile Team
"anon-addy-self-host-alias",
"simple-login-self-host-alias",
"mutual-tls",
"export-attachments",
"inline-menu-totp",
];
let configured_flags = parse_experimental_client_feature_flags(&cfg.experimental_client_feature_flags);
let invalid_flags: Vec<_> = configured_flags.keys().filter(|flag| !KNOWN_FLAGS.contains(&flag.as_str())).collect();

View file

@ -167,6 +167,8 @@ impl DeviceWithAuthRequest {
"creationDate": format_date(&self.device.created_at),
"devicePendingAuthRequest": auth_request,
"isTrusted": false,
"encryptedPublicKey": null,
"encryptedUserKey": null,
"object": "device",
})
}

View file

@ -83,14 +83,24 @@ impl OrgPolicy {
pub fn to_json(&self) -> Value {
let data_json: Value = serde_json::from_str(&self.data).unwrap_or(Value::Null);
json!({
let mut policy = json!({
"id": self.uuid,
"organizationId": self.org_uuid,
"type": self.atype,
"data": data_json,
"enabled": self.enabled,
"object": "policy",
})
});
// Upstream adds this key/value
// Allow enabling Single Org policy when the organization has claimed domains.
// See: (https://github.com/bitwarden/server/pull/5565)
// We return the same to prevent possible issues
if self.atype == 8i32 {
policy["canToggleState"] = json!(true);
}
policy
}
}

View file

@ -203,7 +203,6 @@ impl Organization {
"useResetPassword": CONFIG.mail_enabled(),
"allowAdminAccessToAllCollectionItems": true,
"limitCollectionCreation": true,
"limitCollectionCreationDeletion": true,
"limitCollectionDeletion": true,
"businessName": self.name,
@ -468,7 +467,6 @@ impl Membership {
"familySponsorshipToDelete": null,
"accessSecretsManager": false,
"limitCollectionCreation": self.atype < MembershipType::Manager, // If less then a manager return true, to limit collection creations
"limitCollectionCreationDeletion": true,
"limitCollectionDeletion": true,
"limitItemDeletion": false,
"allowAdminAccessToAllCollectionItems": true,

View file

@ -752,9 +752,16 @@ pub fn convert_json_key_lcase_first(src_json: Value) -> Value {
/// Parses the experimental client feature flags string into a HashMap.
pub fn parse_experimental_client_feature_flags(experimental_client_feature_flags: &str) -> HashMap<String, bool> {
let feature_states = experimental_client_feature_flags.split(',').map(|f| (f.trim().to_owned(), true)).collect();
feature_states
experimental_client_feature_flags
.split(',')
.filter_map(|f| {
let flag = f.trim();
if !flag.is_empty() {
return Some((flag.to_owned(), true));
}
None
})
.collect()
}
/// TODO: This is extracted from IpAddr::is_global, which is unstable: