From ce8efcc48fa1a54129176904fb6911f17d675733 Mon Sep 17 00:00:00 2001 From: guangwu Date: Wed, 20 Mar 2024 02:47:14 +0800 Subject: [PATCH 01/14] fix: typos (#4440) Signed-off-by: guoguangwu --- src/api/push.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/api/push.rs b/src/api/push.rs index 79966c94..607fb7ea 100644 --- a/src/api/push.rs +++ b/src/api/push.rs @@ -114,11 +114,11 @@ pub async fn register_push_device(device: &mut Device, conn: &mut crate::db::DbC .await? .error_for_status() { - err!(format!("An error occured while proceeding registration of a device: {e}")); + err!(format!("An error occurred while proceeding registration of a device: {e}")); } if let Err(e) = device.save(conn).await { - err!(format!("An error occured while trying to save the (registered) device push uuid: {e}")); + err!(format!("An error occurred while trying to save the (registered) device push uuid: {e}")); } Ok(()) From 1e4275518757ce2f5945c0907be8be62ea9a09b0 Mon Sep 17 00:00:00 2001 From: Mathijs van Veluw Date: Tue, 19 Mar 2024 19:47:30 +0100 Subject: [PATCH 02/14] Update chrono and sqlite (#4436) - Updated sqlite crate - Updated chrono crate The latter needed a lot of changes done, mostly `Duration` to `TimeDelta`. And some changes on how to use Naive. --- Cargo.lock | 8 ++--- Cargo.toml | 4 +-- src/api/core/accounts.rs | 2 +- src/api/core/emergency_access.rs | 8 ++--- src/api/core/public.rs | 2 +- src/api/core/sends.rs | 6 ++-- src/api/core/two_factor/email.rs | 10 +++--- src/api/core/two_factor/mod.rs | 4 +-- src/api/core/two_factor/protected_actions.rs | 8 ++--- src/api/notifications.rs | 2 +- src/auth.rs | 38 ++++++++++---------- src/db/models/auth_request.rs | 2 +- src/db/models/cipher.rs | 4 +-- src/db/models/device.rs | 4 +-- src/db/models/event.rs | 4 +-- src/db/models/user.rs | 4 +-- src/util.rs | 2 +- 17 files changed, 56 insertions(+), 56 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b83eb071..bf8c7675 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -533,9 +533,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.34" +version = "0.4.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b" +checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a" dependencies = [ "android-tzdata", "iana-time-zone", @@ -1714,9 +1714,9 @@ dependencies = [ [[package]] name = "libsqlite3-sys" -version = "0.27.0" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4e226dcd58b4be396f7bd3c20da8fdee2911400705297ba7d2d7cc2c30f716" +checksum = "0c10584274047cb335c23d3e61bcef8e323adae7c5c8c760540f73610177fc3f" dependencies = [ "cc", "pkg-config", diff --git a/Cargo.toml b/Cargo.toml index 26916626..4fe555b6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -79,7 +79,7 @@ diesel_migrations = "2.1.0" diesel_logger = { version = "0.3.0", optional = true } # Bundled/Static SQLite -libsqlite3-sys = { version = "0.27.0", features = ["bundled"], optional = true } +libsqlite3-sys = { version = "0.28.0", features = ["bundled"], optional = true } # Crypto-related libraries rand = { version = "0.8.5", features = ["small_rng"] } @@ -89,7 +89,7 @@ ring = "0.17.8" uuid = { version = "1.7.0", features = ["v4"] } # Date and time libraries -chrono = { version = "0.4.34", features = ["clock", "serde"], default-features = false } +chrono = { version = "0.4.35", features = ["clock", "serde"], default-features = false } chrono-tz = "0.8.6" time = "0.3.34" diff --git a/src/api/core/accounts.rs b/src/api/core/accounts.rs index a97c4c31..da25d488 100644 --- a/src/api/core/accounts.rs +++ b/src/api/core/accounts.rs @@ -773,7 +773,7 @@ async fn delete_account(data: JsonUpcase, headers: Headers, m #[get("/accounts/revision-date")] fn revision_date(headers: Headers) -> JsonResult { - let revision_date = headers.user.updated_at.timestamp_millis(); + let revision_date = headers.user.updated_at.and_utc().timestamp_millis(); Ok(Json(json!(revision_date))) } diff --git a/src/api/core/emergency_access.rs b/src/api/core/emergency_access.rs index fb163849..5f64cde0 100644 --- a/src/api/core/emergency_access.rs +++ b/src/api/core/emergency_access.rs @@ -1,4 +1,4 @@ -use chrono::{Duration, Utc}; +use chrono::{TimeDelta, Utc}; use rocket::{serde::json::Json, Route}; use serde_json::Value; @@ -766,7 +766,7 @@ pub async fn emergency_request_timeout_job(pool: DbPool) { for mut emer in emergency_access_list { // The find_all_recoveries_initiated already checks if the recovery_initiated_at is not null (None) let recovery_allowed_at = - emer.recovery_initiated_at.unwrap() + Duration::days(i64::from(emer.wait_time_days)); + emer.recovery_initiated_at.unwrap() + TimeDelta::try_days(i64::from(emer.wait_time_days)).unwrap(); if recovery_allowed_at.le(&now) { // Only update the access status // Updating the whole record could cause issues when the emergency_notification_reminder_job is also active @@ -822,10 +822,10 @@ pub async fn emergency_notification_reminder_job(pool: DbPool) { // The find_all_recoveries_initiated already checks if the recovery_initiated_at is not null (None) // Calculate the day before the recovery will become active let final_recovery_reminder_at = - emer.recovery_initiated_at.unwrap() + Duration::days(i64::from(emer.wait_time_days - 1)); + emer.recovery_initiated_at.unwrap() + TimeDelta::try_days(i64::from(emer.wait_time_days - 1)).unwrap(); // Calculate if a day has passed since the previous notification, else no notification has been sent before let next_recovery_reminder_at = if let Some(last_notification_at) = emer.last_notification_at { - last_notification_at + Duration::days(1) + last_notification_at + TimeDelta::try_days(1).unwrap() } else { now }; diff --git a/src/api/core/public.rs b/src/api/core/public.rs index 74f79a3e..085ac552 100644 --- a/src/api/core/public.rs +++ b/src/api/core/public.rs @@ -209,7 +209,7 @@ impl<'r> FromRequest<'r> for PublicToken { Err(_) => err_handler!("Invalid claim"), }; // Check if time is between claims.nbf and claims.exp - let time_now = Utc::now().naive_utc().timestamp(); + let time_now = Utc::now().timestamp(); if time_now < claims.nbf { err_handler!("Token issued in the future"); } diff --git a/src/api/core/sends.rs b/src/api/core/sends.rs index 1bc6d00f..6842d398 100644 --- a/src/api/core/sends.rs +++ b/src/api/core/sends.rs @@ -1,6 +1,6 @@ use std::path::Path; -use chrono::{DateTime, Duration, Utc}; +use chrono::{DateTime, TimeDelta, Utc}; use num_traits::ToPrimitive; use rocket::form::Form; use rocket::fs::NamedFile; @@ -119,7 +119,7 @@ fn create_send(data: SendData, user_uuid: String) -> ApiResult { err!("Send data not provided"); }; - if data.DeletionDate > Utc::now() + Duration::days(31) { + if data.DeletionDate > Utc::now() + TimeDelta::try_days(31).unwrap() { err!( "You cannot have a Send with a deletion date that far into the future. Adjust the Deletion Date to a value less than 31 days from now and try again." ); @@ -569,7 +569,7 @@ async fn put_send( send.data = data_str; } - if data.DeletionDate > Utc::now() + Duration::days(31) { + if data.DeletionDate > Utc::now() + TimeDelta::try_days(31).unwrap() { err!( "You cannot have a Send with a deletion date that far into the future. Adjust the Deletion Date to a value less than 31 days from now and try again." ); diff --git a/src/api/core/two_factor/email.rs b/src/api/core/two_factor/email.rs index 582265b1..62344cf8 100644 --- a/src/api/core/two_factor/email.rs +++ b/src/api/core/two_factor/email.rs @@ -1,4 +1,4 @@ -use chrono::{Duration, NaiveDateTime, Utc}; +use chrono::{DateTime, TimeDelta, Utc}; use rocket::serde::json::Json; use rocket::Route; @@ -232,9 +232,9 @@ pub async fn validate_email_code_str(user_uuid: &str, token: &str, data: &str, c twofactor.data = email_data.to_json(); twofactor.save(conn).await?; - let date = NaiveDateTime::from_timestamp_opt(email_data.token_sent, 0).expect("Email token timestamp invalid."); + let date = DateTime::from_timestamp(email_data.token_sent, 0).expect("Email token timestamp invalid.").naive_utc(); let max_time = CONFIG.email_expiration_time() as i64; - if date + Duration::seconds(max_time) < Utc::now().naive_utc() { + if date + TimeDelta::try_seconds(max_time).unwrap() < Utc::now().naive_utc() { err!( "Token has expired", ErrorEvent { @@ -265,14 +265,14 @@ impl EmailTokenData { EmailTokenData { email, last_token: Some(token), - token_sent: Utc::now().naive_utc().timestamp(), + token_sent: Utc::now().timestamp(), attempts: 0, } } pub fn set_token(&mut self, token: String) { self.last_token = Some(token); - self.token_sent = Utc::now().naive_utc().timestamp(); + self.token_sent = Utc::now().timestamp(); } pub fn reset_token(&mut self) { diff --git a/src/api/core/two_factor/mod.rs b/src/api/core/two_factor/mod.rs index a40c23e6..8c0d6764 100644 --- a/src/api/core/two_factor/mod.rs +++ b/src/api/core/two_factor/mod.rs @@ -1,4 +1,4 @@ -use chrono::{Duration, Utc}; +use chrono::{TimeDelta, Utc}; use data_encoding::BASE32; use rocket::serde::json::Json; use rocket::Route; @@ -259,7 +259,7 @@ pub async fn send_incomplete_2fa_notifications(pool: DbPool) { }; let now = Utc::now().naive_utc(); - let time_limit = Duration::minutes(CONFIG.incomplete_2fa_time_limit()); + let time_limit = TimeDelta::try_minutes(CONFIG.incomplete_2fa_time_limit()).unwrap(); let time_before = now - time_limit; let incomplete_logins = TwoFactorIncomplete::find_logins_before(&time_before, &mut conn).await; for login in incomplete_logins { diff --git a/src/api/core/two_factor/protected_actions.rs b/src/api/core/two_factor/protected_actions.rs index 09c7ede0..537ed0c6 100644 --- a/src/api/core/two_factor/protected_actions.rs +++ b/src/api/core/two_factor/protected_actions.rs @@ -1,4 +1,4 @@ -use chrono::{Duration, NaiveDateTime, Utc}; +use chrono::{DateTime, TimeDelta, Utc}; use rocket::Route; use crate::{ @@ -32,7 +32,7 @@ impl ProtectedActionData { pub fn new(token: String) -> Self { Self { token, - token_sent: Utc::now().naive_utc().timestamp(), + token_sent: Utc::now().timestamp(), attempts: 0, } } @@ -122,9 +122,9 @@ pub async fn validate_protected_action_otp( // Check if the token has expired (Using the email 2fa expiration time) let date = - NaiveDateTime::from_timestamp_opt(pa_data.token_sent, 0).expect("Protected Action token timestamp invalid."); + DateTime::from_timestamp(pa_data.token_sent, 0).expect("Protected Action token timestamp invalid.").naive_utc(); let max_time = CONFIG.email_expiration_time() as i64; - if date + Duration::seconds(max_time) < Utc::now().naive_utc() { + if date + TimeDelta::try_seconds(max_time).unwrap() < Utc::now().naive_utc() { pa.delete(conn).await?; err!("Token has expired") } diff --git a/src/api/notifications.rs b/src/api/notifications.rs index 1f64b86e..7a1aa2ac 100644 --- a/src/api/notifications.rs +++ b/src/api/notifications.rs @@ -288,7 +288,7 @@ fn serialize(val: Value) -> Vec { } fn serialize_date(date: NaiveDateTime) -> Value { - let seconds: i64 = date.timestamp(); + let seconds: i64 = date.and_utc().timestamp(); let nanos: i64 = date.timestamp_subsec_nanos().into(); let timestamp = nanos << 34 | seconds; diff --git a/src/auth.rs b/src/auth.rs index 7eabbc1e..36e84613 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -1,6 +1,6 @@ // JWT Handling // -use chrono::{Duration, Utc}; +use chrono::{TimeDelta, Utc}; use num_traits::FromPrimitive; use once_cell::sync::{Lazy, OnceCell}; @@ -13,7 +13,7 @@ use crate::{error::Error, CONFIG}; const JWT_ALGORITHM: Algorithm = Algorithm::RS256; -pub static DEFAULT_VALIDITY: Lazy = Lazy::new(|| Duration::hours(2)); +pub static DEFAULT_VALIDITY: Lazy = Lazy::new(|| TimeDelta::try_hours(2).unwrap()); static JWT_HEADER: Lazy
= Lazy::new(|| Header::new(JWT_ALGORITHM)); pub static JWT_LOGIN_ISSUER: Lazy = Lazy::new(|| format!("{}|login", CONFIG.domain_origin())); @@ -187,11 +187,11 @@ pub fn generate_invite_claims( user_org_id: Option, invited_by_email: Option, ) -> InviteJwtClaims { - let time_now = Utc::now().naive_utc(); + let time_now = Utc::now(); let expire_hours = i64::from(CONFIG.invitation_expiration_hours()); InviteJwtClaims { nbf: time_now.timestamp(), - exp: (time_now + Duration::hours(expire_hours)).timestamp(), + exp: (time_now + TimeDelta::try_hours(expire_hours).unwrap()).timestamp(), iss: JWT_INVITE_ISSUER.to_string(), sub: uuid, email, @@ -225,11 +225,11 @@ pub fn generate_emergency_access_invite_claims( grantor_name: String, grantor_email: String, ) -> EmergencyAccessInviteJwtClaims { - let time_now = Utc::now().naive_utc(); + let time_now = Utc::now(); let expire_hours = i64::from(CONFIG.invitation_expiration_hours()); EmergencyAccessInviteJwtClaims { nbf: time_now.timestamp(), - exp: (time_now + Duration::hours(expire_hours)).timestamp(), + exp: (time_now + TimeDelta::try_hours(expire_hours).unwrap()).timestamp(), iss: JWT_EMERGENCY_ACCESS_INVITE_ISSUER.to_string(), sub: uuid, email, @@ -256,10 +256,10 @@ pub struct OrgApiKeyLoginJwtClaims { } pub fn generate_organization_api_key_login_claims(uuid: String, org_id: String) -> OrgApiKeyLoginJwtClaims { - let time_now = Utc::now().naive_utc(); + let time_now = Utc::now(); OrgApiKeyLoginJwtClaims { nbf: time_now.timestamp(), - exp: (time_now + Duration::hours(1)).timestamp(), + exp: (time_now + TimeDelta::try_hours(1).unwrap()).timestamp(), iss: JWT_ORG_API_KEY_ISSUER.to_string(), sub: uuid, client_id: format!("organization.{org_id}"), @@ -283,10 +283,10 @@ pub struct FileDownloadClaims { } pub fn generate_file_download_claims(uuid: String, file_id: String) -> FileDownloadClaims { - let time_now = Utc::now().naive_utc(); + let time_now = Utc::now(); FileDownloadClaims { nbf: time_now.timestamp(), - exp: (time_now + Duration::minutes(5)).timestamp(), + exp: (time_now + TimeDelta::try_minutes(5).unwrap()).timestamp(), iss: JWT_FILE_DOWNLOAD_ISSUER.to_string(), sub: uuid, file_id, @@ -306,42 +306,42 @@ pub struct BasicJwtClaims { } pub fn generate_delete_claims(uuid: String) -> BasicJwtClaims { - let time_now = Utc::now().naive_utc(); + let time_now = Utc::now(); let expire_hours = i64::from(CONFIG.invitation_expiration_hours()); BasicJwtClaims { nbf: time_now.timestamp(), - exp: (time_now + Duration::hours(expire_hours)).timestamp(), + exp: (time_now + TimeDelta::try_hours(expire_hours).unwrap()).timestamp(), iss: JWT_DELETE_ISSUER.to_string(), sub: uuid, } } pub fn generate_verify_email_claims(uuid: String) -> BasicJwtClaims { - let time_now = Utc::now().naive_utc(); + let time_now = Utc::now(); let expire_hours = i64::from(CONFIG.invitation_expiration_hours()); BasicJwtClaims { nbf: time_now.timestamp(), - exp: (time_now + Duration::hours(expire_hours)).timestamp(), + exp: (time_now + TimeDelta::try_hours(expire_hours).unwrap()).timestamp(), iss: JWT_VERIFYEMAIL_ISSUER.to_string(), sub: uuid, } } pub fn generate_admin_claims() -> BasicJwtClaims { - let time_now = Utc::now().naive_utc(); + let time_now = Utc::now(); BasicJwtClaims { nbf: time_now.timestamp(), - exp: (time_now + Duration::minutes(CONFIG.admin_session_lifetime())).timestamp(), + exp: (time_now + TimeDelta::try_minutes(CONFIG.admin_session_lifetime()).unwrap()).timestamp(), iss: JWT_ADMIN_ISSUER.to_string(), sub: "admin_panel".to_string(), } } pub fn generate_send_claims(send_id: &str, file_id: &str) -> BasicJwtClaims { - let time_now = Utc::now().naive_utc(); + let time_now = Utc::now(); BasicJwtClaims { nbf: time_now.timestamp(), - exp: (time_now + Duration::minutes(2)).timestamp(), + exp: (time_now + TimeDelta::try_minutes(2).unwrap()).timestamp(), iss: JWT_SEND_ISSUER.to_string(), sub: format!("{send_id}/{file_id}"), } @@ -498,7 +498,7 @@ impl<'r> FromRequest<'r> for Headers { // Check if the stamp exception has expired first. // Then, check if the current route matches any of the allowed routes. // After that check the stamp in exception matches the one in the claims. - if Utc::now().naive_utc().timestamp() > stamp_exception.expire { + if Utc::now().timestamp() > stamp_exception.expire { // If the stamp exception has been expired remove it from the database. // This prevents checking this stamp exception for new requests. let mut user = user; diff --git a/src/db/models/auth_request.rs b/src/db/models/auth_request.rs index 2a004fb1..9388c71a 100644 --- a/src/db/models/auth_request.rs +++ b/src/db/models/auth_request.rs @@ -140,7 +140,7 @@ impl AuthRequest { } pub async fn purge_expired_auth_requests(conn: &mut DbConn) { - let expiry_time = Utc::now().naive_utc() - chrono::Duration::minutes(5); //after 5 minutes, clients reject the request + let expiry_time = Utc::now().naive_utc() - chrono::TimeDelta::try_minutes(5).unwrap(); //after 5 minutes, clients reject the request for auth_request in Self::find_created_before(&expiry_time, conn).await { auth_request.delete(conn).await.ok(); } diff --git a/src/db/models/cipher.rs b/src/db/models/cipher.rs index 61683d85..0574a833 100644 --- a/src/db/models/cipher.rs +++ b/src/db/models/cipher.rs @@ -1,5 +1,5 @@ use crate::CONFIG; -use chrono::{Duration, NaiveDateTime, Utc}; +use chrono::{NaiveDateTime, TimeDelta, Utc}; use serde_json::Value; use super::{ @@ -361,7 +361,7 @@ impl Cipher { pub async fn purge_trash(conn: &mut DbConn) { if let Some(auto_delete_days) = CONFIG.trash_auto_delete_days() { let now = Utc::now().naive_utc(); - let dt = now - Duration::days(auto_delete_days); + let dt = now - TimeDelta::try_days(auto_delete_days).unwrap(); for cipher in Self::find_deleted_before(&dt, conn).await { cipher.delete(conn).await.ok(); } diff --git a/src/db/models/device.rs b/src/db/models/device.rs index de612e69..60c63589 100644 --- a/src/db/models/device.rs +++ b/src/db/models/device.rs @@ -67,8 +67,8 @@ impl Device { } // Update the expiration of the device and the last update date - let time_now = Utc::now().naive_utc(); - self.updated_at = time_now; + let time_now = Utc::now(); + self.updated_at = time_now.naive_utc(); // --- // Disabled these keys to be added to the JWT since they could cause the JWT to get too large diff --git a/src/db/models/event.rs b/src/db/models/event.rs index af2f6c66..22d8fb00 100644 --- a/src/db/models/event.rs +++ b/src/db/models/event.rs @@ -3,7 +3,7 @@ use serde_json::Value; use crate::{api::EmptyResult, error::MapResult, CONFIG}; -use chrono::{Duration, NaiveDateTime, Utc}; +use chrono::{NaiveDateTime, TimeDelta, Utc}; // https://bitwarden.com/help/event-logs/ @@ -316,7 +316,7 @@ impl Event { pub async fn clean_events(conn: &mut DbConn) -> EmptyResult { if let Some(days_to_retain) = CONFIG.events_days_retain() { - let dt = Utc::now().naive_utc() - Duration::days(days_to_retain); + let dt = Utc::now().naive_utc() - TimeDelta::try_days(days_to_retain).unwrap(); db_run! { conn: { diesel::delete(event::table.filter(event::event_date.lt(dt))) .execute(conn) diff --git a/src/db/models/user.rs b/src/db/models/user.rs index 1475d637..feb09438 100644 --- a/src/db/models/user.rs +++ b/src/db/models/user.rs @@ -1,4 +1,4 @@ -use chrono::{Duration, NaiveDateTime, Utc}; +use chrono::{NaiveDateTime, TimeDelta, Utc}; use serde_json::Value; use crate::crypto; @@ -202,7 +202,7 @@ impl User { let stamp_exception = UserStampException { routes: route_exception, security_stamp: self.security_stamp.clone(), - expire: (Utc::now().naive_utc() + Duration::minutes(2)).timestamp(), + expire: (Utc::now() + TimeDelta::try_minutes(2).unwrap()).timestamp(), }; self.stamp_exception = Some(serde_json::to_string(&stamp_exception).unwrap_or_default()); } diff --git a/src/util.rs b/src/util.rs index 2f04fe34..ed730cb7 100644 --- a/src/util.rs +++ b/src/util.rs @@ -214,7 +214,7 @@ impl<'r, R: 'r + Responder<'r, 'static> + Send> Responder<'r, 'static> for Cache res.set_raw_header("Cache-Control", cache_control_header); let time_now = chrono::Local::now(); - let expiry_time = time_now + chrono::Duration::seconds(self.ttl.try_into().unwrap()); + let expiry_time = time_now + chrono::TimeDelta::try_seconds(self.ttl.try_into().unwrap()).unwrap(); res.set_raw_header("Expires", format_datetime_http(&expiry_time)); Ok(res) } From 93636eb3c3f3dda6211c2c47261218fcfe14cdaf Mon Sep 17 00:00:00 2001 From: Mathijs van Veluw Date: Sat, 23 Mar 2024 15:40:34 +0100 Subject: [PATCH 03/14] Update Rust and crates (#4445) - Updated Rust to v1.77.0 - Updated several crates The `reqwest` update included `trust-dns` > `hickory-dns` changes. Also, `reqwest` v0.12 is not working correctly for us, that is something to investigate. - Fixed a new clippy warning --- Cargo.lock | 183 ++++++++++++++++++------------------- Cargo.toml | 8 +- docker/DockerSettings.yaml | 2 +- docker/Dockerfile.alpine | 8 +- docker/Dockerfile.debian | 2 +- rust-toolchain.toml | 2 +- src/api/icons.rs | 4 +- src/auth.rs | 3 +- src/main.rs | 8 +- src/util.rs | 2 +- 10 files changed, 111 insertions(+), 111 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bf8c7675..ec358d68 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -31,9 +31,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] @@ -134,7 +134,7 @@ dependencies = [ "async-task", "concurrent-queue", "fastrand 2.0.1", - "futures-lite 2.2.0", + "futures-lite 2.3.0", "slab", ] @@ -149,7 +149,7 @@ dependencies = [ "async-io 2.3.2", "async-lock 3.3.0", "blocking", - "futures-lite 2.2.0", + "futures-lite 2.3.0", "once_cell", ] @@ -183,10 +183,10 @@ dependencies = [ "cfg-if", "concurrent-queue", "futures-io", - "futures-lite 2.2.0", + "futures-lite 2.3.0", "parking", "polling 3.5.0", - "rustix 0.38.31", + "rustix 0.38.32", "slab", "tracing", "windows-sys 0.52.0", @@ -225,7 +225,7 @@ dependencies = [ "cfg-if", "event-listener 3.1.0", "futures-lite 1.13.0", - "rustix 0.38.31", + "rustix 0.38.32", "windows-sys 0.48.0", ] @@ -241,7 +241,7 @@ dependencies = [ "cfg-if", "futures-core", "futures-io", - "rustix 0.38.31", + "rustix 0.38.32", "signal-hook-registry", "slab", "windows-sys 0.48.0", @@ -342,9 +342,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "95d8e92cac0961e91dbd517496b00f7e9b92363dbe6d42c3198268323798860c" dependencies = [ "addr2line", "cc", @@ -400,9 +400,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.2" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] name = "blake2" @@ -433,7 +433,7 @@ dependencies = [ "async-task", "fastrand 2.0.1", "futures-io", - "futures-lite 2.2.0", + "futures-lite 2.3.0", "piper", "tracing", ] @@ -797,7 +797,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35b50dba0afdca80b187392b24f2499a88c336d5a8493e4b4ccfb608708be56a" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "proc-macro2", "proc-macro2-diagnostics", "quote", @@ -811,7 +811,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03fc05c17098f21b89bc7d98fe1dd3cce2c11c2ad8e145f2a44fe08ed28eb559" dependencies = [ "bigdecimal", - "bitflags 2.4.2", + "bitflags 2.5.0", "byteorder", "chrono", "diesel_derives", @@ -1053,7 +1053,7 @@ dependencies = [ "atomic 0.6.0", "pear", "serde", - "toml 0.8.11", + "toml 0.8.12", "uncased", "version_check", ] @@ -1163,9 +1163,9 @@ dependencies = [ [[package]] name = "futures-lite" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445ba825b27408685aaecefd65178908c36c6e96aaf6d8599419d46e624192ba" +checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" dependencies = [ "fastrand 2.0.1", "futures-core", @@ -1363,6 +1363,51 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +[[package]] +name = "hickory-proto" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "091a6fbccf4860009355e3efc52ff4acf37a63489aad7435372d44ceeb6fbbcf" +dependencies = [ + "async-trait", + "cfg-if", + "data-encoding", + "enum-as-inner", + "futures-channel", + "futures-io", + "futures-util", + "idna 0.4.0", + "ipnet", + "once_cell", + "rand", + "thiserror", + "tinyvec", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "hickory-resolver" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35b8f021164e6a984c9030023544c57789c51760065cd510572fedcfb04164e8" +dependencies = [ + "cfg-if", + "futures-util", + "hickory-proto", + "ipconfig", + "lru-cache", + "once_cell", + "parking_lot", + "rand", + "resolv-conf", + "smallvec", + "thiserror", + "tokio", + "tracing", +] + [[package]] name = "hmac" version = "0.12.1" @@ -1631,9 +1676,9 @@ dependencies = [ [[package]] name = "jsonwebtoken" -version = "9.2.0" +version = "9.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7ea04a7c5c055c175f189b6dc6ba036fd62306b58c66c9f6389036c503a3f4" +checksum = "b9ae10193d25051e74945f1ea2d0b42e03cc3b890f7e4cc5faa44997d808193f" dependencies = [ "base64 0.21.7", "js-sys", @@ -2033,7 +2078,7 @@ version = "0.10.64" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "cfg-if", "foreign-types", "libc", @@ -2144,9 +2189,9 @@ checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" [[package]] name = "pear" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ccca0f6c17acc81df8e242ed473ec144cbf5c98037e69aa6d144780aad103c8" +checksum = "bdeeaa00ce488657faba8ebf44ab9361f9365a97bd39ffb8a60663f57ff4b467" dependencies = [ "inlinable_string", "pear_codegen", @@ -2155,9 +2200,9 @@ dependencies = [ [[package]] name = "pear_codegen" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e22670e8eb757cff11d6c199ca7b987f352f0346e0be4dd23869ec72cb53c77" +checksum = "4bab5b985dc082b345f812b7df84e1bef27e7207b39e448439ba8bd69c93f147" dependencies = [ "proc-macro2", "proc-macro2-diagnostics", @@ -2324,7 +2369,7 @@ dependencies = [ "cfg-if", "concurrent-queue", "pin-project-lite", - "rustix 0.38.31", + "rustix 0.38.32", "tracing", "windows-sys 0.52.0", ] @@ -2486,7 +2531,7 @@ version = "11.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d86a7c4638d42c44551f4791a20e687dbb4c3de1f33c43dd71e355cd429def1" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", ] [[package]] @@ -2575,9 +2620,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.26" +version = "0.11.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bf93c4af7a8bb7d879d51cebe797356ff10ae8516ace542b5182d9dcac10b2" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ "async-compression", "base64 0.21.7", @@ -2588,6 +2633,7 @@ dependencies = [ "futures-core", "futures-util", "h2", + "hickory-resolver", "http", "http-body", "hyper", @@ -2611,7 +2657,6 @@ dependencies = [ "tokio-socks", "tokio-util", "tower-service", - "trust-dns-resolver", "url", "wasm-bindgen", "wasm-bindgen-futures", @@ -2804,11 +2849,11 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.31" +version = "0.38.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" +checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "errno", "libc", "linux-raw-sys 0.4.13", @@ -3077,9 +3122,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" @@ -3229,7 +3274,7 @@ checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", "fastrand 2.0.1", - "rustix 0.38.31", + "rustix 0.38.32", "windows-sys 0.52.0", ] @@ -3433,14 +3478,14 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af06656561d28735e9c1cd63dfd57132c8155426aa6af24f36a00a351f88c48e" +checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.7", + "toml_edit 0.22.9", ] [[package]] @@ -3467,9 +3512,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.7" +version = "0.22.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18769cd1cec395d70860ceb4d932812a0b4d06b1a4bb336745a4d21b9496e992" +checksum = "8e40bb779c5187258fd7aad0eb68cb8706a0a81fa712fbea808ab43c4b8374c4" dependencies = [ "indexmap", "serde", @@ -3558,52 +3603,6 @@ dependencies = [ "tracing-log", ] -[[package]] -name = "trust-dns-proto" -version = "0.23.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3119112651c157f4488931a01e586aa459736e9d6046d3bd9105ffb69352d374" -dependencies = [ - "async-trait", - "cfg-if", - "data-encoding", - "enum-as-inner", - "futures-channel", - "futures-io", - "futures-util", - "idna 0.4.0", - "ipnet", - "once_cell", - "rand", - "smallvec", - "thiserror", - "tinyvec", - "tokio", - "tracing", - "url", -] - -[[package]] -name = "trust-dns-resolver" -version = "0.23.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a3e6c3aff1718b3c73e395d1f35202ba2ffa847c6a62eea0db8fb4cfe30be6" -dependencies = [ - "cfg-if", - "futures-util", - "ipconfig", - "lru-cache", - "once_cell", - "parking_lot", - "rand", - "resolv-conf", - "smallvec", - "thiserror", - "tokio", - "tracing", - "trust-dns-proto", -] - [[package]] name = "try-lock" version = "0.2.5" @@ -3713,9 +3712,9 @@ checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" [[package]] name = "uuid" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" +checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" dependencies = [ "getrandom", ] @@ -3728,9 +3727,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "value-bag" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fec26a25bd6fca441cdd0f769fd7f891bae119f996de31f86a5eddccef54c1d" +checksum = "74797339c3b98616c009c7c3eb53a0ce41e85c8ec66bd3db96ed132d20cfdee8" [[package]] name = "vaultwarden" @@ -3953,7 +3952,7 @@ dependencies = [ "either", "home", "once_cell", - "rustix 0.38.31", + "rustix 0.38.32", "windows-sys 0.52.0", ] diff --git a/Cargo.toml b/Cargo.toml index 4fe555b6..22008c9f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ name = "vaultwarden" version = "1.0.0" authors = ["Daniel GarcĂ­a "] edition = "2021" -rust-version = "1.74.0" +rust-version = "1.75.0" resolver = "2" repository = "https://github.com/dani-garcia/vaultwarden" @@ -86,7 +86,7 @@ rand = { version = "0.8.5", features = ["small_rng"] } ring = "0.17.8" # UUID generation -uuid = { version = "1.7.0", features = ["v4"] } +uuid = { version = "1.8.0", features = ["v4"] } # Date and time libraries chrono = { version = "0.4.35", features = ["clock", "serde"], default-features = false } @@ -100,7 +100,7 @@ job_scheduler_ng = "2.0.4" data-encoding = "2.5.0" # JWT library -jsonwebtoken = "9.2.0" +jsonwebtoken = "9.3.0" # TOTP library totp-lite = "2.0.1" @@ -123,7 +123,7 @@ email_address = "0.2.4" handlebars = { version = "5.1.0", features = ["dir_source"] } # HTTP client (Used for favicons, version check, DUO and HIBP API) -reqwest = { version = "0.11.26", features = ["stream", "json", "gzip", "brotli", "socks", "cookies", "trust-dns", "native-tls-alpn"] } +reqwest = { version = "0.11.27", features = ["default-tls", "native-tls-alpn", "stream", "json", "gzip", "brotli", "socks", "cookies", "hickory-dns"], default-features = false} # Favicon extraction libraries html5gum = "0.5.7" diff --git a/docker/DockerSettings.yaml b/docker/DockerSettings.yaml index 9ea779b7..9c4612ab 100644 --- a/docker/DockerSettings.yaml +++ b/docker/DockerSettings.yaml @@ -4,7 +4,7 @@ vault_image_digest: "sha256:798c0c893b6d16728878ff280b49da08863334d1f8dd88895580 # Cross Compile Docker Helper Scripts v1.3.0 # We use the linux/amd64 platform shell scripts since there is no difference between the different platform scripts xx_image_digest: "sha256:c9609ace652bbe51dd4ce90e0af9d48a4590f1214246da5bc70e46f6dd586edc" -rust_version: 1.76.0 # Rust version to be used +rust_version: 1.77.0 # Rust version to be used debian_version: bookworm # Debian release name to be used alpine_version: 3.19 # Alpine version to be used # For which platforms/architectures will we try to build images diff --git a/docker/Dockerfile.alpine b/docker/Dockerfile.alpine index 427f5153..56f2a6e7 100644 --- a/docker/Dockerfile.alpine +++ b/docker/Dockerfile.alpine @@ -31,10 +31,10 @@ FROM --platform=linux/amd64 docker.io/vaultwarden/web-vault@sha256:798c0c893b6d1 ########################## ALPINE BUILD IMAGES ########################## ## NOTE: The Alpine Base Images do not support other platforms then linux/amd64 ## And for Alpine we define all build images here, they will only be loaded when actually used -FROM --platform=linux/amd64 ghcr.io/blackdex/rust-musl:x86_64-musl-stable-1.76.0 as build_amd64 -FROM --platform=linux/amd64 ghcr.io/blackdex/rust-musl:aarch64-musl-stable-1.76.0 as build_arm64 -FROM --platform=linux/amd64 ghcr.io/blackdex/rust-musl:armv7-musleabihf-stable-1.76.0 as build_armv7 -FROM --platform=linux/amd64 ghcr.io/blackdex/rust-musl:arm-musleabi-stable-1.76.0 as build_armv6 +FROM --platform=linux/amd64 ghcr.io/blackdex/rust-musl:x86_64-musl-stable-1.77.0 as build_amd64 +FROM --platform=linux/amd64 ghcr.io/blackdex/rust-musl:aarch64-musl-stable-1.77.0 as build_arm64 +FROM --platform=linux/amd64 ghcr.io/blackdex/rust-musl:armv7-musleabihf-stable-1.77.0 as build_armv7 +FROM --platform=linux/amd64 ghcr.io/blackdex/rust-musl:arm-musleabi-stable-1.77.0 as build_armv6 ########################## BUILD IMAGE ########################## # hadolint ignore=DL3006 diff --git a/docker/Dockerfile.debian b/docker/Dockerfile.debian index c2d9eee8..51e38b89 100644 --- a/docker/Dockerfile.debian +++ b/docker/Dockerfile.debian @@ -35,7 +35,7 @@ FROM --platform=linux/amd64 docker.io/tonistiigi/xx@sha256:c9609ace652bbe51dd4ce ########################## BUILD IMAGE ########################## # hadolint ignore=DL3006 -FROM --platform=$BUILDPLATFORM docker.io/library/rust:1.76.0-slim-bookworm as build +FROM --platform=$BUILDPLATFORM docker.io/library/rust:1.77.0-slim-bookworm as build COPY --from=xx / / ARG TARGETARCH ARG TARGETVARIANT diff --git a/rust-toolchain.toml b/rust-toolchain.toml index d8e821e8..d39770b2 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "1.76.0" +channel = "1.77.0" components = [ "rustfmt", "clippy" ] profile = "minimal" diff --git a/src/api/icons.rs b/src/api/icons.rs index f47357bb..2f76b86a 100644 --- a/src/api/icons.rs +++ b/src/api/icons.rs @@ -54,7 +54,7 @@ static CLIENT: Lazy = Lazy::new(|| { .timeout(icon_download_timeout) .pool_max_idle_per_host(5) // Configure the Hyper Pool to only have max 5 idle connections .pool_idle_timeout(pool_idle_timeout) // Configure the Hyper Pool to timeout after 10 seconds - .trust_dns(true) + .hickory_dns(true) .default_headers(default_headers.clone()); match client.build() { @@ -66,7 +66,7 @@ static CLIENT: Lazy = Lazy::new(|| { .timeout(icon_download_timeout) .pool_max_idle_per_host(5) // Configure the Hyper Pool to only have max 5 idle connections .pool_idle_timeout(pool_idle_timeout) // Configure the Hyper Pool to timeout after 10 seconds - .trust_dns(false) + .hickory_dns(false) .default_headers(default_headers) .build() .expect("Failed to build client") diff --git a/src/auth.rs b/src/auth.rs index 36e84613..3d5be269 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -34,7 +34,8 @@ pub fn initialize_keys() -> Result<(), crate::error::Error> { let mut priv_key_buffer = Vec::with_capacity(2048); let priv_key = { - let mut priv_key_file = File::options().create(true).read(true).write(true).open(CONFIG.private_rsa_key())?; + let mut priv_key_file = + File::options().create(true).truncate(false).read(true).write(true).open(CONFIG.private_rsa_key())?; #[allow(clippy::verbose_file_reads)] let bytes_read = priv_key_file.read_to_end(&mut priv_key_buffer)?; diff --git a/src/main.rs b/src/main.rs index e3b29383..12953979 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,7 @@ // The more key/value pairs there are the more recursion occurs. // We want to keep this as low as possible, but not higher then 128. // If you go above 128 it will cause rust-analyzer to fail, -#![recursion_limit = "103"] +#![recursion_limit = "87"] // When enabled use MiMalloc as malloc instead of the default malloc #[cfg(feature = "enable_mimalloc")] @@ -213,7 +213,7 @@ fn launch_info() { fn init_logging(level: log::LevelFilter) -> Result<(), fern::InitError> { // Depending on the main log level we either want to disable or enable logging for trust-dns. // Else if there are timeouts it will clutter the logs since trust-dns uses warn for this. - let trust_dns_level = if level >= log::LevelFilter::Debug { + let hickory_level = if level >= log::LevelFilter::Debug { level } else { log::LevelFilter::Off @@ -267,8 +267,8 @@ fn init_logging(level: log::LevelFilter) -> Result<(), fern::InitError> { // Prevent cookie_store logs .level_for("cookie_store", log::LevelFilter::Off) // Variable level for trust-dns used by reqwest - .level_for("trust_dns_resolver::name_server::name_server", trust_dns_level) - .level_for("trust_dns_proto::xfer", trust_dns_level) + .level_for("hickory_resolver::name_server::name_server", hickory_level) + .level_for("hickory_proto::xfer", hickory_level) .level_for("diesel_logger", diesel_logger_level) .chain(std::io::stdout()); diff --git a/src/util.rs b/src/util.rs index ed730cb7..d10dc6d8 100644 --- a/src/util.rs +++ b/src/util.rs @@ -706,7 +706,7 @@ pub fn get_reqwest_client() -> Client { Ok(client) => client, Err(e) => { error!("Possible trust-dns error, trying with trust-dns disabled: '{e}'"); - get_reqwest_client_builder().trust_dns(false).build().expect("Failed to build client") + get_reqwest_client_builder().hickory_dns(false).build().expect("Failed to build client") } } } From 2d98aa304501b0f710d3a97ec854acdfc115228f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Sat, 23 Mar 2024 16:03:17 +0100 Subject: [PATCH 04/14] Use async verify for Yubikey (#4448) --- src/api/core/two_factor/yubikey.rs | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/src/api/core/two_factor/yubikey.rs b/src/api/core/two_factor/yubikey.rs index ea43f36f..2b199dfd 100644 --- a/src/api/core/two_factor/yubikey.rs +++ b/src/api/core/two_factor/yubikey.rs @@ -1,7 +1,7 @@ use rocket::serde::json::Json; use rocket::Route; use serde_json::Value; -use yubico::{config::Config, verify}; +use yubico::{config::Config, verify_async}; use crate::{ api::{ @@ -74,13 +74,10 @@ async fn verify_yubikey_otp(otp: String) -> EmptyResult { let config = Config::default().set_client_id(yubico_id).set_key(yubico_secret); match CONFIG.yubico_server() { - Some(server) => { - tokio::task::spawn_blocking(move || verify(otp, config.set_api_hosts(vec![server]))).await.unwrap() - } - None => tokio::task::spawn_blocking(move || verify(otp, config)).await.unwrap(), + Some(server) => verify_async(otp, config.set_api_hosts(vec![server])).await, + None => verify_async(otp, config).await, } .map_res("Failed to verify OTP") - .and(Ok(())) } #[post("/two-factor/get-yubikey", data = "")] @@ -194,10 +191,6 @@ pub async fn validate_yubikey_login(response: &str, twofactor_data: &str) -> Emp err!("Given Yubikey is not registered"); } - let result = verify_yubikey_otp(response.to_owned()).await; - - match result { - Ok(_answer) => Ok(()), - Err(_e) => err!("Failed to verify Yubikey against OTP server"), - } + verify_yubikey_otp(response.to_owned()).await.map_res("Failed to verify Yubikey against OTP server")?; + Ok(()) } From 129b835ac7eaedba00c3aafcdaff2bbe263aaf2f Mon Sep 17 00:00:00 2001 From: Stefan Melmuk <509385+stefan0xC@users.noreply.github.com> Date: Sat, 6 Apr 2024 11:45:25 +0200 Subject: [PATCH 05/14] update web-vault to v2024.3.1 (new vertical layout) (#4468) * update web-vault to v2024.3.0 * update web-vault to v2024.3.1 --- docker/DockerSettings.yaml | 4 ++-- docker/Dockerfile.alpine | 12 ++++++------ docker/Dockerfile.debian | 12 ++++++------ 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docker/DockerSettings.yaml b/docker/DockerSettings.yaml index 9c4612ab..1034816d 100644 --- a/docker/DockerSettings.yaml +++ b/docker/DockerSettings.yaml @@ -1,6 +1,6 @@ --- -vault_version: "v2024.1.2b" -vault_image_digest: "sha256:798c0c893b6d16728878ff280b49da08863334d1f8dd88895580dc3dba622f08" +vault_version: "v2024.3.1" +vault_image_digest: "sha256:689b1e706f29e1858a5c7e0ec82e40fac793322e5e0ac9102ab09c2620207cd5" # Cross Compile Docker Helper Scripts v1.3.0 # We use the linux/amd64 platform shell scripts since there is no difference between the different platform scripts xx_image_digest: "sha256:c9609ace652bbe51dd4ce90e0af9d48a4590f1214246da5bc70e46f6dd586edc" diff --git a/docker/Dockerfile.alpine b/docker/Dockerfile.alpine index 56f2a6e7..b173a2fd 100644 --- a/docker/Dockerfile.alpine +++ b/docker/Dockerfile.alpine @@ -18,15 +18,15 @@ # - From https://hub.docker.com/r/vaultwarden/web-vault/tags, # click the tag name to view the digest of the image it currently points to. # - From the command line: -# $ docker pull docker.io/vaultwarden/web-vault:v2024.1.2b -# $ docker image inspect --format "{{.RepoDigests}}" docker.io/vaultwarden/web-vault:v2024.1.2b -# [docker.io/vaultwarden/web-vault@sha256:798c0c893b6d16728878ff280b49da08863334d1f8dd88895580dc3dba622f08] +# $ docker pull docker.io/vaultwarden/web-vault:v2024.3.1 +# $ docker image inspect --format "{{.RepoDigests}}" docker.io/vaultwarden/web-vault:v2024.3.1 +# [docker.io/vaultwarden/web-vault@sha256:689b1e706f29e1858a5c7e0ec82e40fac793322e5e0ac9102ab09c2620207cd5] # # - Conversely, to get the tag name from the digest: -# $ docker image inspect --format "{{.RepoTags}}" docker.io/vaultwarden/web-vault@sha256:798c0c893b6d16728878ff280b49da08863334d1f8dd88895580dc3dba622f08 -# [docker.io/vaultwarden/web-vault:v2024.1.2b] +# $ docker image inspect --format "{{.RepoTags}}" docker.io/vaultwarden/web-vault@sha256:689b1e706f29e1858a5c7e0ec82e40fac793322e5e0ac9102ab09c2620207cd5 +# [docker.io/vaultwarden/web-vault:v2024.3.1] # -FROM --platform=linux/amd64 docker.io/vaultwarden/web-vault@sha256:798c0c893b6d16728878ff280b49da08863334d1f8dd88895580dc3dba622f08 as vault +FROM --platform=linux/amd64 docker.io/vaultwarden/web-vault@sha256:689b1e706f29e1858a5c7e0ec82e40fac793322e5e0ac9102ab09c2620207cd5 as vault ########################## ALPINE BUILD IMAGES ########################## ## NOTE: The Alpine Base Images do not support other platforms then linux/amd64 diff --git a/docker/Dockerfile.debian b/docker/Dockerfile.debian index 51e38b89..42e475b5 100644 --- a/docker/Dockerfile.debian +++ b/docker/Dockerfile.debian @@ -18,15 +18,15 @@ # - From https://hub.docker.com/r/vaultwarden/web-vault/tags, # click the tag name to view the digest of the image it currently points to. # - From the command line: -# $ docker pull docker.io/vaultwarden/web-vault:v2024.1.2b -# $ docker image inspect --format "{{.RepoDigests}}" docker.io/vaultwarden/web-vault:v2024.1.2b -# [docker.io/vaultwarden/web-vault@sha256:798c0c893b6d16728878ff280b49da08863334d1f8dd88895580dc3dba622f08] +# $ docker pull docker.io/vaultwarden/web-vault:v2024.3.1 +# $ docker image inspect --format "{{.RepoDigests}}" docker.io/vaultwarden/web-vault:v2024.3.1 +# [docker.io/vaultwarden/web-vault@sha256:689b1e706f29e1858a5c7e0ec82e40fac793322e5e0ac9102ab09c2620207cd5] # # - Conversely, to get the tag name from the digest: -# $ docker image inspect --format "{{.RepoTags}}" docker.io/vaultwarden/web-vault@sha256:798c0c893b6d16728878ff280b49da08863334d1f8dd88895580dc3dba622f08 -# [docker.io/vaultwarden/web-vault:v2024.1.2b] +# $ docker image inspect --format "{{.RepoTags}}" docker.io/vaultwarden/web-vault@sha256:689b1e706f29e1858a5c7e0ec82e40fac793322e5e0ac9102ab09c2620207cd5 +# [docker.io/vaultwarden/web-vault:v2024.3.1] # -FROM --platform=linux/amd64 docker.io/vaultwarden/web-vault@sha256:798c0c893b6d16728878ff280b49da08863334d1f8dd88895580dc3dba622f08 as vault +FROM --platform=linux/amd64 docker.io/vaultwarden/web-vault@sha256:689b1e706f29e1858a5c7e0ec82e40fac793322e5e0ac9102ab09c2620207cd5 as vault ########################## Cross Compile Docker Helper Scripts ########################## ## We use the linux/amd64 no matter which Build Platform, since these are all bash scripts From e42a37c6c12bf7d51dd33ff7b6f000f4be6c8384 Mon Sep 17 00:00:00 2001 From: Mathijs van Veluw Date: Sat, 6 Apr 2024 13:55:10 +0200 Subject: [PATCH 06/14] Update crates and some Clippy fixes (#4475) - Updated all crates including reqwest - Fixed some clippy lints reported by nightly Rust --- Cargo.lock | 519 +++++++++++++++++++++--------- Cargo.toml | 30 +- src/api/admin.rs | 9 +- src/api/core/organizations.rs | 2 +- src/api/notifications.rs | 2 +- src/auth.rs | 6 +- src/db/models/cipher.rs | 2 +- src/db/models/emergency_access.rs | 4 +- src/util.rs | 2 +- 9 files changed, 401 insertions(+), 175 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ec358d68..1afed44f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -104,17 +104,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f28243a43d821d11341ab73c80bed182dc015c514b951616cf79bd4af39af0c3" dependencies = [ "concurrent-queue", - "event-listener 5.2.0", - "event-listener-strategy 0.5.0", + "event-listener 5.3.0", + "event-listener-strategy 0.5.1", "futures-core", "pin-project-lite", ] [[package]] name = "async-compression" -version = "0.4.6" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a116f46a969224200a0a97f29cfd4c50e7534e4b4826bd23ea2c3c533039c82c" +checksum = "07dbbf24db18d609b1462965249abdf49129ccad073ec257da372adc83259c60" dependencies = [ "brotli", "flate2", @@ -126,14 +126,14 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.8.0" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ae5ebefcc48e7452b4987947920dac9450be1110cadf34d1b8c116bdbaf97c" +checksum = "10b3e585719c2358d2660232671ca8ca4ddb4be4ce8a1842d6c2dc8685303316" dependencies = [ "async-lock 3.3.0", "async-task", "concurrent-queue", - "fastrand 2.0.1", + "fastrand 2.0.2", "futures-lite 2.3.0", "slab", ] @@ -185,7 +185,7 @@ dependencies = [ "futures-io", "futures-lite 2.3.0", "parking", - "polling 3.5.0", + "polling 3.6.0", "rustix 0.38.32", "slab", "tracing", @@ -293,7 +293,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -304,13 +304,13 @@ checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799" [[package]] name = "async-trait" -version = "0.1.78" +version = "0.1.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "461abc97219de0eaaf81fe3ef974a540158f3d079c2ab200f891f1a2ef201e85" +checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -336,15 +336,15 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" [[package]] name = "backtrace" -version = "0.3.70" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95d8e92cac0961e91dbd517496b00f7e9b92363dbe6d42c3198268323798860c" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", @@ -367,6 +367,12 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +[[package]] +name = "base64" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51" + [[package]] name = "base64ct" version = "1.6.0" @@ -431,7 +437,7 @@ dependencies = [ "async-channel 2.2.0", "async-lock 3.3.0", "async-task", - "fastrand 2.0.1", + "fastrand 2.0.2", "futures-io", "futures-lite 2.3.0", "piper", @@ -440,9 +446,9 @@ dependencies = [ [[package]] name = "brotli" -version = "3.5.0" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d640d25bc63c50fb1f0b545ffd80207d2e10a4c965530809b40ba3386825c391" +checksum = "125740193d7fee5cc63ab9e16c2fdc4e07c74ba755cc53b327d6ea029e9fc569" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -451,9 +457,9 @@ dependencies = [ [[package]] name = "brotli-decompressor" -version = "2.5.1" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e2e4afe60d7dd600fdd3de8d0f08c2b7ec039712e3b6137ff98b7004e82de4f" +checksum = "65622a320492e09b5e0ac436b14c54ff68199bac392d0e89a6832c4518eea525" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -479,9 +485,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "cached" @@ -533,9 +539,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.35" +version = "0.4.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a" +checksum = "8a0d04d43504c61aa6c7531f1871dd0d418d91130162063b789da00fd7057a5e" dependencies = [ "android-tzdata", "iana-time-zone", @@ -546,9 +552,9 @@ dependencies = [ [[package]] name = "chrono-tz" -version = "0.8.6" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59ae0466b83e838b81a54256c39d5d7c20b9d7daa10510a242d9b75abd5936e" +checksum = "93698b29de5e97ad0ae26447b344c482a7284c737d9ddc5f9e52b74a336671bb" dependencies = [ "chrono", "chrono-tz-build", @@ -557,9 +563,9 @@ dependencies = [ [[package]] name = "chrono-tz-build" -version = "0.2.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "433e39f13c9a060046954e0592a8d0a4bcb1040125cbf91cb8ee58964cfb350f" +checksum = "0c088aee841df9c3041febbb73934cfc39708749bf96dc827e3359cd39ef11b1" dependencies = [ "parse-zoneinfo", "phf", @@ -598,9 +604,9 @@ dependencies = [ [[package]] name = "cookie" -version = "0.18.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cd91cf61412820176e137621345ee43b3f4423e589e7ae4e50d601d93e35ef8" +checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747" dependencies = [ "percent-encoding", "time", @@ -630,7 +636,7 @@ version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4934e6b7e8419148b6ef56950d277af8561060b56afd59e2aadf98b59fce6baa" dependencies = [ - "cookie 0.18.0", + "cookie 0.18.1", "idna 0.5.0", "log", "publicsuffix", @@ -801,7 +807,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -837,7 +843,7 @@ dependencies = [ "diesel_table_macro_syntax", "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -867,7 +873,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc5557efc453706fed5e4fa85006fe9817c224c3f480a34c7e5959fd700921c5" dependencies = [ - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -895,11 +901,11 @@ checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" [[package]] name = "email-encoding" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbfb21b9878cf7a348dcb8559109aabc0ec40d69924bd706fa5149846c4fef75" +checksum = "60d1d33cdaede7e24091f039632eb5d3c7469fe5b066a985281a34fc70fa317f" dependencies = [ - "base64 0.21.7", + "base64 0.22.0", "memchr", ] @@ -930,7 +936,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -988,9 +994,9 @@ dependencies = [ [[package]] name = "event-listener" -version = "5.2.0" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b5fb89194fa3cad959b833185b3063ba881dbfc7030680b314250779fb4cc91" +checksum = "6d9944b8ca13534cdfb2800775f8dd4902ff3fc75a50101466decadfdf322a24" dependencies = [ "concurrent-queue", "parking", @@ -1009,11 +1015,11 @@ dependencies = [ [[package]] name = "event-listener-strategy" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "feedafcaa9b749175d5ac357452a9d41ea2911da598fde46ce1fe02c37751291" +checksum = "332f51cb23d20b0de8458b86580878211da09bcd4503cb579c225b3d124cabb3" dependencies = [ - "event-listener 5.2.0", + "event-listener 5.3.0", "pin-project-lite", ] @@ -1028,9 +1034,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" [[package]] name = "fern" @@ -1167,7 +1173,7 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" dependencies = [ - "fastrand 2.0.1", + "fastrand 2.0.2", "futures-core", "futures-io", "parking", @@ -1182,7 +1188,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -1246,9 +1252,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +checksum = "a06fddc2749e0528d2813f95e050e87e52c8cbbae56223b9babf73b3e53b0cc6" dependencies = [ "cfg-if", "js-sys", @@ -1303,16 +1309,35 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fbd2820c5e49886948654ab546d0688ff24530286bdcf8fca3cefb16d4618eb" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ "bytes", "fnv", "futures-core", "futures-sink", "futures-util", - "http", + "http 0.2.12", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "h2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "816ec7294445779408f36fe57bc5b7fc1cf59664059096c65f905c1c61f58069" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 1.1.0", "indexmap", "slab", "tokio", @@ -1328,9 +1353,9 @@ checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" [[package]] name = "handlebars" -version = "5.1.0" +version = "5.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab283476b99e66691dee3f1640fea91487a8d81f50fb5ecc75538f8f8879a1e4" +checksum = "d08485b96a0e6393e9e4d1b8d48cf74ad6c063cd905eb33f42c1ce3f0377539b" dependencies = [ "log", "pest", @@ -1457,6 +1482,17 @@ dependencies = [ "itoa", ] +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + [[package]] name = "http-body" version = "0.4.6" @@ -1464,7 +1500,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", - "http", + "http 0.2.12", + "pin-project-lite", +] + +[[package]] +name = "http-body" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +dependencies = [ + "bytes", + "http 1.1.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +dependencies = [ + "bytes", + "futures-core", + "http 1.1.0", + "http-body 1.0.0", "pin-project-lite", ] @@ -1490,9 +1549,9 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2", - "http", - "http-body", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", "httparse", "httpdate", "itoa", @@ -1504,6 +1563,26 @@ dependencies = [ "want", ] +[[package]] +name = "hyper" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2 0.4.4", + "http 1.1.0", + "http-body 1.0.0", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + [[package]] name = "hyper-tls" version = "0.5.0" @@ -1511,12 +1590,48 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ "bytes", - "hyper", + "hyper 0.14.28", "native-tls", "tokio", "tokio-native-tls", ] +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper 1.2.0", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "hyper 1.2.0", + "pin-project-lite", + "socket2 0.5.6", + "tokio", + "tower", + "tower-service", + "tracing", +] + [[package]] name = "iana-time-zone" version = "0.1.60" @@ -1578,9 +1693,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.5" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", "hashbrown", @@ -1622,7 +1737,7 @@ dependencies = [ "socket2 0.5.6", "widestring", "windows-sys 0.48.0", - "winreg", + "winreg 0.50.0", ] [[package]] @@ -1644,9 +1759,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jetscii" @@ -1706,17 +1821,17 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "lettre" -version = "0.11.4" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357ff5edb6d8326473a64c82cf41ddf78ab116f89668c50c4fac1b321e5e80f4" +checksum = "47460276655930189e0919e4fbf46e46476b14f934f18a63dd726a5fb7b60e2e" dependencies = [ "async-std", "async-trait", - "base64 0.21.7", + "base64 0.22.0", "chumsky", "email-encoding", "email_address", - "fastrand 2.0.1", + "fastrand 2.0.2", "futures-io", "futures-util", "hostname", @@ -1846,9 +1961,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.1" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "migrations_internals" @@ -1921,7 +2036,7 @@ dependencies = [ "bytes", "encoding_rs", "futures-util", - "http", + "http 0.2.12", "httparse", "log", "memchr", @@ -2017,7 +2132,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -2095,7 +2210,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -2115,9 +2230,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.101" +version = "0.9.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dda2b0f344e78efc2facf7d195d098df0dd72151b26ab98da807afc26c198dff" +checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" dependencies = [ "cc", "libc", @@ -2207,7 +2322,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -2228,9 +2343,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.8" +version = "2.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f8023d0fb78c8e03784ea1c7f3fa36e68a723138990b8d5a47d916b651e7a8" +checksum = "311fb059dee1a7b802f036316d790138c613a4e8b180c822e3925a662e9f0c95" dependencies = [ "memchr", "thiserror", @@ -2239,9 +2354,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.8" +version = "2.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0d24f72393fd16ab6ac5738bc33cdb6a9aa73f8b902e8fe29cf4e67d7dd1026" +checksum = "f73541b156d32197eecda1a4014d7f868fd2bcb3c550d5386087cfba442bf69c" dependencies = [ "pest", "pest_generator", @@ -2249,22 +2364,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.8" +version = "2.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc17e2a6c7d0a492f0158d7a4bd66cc17280308bbaff78d5bef566dca35ab80" +checksum = "c35eeed0a3fab112f75165fdc026b3913f4183133f19b49be773ac9ea966e8bd" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] name = "pest_meta" -version = "2.7.8" +version = "2.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "934cd7631c050f4674352a6e835d5f6711ffbfb9345c2fc0107155ac495ae293" +checksum = "2adbf29bb9776f28caece835398781ab24435585fe0d4dc1374a61db5accedca" dependencies = [ "once_cell", "pest", @@ -2316,10 +2431,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" [[package]] -name = "pin-project-lite" -version = "0.2.13" +name = "pin-project" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.58", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -2334,7 +2469,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" dependencies = [ "atomic-waker", - "fastrand 2.0.1", + "fastrand 2.0.2", "futures-io", ] @@ -2362,12 +2497,13 @@ dependencies = [ [[package]] name = "polling" -version = "3.5.0" +version = "3.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24f040dee2588b4963afb4e420540439d126f73fdacf4a9c486a96d840bac3c9" +checksum = "e0c976a60b2d7e99d6f229e414670a9b85d13ac305cc6d1e9c134de58c5aaaf6" dependencies = [ "cfg-if", "concurrent-queue", + "hermit-abi", "pin-project-lite", "rustix 0.38.32", "tracing", @@ -2418,7 +2554,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", "version_check", "yansi", ] @@ -2450,9 +2586,9 @@ dependencies = [ [[package]] name = "quanta" -version = "0.12.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ca0b7bac0b97248c40bb77288fc52029cf1459c0461ea1b05ee32ccf011de2c" +checksum = "8e5167a477619228a0b284fac2674e3c388cba90631d7b7de620e6f1fcd08da5" dependencies = [ "crossbeam-utils", "libc", @@ -2560,19 +2696,19 @@ checksum = "5fddb4f8d99b0a2ebafc65a87a69a7b9875e4b1ae1f00db265d300ef7f28bccc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] name = "regex" -version = "1.10.3" +version = "1.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ "aho-corasick", "memchr", "regex-automata 0.4.6", - "regex-syntax 0.8.2", + "regex-syntax 0.8.3", ] [[package]] @@ -2592,7 +2728,7 @@ checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.2", + "regex-syntax 0.8.3", ] [[package]] @@ -2603,9 +2739,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "reopen" @@ -2624,20 +2760,16 @@ version = "0.11.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ - "async-compression", "base64 0.21.7", "bytes", - "cookie 0.17.0", - "cookie_store 0.20.0", "encoding_rs", "futures-core", "futures-util", - "h2", - "hickory-resolver", - "http", - "http-body", - "hyper", - "hyper-tls", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.28", + "hyper-tls 0.5.0", "ipnet", "js-sys", "log", @@ -2646,7 +2778,53 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls-pemfile", + "rustls-pemfile 1.0.4", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg 0.50.0", +] + +[[package]] +name = "reqwest" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e6cc1e89e689536eb5aeede61520e874df5a4707df811cd5da4aa5fbb2aae19" +dependencies = [ + "async-compression", + "base64 0.22.0", + "bytes", + "cookie 0.17.0", + "cookie_store 0.20.0", + "encoding_rs", + "futures-core", + "futures-util", + "h2 0.4.4", + "hickory-resolver", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", + "hyper 1.2.0", + "hyper-tls 0.6.0", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile 2.1.1", "serde", "serde_json", "serde_urlencoded", @@ -2662,7 +2840,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "winreg", + "winreg 0.52.0", ] [[package]] @@ -2761,7 +2939,7 @@ dependencies = [ "proc-macro2", "quote", "rocket_http", - "syn 2.0.53", + "syn 2.0.58", "unicode-xid", "version_check", ] @@ -2772,11 +2950,11 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37a1663694d059fe5f943ea5481363e48050acedd241d46deb2e27f71110389e" dependencies = [ - "cookie 0.18.0", + "cookie 0.18.1", "either", "futures", - "http", - "hyper", + "http 0.2.12", + "hyper 0.14.28", "indexmap", "log", "memchr", @@ -2785,7 +2963,7 @@ dependencies = [ "pin-project-lite", "ref-cast", "rustls", - "rustls-pemfile", + "rustls-pemfile 1.0.4", "serde", "smallvec", "stable-pattern", @@ -2881,6 +3059,22 @@ dependencies = [ "base64 0.21.7", ] +[[package]] +name = "rustls-pemfile" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f48172685e6ff52a556baa527774f61fcaa884f59daf3375c62a3f1cd2549dab" +dependencies = [ + "base64 0.21.7", + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecd36cc4259e3e4514335c4a138c6b43171a8d61d8f5c9348f9fc7529416f247" + [[package]] name = "rustls-webpki" version = "0.101.7" @@ -2954,9 +3148,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.2" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" dependencies = [ "bitflags 1.3.2", "core-foundation", @@ -2967,9 +3161,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.1" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef" dependencies = [ "core-foundation-sys", "libc", @@ -3008,14 +3202,14 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] name = "serde_json" -version = "1.0.114" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" dependencies = [ "itoa", "ryu", @@ -3217,9 +3411,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.53" +version = "2.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032" +checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" dependencies = [ "proc-macro2", "quote", @@ -3273,7 +3467,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", - "fastrand 2.0.1", + "fastrand 2.0.2", "rustix 0.38.32", "windows-sys 0.52.0", ] @@ -3295,7 +3489,7 @@ checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -3367,9 +3561,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.36.0" +version = "1.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ "backtrace", "bytes", @@ -3392,7 +3586,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -3535,6 +3729,28 @@ dependencies = [ "sha2", ] +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + [[package]] name = "tower-service" version = "0.3.2" @@ -3561,7 +3777,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -3618,7 +3834,7 @@ dependencies = [ "byteorder", "bytes", "data-encoding", - "http", + "http 0.2.12", "httparse", "log", "rand", @@ -3741,7 +3957,7 @@ dependencies = [ "cached", "chrono", "chrono-tz", - "cookie 0.18.0", + "cookie 0.18.1", "cookie_store 0.21.0", "dashmap", "data-encoding", @@ -3771,7 +3987,7 @@ dependencies = [ "pico-args", "rand", "regex", - "reqwest", + "reqwest 0.12.3", "ring", "rmpv", "rocket", @@ -3856,7 +4072,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", "wasm-bindgen-shared", ] @@ -3890,7 +4106,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3945,15 +4161,14 @@ dependencies = [ [[package]] name = "which" -version = "6.0.0" +version = "6.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fa5e0c10bf77f44aac573e498d1a82d5fbd5e91f6fc0a99e7be4b38e85e101c" +checksum = "8211e4f58a2b2805adfbefbc07bab82958fc91e3836339b1ab7ae32465dce0d7" dependencies = [ "either", "home", - "once_cell", "rustix 0.38.32", - "windows-sys 0.52.0", + "winsafe", ] [[package]] @@ -4171,6 +4386,22 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "winreg" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "winsafe" +version = "0.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" + [[package]] name = "yansi" version = "1.0.1" @@ -4191,7 +4422,7 @@ dependencies = [ "futures", "hmac", "rand", - "reqwest", + "reqwest 0.11.27", "sha1", "threadpool", ] @@ -4213,5 +4444,5 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] diff --git a/Cargo.toml b/Cargo.toml index 22008c9f..16546a7f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -67,11 +67,11 @@ dashmap = "5.5.3" # Async futures futures = "0.3.30" -tokio = { version = "1.36.0", features = ["rt-multi-thread", "fs", "io-util", "parking_lot", "time", "signal"] } +tokio = { version = "1.37.0", features = ["rt-multi-thread", "fs", "io-util", "parking_lot", "time", "signal"] } # A generic serialization/deserialization framework serde = { version = "1.0.197", features = ["derive"] } -serde_json = "1.0.114" +serde_json = "1.0.115" # A safe, extensible ORM and Query builder diesel = { version = "2.1.5", features = ["chrono", "r2d2", "numeric"] } @@ -89,8 +89,8 @@ ring = "0.17.8" uuid = { version = "1.8.0", features = ["v4"] } # Date and time libraries -chrono = { version = "0.4.35", features = ["clock", "serde"], default-features = false } -chrono-tz = "0.8.6" +chrono = { version = "0.4.37", features = ["clock", "serde"], default-features = false } +chrono-tz = "0.9.0" time = "0.3.34" # Job scheduler @@ -115,27 +115,27 @@ webauthn-rs = "0.3.2" url = "2.5.0" # Email libraries -lettre = { version = "0.11.4", features = ["smtp-transport", "sendmail-transport", "builder", "serde", "tokio1-native-tls", "hostname", "tracing", "tokio1"], default-features = false } +lettre = { version = "0.11.6", features = ["smtp-transport", "sendmail-transport", "builder", "serde", "tokio1-native-tls", "hostname", "tracing", "tokio1"], default-features = false } percent-encoding = "2.3.1" # URL encoding library used for URL's in the emails email_address = "0.2.4" # HTML Template library -handlebars = { version = "5.1.0", features = ["dir_source"] } +handlebars = { version = "5.1.2", features = ["dir_source"] } # HTTP client (Used for favicons, version check, DUO and HIBP API) -reqwest = { version = "0.11.27", features = ["default-tls", "native-tls-alpn", "stream", "json", "gzip", "brotli", "socks", "cookies", "hickory-dns"], default-features = false} +reqwest = { version = "0.12.3", features = ["native-tls-alpn", "stream", "json", "gzip", "brotli", "socks", "cookies", "hickory-dns"] } # Favicon extraction libraries html5gum = "0.5.7" -regex = { version = "1.10.3", features = ["std", "perf", "unicode-perl"], default-features = false } +regex = { version = "1.10.4", features = ["std", "perf", "unicode-perl"], default-features = false } data-url = "0.3.1" -bytes = "1.5.0" +bytes = "1.6.0" # Cache function results (Used for version check and favicon fetching) cached = { version = "0.49.2", features = ["async"] } # Used for custom short lived cookie jar during favicon extraction -cookie = "0.18.0" +cookie = "0.18.1" cookie_store = "0.21.0" # Used by U2F, JWT and PostgreSQL @@ -154,7 +154,7 @@ semver = "1.0.22" # Allow overriding the default memory allocator # Mainly used for the musl builds, since the default musl malloc is very slow mimalloc = { version = "0.1.39", features = ["secure"], default-features = false, optional = true } -which = "6.0.0" +which = "6.0.1" # Argon2 library with support for the PHC format argon2 = "0.5.3" @@ -205,14 +205,14 @@ unsafe_code = "forbid" non_ascii_idents = "forbid" # Deny -future_incompatible = "deny" +future_incompatible = { level = "deny", priority = -1 } noop_method_call = "deny" pointer_structural_match = "deny" -rust_2018_idioms = "deny" -rust_2021_compatibility = "deny" +rust_2018_idioms = { level = "deny", priority = -1 } +rust_2021_compatibility = { level = "deny", priority = -1 } trivial_casts = "deny" trivial_numeric_casts = "deny" -unused = "deny" +unused = { level = "deny", priority = -1 } unused_import_braces = "deny" unused_lifetimes = "deny" deprecated_in_future = "deny" diff --git a/src/api/admin.rs b/src/api/admin.rs index 4c8d5604..b3dc588c 100644 --- a/src/api/admin.rs +++ b/src/api/admin.rs @@ -701,10 +701,7 @@ async fn diagnostics(_token: AdminToken, ip_header: IpHeader, mut conn: DbConn) let (latest_release, latest_commit, latest_web_build) = get_release_info(has_http_access, running_within_container).await; - let ip_header_name = match &ip_header.0 { - Some(h) => h, - _ => "", - }; + let ip_header_name = &ip_header.0.unwrap_or_default(); let diagnostics_json = json!({ "dns_resolved": dns_resolved, @@ -717,8 +714,8 @@ async fn diagnostics(_token: AdminToken, ip_header: IpHeader, mut conn: DbConn) "running_within_container": running_within_container, "container_base_image": if running_within_container { container_base_image() } else { "Not applicable" }, "has_http_access": has_http_access, - "ip_header_exists": &ip_header.0.is_some(), - "ip_header_match": ip_header_name == CONFIG.ip_header(), + "ip_header_exists": !ip_header_name.is_empty(), + "ip_header_match": ip_header_name.eq(&CONFIG.ip_header()), "ip_header_name": ip_header_name, "ip_header_config": &CONFIG.ip_header(), "uses_proxy": uses_proxy, diff --git a/src/api/core/organizations.rs b/src/api/core/organizations.rs index 1d841cda..840ae6ea 100644 --- a/src/api/core/organizations.rs +++ b/src/api/core/organizations.rs @@ -2247,7 +2247,7 @@ impl GroupRequest { } pub fn update_group(&self, mut group: Group) -> Group { - group.name = self.Name.clone(); + group.name.clone_from(&self.Name); group.access_all = self.AccessAll.unwrap_or(false); // Group Updates do not support changing the external_id // These input fields are in a disabled state, and can only be updated/added via ldap_import diff --git a/src/api/notifications.rs b/src/api/notifications.rs index 7a1aa2ac..e4707399 100644 --- a/src/api/notifications.rs +++ b/src/api/notifications.rs @@ -289,7 +289,7 @@ fn serialize(val: Value) -> Vec { fn serialize_date(date: NaiveDateTime) -> Value { let seconds: i64 = date.and_utc().timestamp(); - let nanos: i64 = date.timestamp_subsec_nanos().into(); + let nanos: i64 = date.and_utc().timestamp_subsec_nanos().into(); let timestamp = nanos << 34 | seconds; let bs = timestamp.to_be_bytes(); diff --git a/src/auth.rs b/src/auth.rs index 3d5be269..3f92be76 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -4,7 +4,7 @@ use chrono::{TimeDelta, Utc}; use num_traits::FromPrimitive; use once_cell::sync::{Lazy, OnceCell}; -use jsonwebtoken::{self, errors::ErrorKind, Algorithm, DecodingKey, EncodingKey, Header}; +use jsonwebtoken::{errors::ErrorKind, Algorithm, DecodingKey, EncodingKey, Header}; use openssl::rsa::Rsa; use serde::de::DeserializeOwned; use serde::ser::Serialize; @@ -391,10 +391,8 @@ impl<'r> FromRequest<'r> for Host { let host = if let Some(host) = headers.get_one("X-Forwarded-Host") { host - } else if let Some(host) = headers.get_one("Host") { - host } else { - "" + headers.get_one("Host").unwrap_or_default() }; format!("{protocol}://{host}") diff --git a/src/db/models/cipher.rs b/src/db/models/cipher.rs index 0574a833..3ed3401a 100644 --- a/src/db/models/cipher.rs +++ b/src/db/models/cipher.rs @@ -431,7 +431,7 @@ impl Cipher { } if let Some(ref org_uuid) = self.organization_uuid { if let Some(cipher_sync_data) = cipher_sync_data { - return cipher_sync_data.user_group_full_access_for_organizations.get(org_uuid).is_some(); + return cipher_sync_data.user_group_full_access_for_organizations.contains(org_uuid); } else { return Group::is_in_full_access_group(user_uuid, org_uuid, conn).await; } diff --git a/src/db/models/emergency_access.rs b/src/db/models/emergency_access.rs index ccb21e5b..c3682920 100644 --- a/src/db/models/emergency_access.rs +++ b/src/db/models/emergency_access.rs @@ -174,7 +174,7 @@ impl EmergencyAccess { // Update the grantee so that it will refresh it's status. User::update_uuid_revision(self.grantee_uuid.as_ref().expect("Error getting grantee"), conn).await; self.status = status; - self.updated_at = date.to_owned(); + date.clone_into(&mut self.updated_at); db_run! {conn: { crate::util::retry(|| { @@ -192,7 +192,7 @@ impl EmergencyAccess { conn: &mut DbConn, ) -> EmptyResult { self.last_notification_at = Some(date.to_owned()); - self.updated_at = date.to_owned(); + date.clone_into(&mut self.updated_at); db_run! {conn: { crate::util::retry(|| { diff --git a/src/util.rs b/src/util.rs index d10dc6d8..8aae4bd1 100644 --- a/src/util.rs +++ b/src/util.rs @@ -520,7 +520,7 @@ pub fn container_base_image() -> &'static str { use std::fmt; use serde::de::{self, DeserializeOwned, Deserializer, MapAccess, SeqAccess, Visitor}; -use serde_json::{self, Value}; +use serde_json::Value; pub type JsonMap = serde_json::Map; From e1a8df96dbadfbf5ad36ce9aa2f31f34396166c2 Mon Sep 17 00:00:00 2001 From: Mathijs van Veluw Date: Sat, 6 Apr 2024 14:42:53 +0200 Subject: [PATCH 07/14] Update Key Rotation web-vault v2024.3.x (#4446) Key rotation was changed since 2024.1.x. Multiple other items were added to be rotated like password-reset and emergency-access data to be part of just one POST instead of having multiple. See: https://github.com/dani-garcia/bw_web_builds/pull/157 --- src/api/core/accounts.rs | 110 +++++++++++++++++++++++++++++++-------- src/api/core/ciphers.rs | 2 +- src/api/core/mod.rs | 7 ++- src/api/core/sends.rs | 45 ++++++++++------ 4 files changed, 123 insertions(+), 41 deletions(-) diff --git a/src/api/core/accounts.rs b/src/api/core/accounts.rs index da25d488..ff74c84f 100644 --- a/src/api/core/accounts.rs +++ b/src/api/core/accounts.rs @@ -438,24 +438,46 @@ async fn post_kdf(data: JsonUpcase, headers: Headers, mut conn: D #[derive(Deserialize)] #[allow(non_snake_case)] struct UpdateFolderData { - Id: String, + // There is a bug in 2024.3.x which adds a `null` item. + // To bypass this we allow a Option here, but skip it during the updates + // See: https://github.com/bitwarden/clients/issues/8453 + Id: Option, Name: String, } +#[derive(Deserialize)] +#[allow(non_snake_case)] +struct UpdateEmergencyAccessData { + Id: String, + KeyEncrypted: String, +} + +#[derive(Deserialize)] +#[allow(non_snake_case)] +struct UpdateResetPasswordData { + OrganizationId: String, + ResetPasswordKey: String, +} + use super::ciphers::CipherData; +use super::sends::{update_send_from_data, SendData}; #[derive(Deserialize)] #[allow(non_snake_case)] struct KeyData { Ciphers: Vec, Folders: Vec, + Sends: Vec, + EmergencyAccessKeys: Vec, + ResetPasswordKeys: Vec, Key: String, - PrivateKey: String, MasterPasswordHash: String, + PrivateKey: String, } #[post("/accounts/key", data = "")] async fn post_rotatekey(data: JsonUpcase, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult { + // TODO: See if we can wrap everything within a SQL Transaction. If something fails it should revert everything. let data: KeyData = data.into_inner().data; if !headers.user.check_valid_password(&data.MasterPasswordHash) { @@ -472,37 +494,83 @@ async fn post_rotatekey(data: JsonUpcase, headers: Headers, mut conn: D // Update folder data for folder_data in data.Folders { - let mut saved_folder = match Folder::find_by_uuid(&folder_data.Id, &mut conn).await { - Some(folder) => folder, - None => err!("Folder doesn't exist"), + // Skip `null` folder id entries. + // See: https://github.com/bitwarden/clients/issues/8453 + if let Some(folder_id) = folder_data.Id { + let mut saved_folder = match Folder::find_by_uuid(&folder_id, &mut conn).await { + Some(folder) => folder, + None => err!("Folder doesn't exist"), + }; + + if &saved_folder.user_uuid != user_uuid { + err!("The folder is not owned by the user") + } + + saved_folder.name = folder_data.Name; + saved_folder.save(&mut conn).await? + } + } + + // Update emergency access data + for emergency_access_data in data.EmergencyAccessKeys { + let mut saved_emergency_access = match EmergencyAccess::find_by_uuid(&emergency_access_data.Id, &mut conn).await + { + Some(emergency_access) => emergency_access, + None => err!("Emergency access doesn't exist"), }; - if &saved_folder.user_uuid != user_uuid { - err!("The folder is not owned by the user") + if &saved_emergency_access.grantor_uuid != user_uuid { + err!("The emergency access is not owned by the user") } - saved_folder.name = folder_data.Name; - saved_folder.save(&mut conn).await? + saved_emergency_access.key_encrypted = Some(emergency_access_data.KeyEncrypted); + saved_emergency_access.save(&mut conn).await? + } + + // Update reset password data + for reset_password_data in data.ResetPasswordKeys { + let mut user_org = + match UserOrganization::find_by_user_and_org(user_uuid, &reset_password_data.OrganizationId, &mut conn) + .await + { + Some(reset_password) => reset_password, + None => err!("Reset password doesn't exist"), + }; + + user_org.reset_password_key = Some(reset_password_data.ResetPasswordKey); + user_org.save(&mut conn).await? + } + + // Update send data + for send_data in data.Sends { + let mut send = match Send::find_by_uuid(send_data.Id.as_ref().unwrap(), &mut conn).await { + Some(send) => send, + None => err!("Send doesn't exist"), + }; + + update_send_from_data(&mut send, send_data, &headers, &mut conn, &nt, UpdateType::None).await?; } // Update cipher data use super::ciphers::update_cipher_from_data; for cipher_data in data.Ciphers { - let mut saved_cipher = match Cipher::find_by_uuid(cipher_data.Id.as_ref().unwrap(), &mut conn).await { - Some(cipher) => cipher, - None => err!("Cipher doesn't exist"), - }; + if cipher_data.OrganizationId.is_none() { + let mut saved_cipher = match Cipher::find_by_uuid(cipher_data.Id.as_ref().unwrap(), &mut conn).await { + Some(cipher) => cipher, + None => err!("Cipher doesn't exist"), + }; - if saved_cipher.user_uuid.as_ref().unwrap() != user_uuid { - err!("The cipher is not owned by the user") + if saved_cipher.user_uuid.as_ref().unwrap() != user_uuid { + err!("The cipher is not owned by the user") + } + + // Prevent triggering cipher updates via WebSockets by settings UpdateType::None + // The user sessions are invalidated because all the ciphers were re-encrypted and thus triggering an update could cause issues. + // We force the users to logout after the user has been saved to try and prevent these issues. + update_cipher_from_data(&mut saved_cipher, cipher_data, &headers, false, &mut conn, &nt, UpdateType::None) + .await? } - - // Prevent triggering cipher updates via WebSockets by settings UpdateType::None - // The user sessions are invalidated because all the ciphers were re-encrypted and thus triggering an update could cause issues. - // We force the users to logout after the user has been saved to try and prevent these issues. - update_cipher_from_data(&mut saved_cipher, cipher_data, &headers, false, &mut conn, &nt, UpdateType::None) - .await? } // Update user data diff --git a/src/api/core/ciphers.rs b/src/api/core/ciphers.rs index b3dca3b6..51a9589d 100644 --- a/src/api/core/ciphers.rs +++ b/src/api/core/ciphers.rs @@ -205,7 +205,7 @@ pub struct CipherData { // Folder id is not included in import FolderId: Option, // TODO: Some of these might appear all the time, no need for Option - OrganizationId: Option, + pub OrganizationId: Option, Key: Option, diff --git a/src/api/core/mod.rs b/src/api/core/mod.rs index 7712ea82..1d31b27c 100644 --- a/src/api/core/mod.rs +++ b/src/api/core/mod.rs @@ -191,14 +191,17 @@ fn version() -> Json<&'static str> { #[get("/config")] fn config() -> Json { let domain = crate::CONFIG.domain(); - let feature_states = parse_experimental_client_feature_flags(&crate::CONFIG.experimental_client_feature_flags()); + 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); Json(json!({ // Note: The clients use this version to handle backwards compatibility concerns // This means they expect a version that closely matches the Bitwarden server version // We should make sure that we keep this updated when we support the new server features // Version history: // - Individual cipher key encryption: 2023.9.1 - "version": "2023.9.1", + "version": "2024.2.0", "gitHash": option_env!("GIT_REV"), "server": { "name": "Vaultwarden", diff --git a/src/api/core/sends.rs b/src/api/core/sends.rs index 6842d398..338510c6 100644 --- a/src/api/core/sends.rs +++ b/src/api/core/sends.rs @@ -49,7 +49,7 @@ pub async fn purge_sends(pool: DbPool) { #[derive(Deserialize)] #[allow(non_snake_case)] -struct SendData { +pub struct SendData { Type: i32, Key: String, Password: Option, @@ -65,6 +65,9 @@ struct SendData { Text: Option, File: Option, FileLength: Option, + + // Used for key rotations + pub Id: Option, } /// Enforces the `Disable Send` policy. A non-owner/admin user belonging to @@ -549,6 +552,19 @@ async fn put_send( None => err!("Send not found"), }; + update_send_from_data(&mut send, data, &headers, &mut conn, &nt, UpdateType::SyncSendUpdate).await?; + + Ok(Json(send.to_json())) +} + +pub async fn update_send_from_data( + send: &mut Send, + data: SendData, + headers: &Headers, + conn: &mut DbConn, + nt: &Notify<'_>, + ut: UpdateType, +) -> EmptyResult { if send.user_uuid.as_ref() != Some(&headers.user.uuid) { err!("Send is not owned by user") } @@ -557,6 +573,12 @@ async fn put_send( err!("Sends can't change type") } + if data.DeletionDate > Utc::now() + TimeDelta::try_days(31).unwrap() { + err!( + "You cannot have a Send with a deletion date that far into the future. Adjust the Deletion Date to a value less than 31 days from now and try again." + ); + } + // When updating a file Send, we receive nulls in the File field, as it's immutable, // so we only need to update the data field in the Text case if data.Type == SendType::Text as i32 { @@ -569,11 +591,6 @@ async fn put_send( send.data = data_str; } - if data.DeletionDate > Utc::now() + TimeDelta::try_days(31).unwrap() { - err!( - "You cannot have a Send with a deletion date that far into the future. Adjust the Deletion Date to a value less than 31 days from now and try again." - ); - } send.name = data.Name; send.akey = data.Key; send.deletion_date = data.DeletionDate.naive_utc(); @@ -591,17 +608,11 @@ async fn put_send( send.set_password(Some(&password)); } - send.save(&mut conn).await?; - nt.send_send_update( - UpdateType::SyncSendUpdate, - &send, - &send.update_users_revision(&mut conn).await, - &headers.device.uuid, - &mut conn, - ) - .await; - - Ok(Json(send.to_json())) + send.save(conn).await?; + if ut != UpdateType::None { + nt.send_send_update(ut, send, &send.update_users_revision(conn).await, &headers.device.uuid, conn).await; + } + Ok(()) } #[delete("/sends/")] From 2ad33ec97f415edb2af054f527efed52b3b93a9e Mon Sep 17 00:00:00 2001 From: Mathijs van Veluw Date: Sat, 27 Apr 2024 00:53:42 +0200 Subject: [PATCH 08/14] Update Crate and Rust (#4522) * Update Crate and Rust - Updated all crates - Updated Rust to the latest patch version * Updated GitHub Actions --- .github/workflows/build.yml | 6 +- .github/workflows/hadolint.yml | 2 +- .github/workflows/release.yml | 22 +- .github/workflows/trivy.yml | 6 +- Cargo.lock | 440 +++++++++++++++++---------------- Cargo.toml | 24 +- docker/DockerSettings.yaml | 6 +- docker/Dockerfile.alpine | 8 +- docker/Dockerfile.debian | 4 +- rust-toolchain.toml | 2 +- 10 files changed, 268 insertions(+), 252 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e78c0eba..f3cf942e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -46,7 +46,7 @@ jobs: steps: # Checkout the repo - name: "Checkout" - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b #v4.1.4 # End Checkout the repo @@ -74,7 +74,7 @@ jobs: # Only install the clippy and rustfmt components on the default rust-toolchain - name: "Install rust-toolchain version" - uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # master @ 2023-12-07 - 10:22 PM GMT+1 + uses: dtolnay/rust-toolchain@bb45937a053e097f8591208d8e74c90db1873d07 # master @ Apr 14, 2024, 9:02 PM GMT+2 if: ${{ matrix.channel == 'rust-toolchain' }} with: toolchain: "${{steps.toolchain.outputs.RUST_TOOLCHAIN}}" @@ -84,7 +84,7 @@ jobs: # Install the any other channel to be used for which we do not execute clippy and rustfmt - name: "Install MSRV version" - uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # master @ 2023-12-07 - 10:22 PM GMT+1 + uses: dtolnay/rust-toolchain@bb45937a053e097f8591208d8e74c90db1873d07 # master @ Apr 14, 2024, 9:02 PM GMT+2 if: ${{ matrix.channel != 'rust-toolchain' }} with: toolchain: "${{steps.toolchain.outputs.RUST_TOOLCHAIN}}" diff --git a/.github/workflows/hadolint.yml b/.github/workflows/hadolint.yml index 82acc926..923d8372 100644 --- a/.github/workflows/hadolint.yml +++ b/.github/workflows/hadolint.yml @@ -13,7 +13,7 @@ jobs: steps: # Checkout the repo - name: Checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 # End Checkout the repo # Download hadolint - https://github.com/hadolint/hadolint/releases diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8063827d..baf48763 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -58,7 +58,7 @@ jobs: steps: # Checkout the repo - name: Checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: fetch-depth: 0 @@ -69,11 +69,11 @@ jobs: # Start Docker Buildx - name: Setup Docker Buildx - uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0 + uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # v3.3.0 # https://github.com/moby/buildkit/issues/3969 # Also set max parallelism to 2, the default of 4 breaks GitHub Actions with: - config-inline: | + buildkitd-config-inline: | [worker.oci] max-parallelism = 2 driver-opts: | @@ -102,7 +102,7 @@ jobs: # Login to Docker Hub - name: Login to Docker Hub - uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0 + uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3.1.0 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} @@ -116,7 +116,7 @@ jobs: # Login to GitHub Container Registry - name: Login to GitHub Container Registry - uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0 + uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3.1.0 with: registry: ghcr.io username: ${{ github.repository_owner }} @@ -137,7 +137,7 @@ jobs: # Login to Quay.io - name: Login to Quay.io - uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0 + uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3.1.0 with: registry: quay.io username: ${{ secrets.QUAY_USERNAME }} @@ -171,7 +171,7 @@ jobs: echo "CONTAINER_REGISTRIES=${CONTAINER_REGISTRIES:+${CONTAINER_REGISTRIES},}localhost:5000/vaultwarden/server" | tee -a "${GITHUB_ENV}" - name: Bake ${{ matrix.base_image }} containers - uses: docker/bake-action@849707117b03d39aba7924c50a10376a69e88d7d # v4.1.0 + uses: docker/bake-action@73b0efa7a0e8ac276e0a8d5c580698a942ff10b5 # v4.4.0 env: BASE_TAGS: "${{ env.BASE_TAGS }}" SOURCE_COMMIT: "${{ env.SOURCE_COMMIT }}" @@ -229,28 +229,28 @@ jobs: # Upload artifacts to Github Actions - name: "Upload amd64 artifact" - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 if: ${{ matrix.base_image == 'alpine' }} with: name: vaultwarden-${{ env.SOURCE_VERSION }}-linux-amd64 path: vaultwarden-amd64 - name: "Upload arm64 artifact" - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 if: ${{ matrix.base_image == 'alpine' }} with: name: vaultwarden-${{ env.SOURCE_VERSION }}-linux-arm64 path: vaultwarden-arm64 - name: "Upload armv7 artifact" - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 if: ${{ matrix.base_image == 'alpine' }} with: name: vaultwarden-${{ env.SOURCE_VERSION }}-linux-armv7 path: vaultwarden-armv7 - name: "Upload armv6 artifact" - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 if: ${{ matrix.base_image == 'alpine' }} with: name: vaultwarden-${{ env.SOURCE_VERSION }}-linux-armv6 diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml index caecf695..86448485 100644 --- a/.github/workflows/trivy.yml +++ b/.github/workflows/trivy.yml @@ -25,10 +25,10 @@ jobs: actions: read steps: - name: Checkout code - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b #v4.1.4 - name: Run Trivy vulnerability scanner - uses: aquasecurity/trivy-action@d43c1f16c00cfd3978dde6c07f4bbcf9eb6993ca # v0.16.1 + uses: aquasecurity/trivy-action@d710430a6722f083d3b36b8339ff66b32f22ee55 # v0.19.0 with: scan-type: repo ignore-unfixed: true @@ -37,6 +37,6 @@ jobs: severity: CRITICAL,HIGH - name: Upload Trivy scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@b7bf0a3ed3ecfa44160715d7c442788f65f0f923 # v3.23.2 + uses: github/codeql-action/upload-sarif@2bbafcdd7fbf96243689e764c2f15d9735164f33 # v3.25.3 with: sarif_file: 'trivy-results.sarif' diff --git a/Cargo.lock b/Cargo.lock index 1afed44f..23406ed3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -55,9 +55,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.16" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "android-tzdata" @@ -99,9 +99,9 @@ dependencies = [ [[package]] name = "async-channel" -version = "2.2.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28243a43d821d11341ab73c80bed182dc015c514b951616cf79bd4af39af0c3" +checksum = "136d4d23bcc79e27423727b36823d86233aad06dfea531837b038394d11e9928" dependencies = [ "concurrent-queue", "event-listener 5.3.0", @@ -112,9 +112,9 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dbbf24db18d609b1462965249abdf49129ccad073ec257da372adc83259c60" +checksum = "4e9eabd7a98fe442131a17c316bd9349c43695e49e730c3c8e12cfb5f4da2693" dependencies = [ "brotli", "flate2", @@ -126,11 +126,10 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.9.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10b3e585719c2358d2660232671ca8ca4ddb4be4ce8a1842d6c2dc8685303316" +checksum = "b10202063978b3351199d68f8b22c4e47e4b1b822f8d43fd862d5ea8c006b29a" dependencies = [ - "async-lock 3.3.0", "async-task", "concurrent-queue", "fastrand 2.0.2", @@ -144,7 +143,7 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" dependencies = [ - "async-channel 2.2.0", + "async-channel 2.2.1", "async-executor", "async-io 2.3.2", "async-lock 3.3.0", @@ -185,8 +184,8 @@ dependencies = [ "futures-io", "futures-lite 2.3.0", "parking", - "polling 3.6.0", - "rustix 0.38.32", + "polling 3.7.0", + "rustix 0.38.34", "slab", "tracing", "windows-sys 0.52.0", @@ -225,26 +224,26 @@ dependencies = [ "cfg-if", "event-listener 3.1.0", "futures-lite 1.13.0", - "rustix 0.38.32", + "rustix 0.38.34", "windows-sys 0.48.0", ] [[package]] name = "async-signal" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e47d90f65a225c4527103a8d747001fc56e375203592b25ad103e1ca13124c5" +checksum = "afe66191c335039c7bb78f99dc7520b0cbb166b3a1cb33a03f53d8a1c6f2afda" dependencies = [ "async-io 2.3.2", - "async-lock 2.8.0", + "async-lock 3.3.0", "atomic-waker", "cfg-if", "futures-core", "futures-io", - "rustix 0.38.32", + "rustix 0.38.34", "signal-hook-registry", "slab", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -293,7 +292,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn", ] [[package]] @@ -304,13 +303,13 @@ checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799" [[package]] name = "async-trait" -version = "0.1.79" +version = "0.1.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn", ] [[package]] @@ -434,7 +433,7 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118" dependencies = [ - "async-channel 2.2.0", + "async-channel 2.2.1", "async-lock 3.3.0", "async-task", "fastrand 2.0.2", @@ -446,9 +445,9 @@ dependencies = [ [[package]] name = "brotli" -version = "4.0.0" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "125740193d7fee5cc63ab9e16c2fdc4e07c74ba755cc53b327d6ea029e9fc569" +checksum = "19483b140a7ac7174d34b5a581b406c64f84da5409d3e09cf4fff604f9270e67" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -457,9 +456,9 @@ dependencies = [ [[package]] name = "brotli-decompressor" -version = "3.0.0" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65622a320492e09b5e0ac436b14c54ff68199bac392d0e89a6832c4518eea525" +checksum = "e6221fe77a248b9117d431ad93761222e1cf8ff282d9d1d5d9f53d6299a1cf76" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -467,9 +466,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.15.4" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" @@ -491,9 +490,9 @@ checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "cached" -version = "0.49.2" +version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f251fd1e72720ca07bf5d8e310f54a193fd053479a1f6342c6663ee4fa01cf96" +checksum = "10a7d38ed2761b8a13ce42bc44b09d5a052b88da2f9fead624c779f31ac0729a" dependencies = [ "ahash", "async-trait", @@ -509,14 +508,14 @@ dependencies = [ [[package]] name = "cached_proc_macro" -version = "0.20.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad9f16c0d84de31a2ab7fdf5f7783c14631f7075cf464eb3bb43119f61c9cb2a" +checksum = "771aa57f3b17da6c8bcacb187bb9ec9bc81c8160e72342e67c329e0e1651a669" dependencies = [ "darling", "proc-macro2", "quote", - "syn 1.0.109", + "syn", ] [[package]] @@ -527,9 +526,9 @@ checksum = "ade8366b8bd5ba243f0a58f036cc0ca8a2f069cff1a2351ef1cac6b083e16fc0" [[package]] name = "cc" -version = "1.0.90" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" +checksum = "d32a725bc159af97c3e629873bb9f88fb8cf8a4867175f76dc987815ea07c83b" [[package]] name = "cfg-if" @@ -539,15 +538,15 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.37" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d04d43504c61aa6c7531f1871dd0d418d91130162063b789da00fd7057a5e" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", "num-traits", "serde", - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -584,9 +583,9 @@ dependencies = [ [[package]] name = "concurrent-queue" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" dependencies = [ "crossbeam-utils", ] @@ -710,9 +709,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.14.4" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" +checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" dependencies = [ "darling_core", "darling_macro", @@ -720,27 +719,27 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.14.4" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim", - "syn 1.0.109", + "syn", ] [[package]] name = "darling_macro" -version = "0.14.4" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" dependencies = [ "darling_core", "quote", - "syn 1.0.109", + "syn", ] [[package]] @@ -807,14 +806,14 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.58", + "syn", ] [[package]] name = "diesel" -version = "2.1.5" +version = "2.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03fc05c17098f21b89bc7d98fe1dd3cce2c11c2ad8e145f2a44fe08ed28eb559" +checksum = "ff236accb9a5069572099f0b350a92e9560e8e63a9b8d546162f4a5e03026bb2" dependencies = [ "bigdecimal", "bitflags 2.5.0", @@ -836,14 +835,14 @@ dependencies = [ [[package]] name = "diesel_derives" -version = "2.1.3" +version = "2.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d02eecb814ae714ffe61ddc2db2dd03e6c49a42e269b5001355500d431cce0c" +checksum = "14701062d6bed917b5c7103bdffaee1e4609279e240488ad24e7bd979ca6866c" dependencies = [ "diesel_table_macro_syntax", "proc-macro2", "quote", - "syn 2.0.58", + "syn", ] [[package]] @@ -873,7 +872,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc5557efc453706fed5e4fa85006fe9817c224c3f480a34c7e5959fd700921c5" dependencies = [ - "syn 2.0.58", + "syn", ] [[package]] @@ -895,9 +894,9 @@ checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" [[package]] name = "either" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" [[package]] name = "email-encoding" @@ -920,9 +919,9 @@ dependencies = [ [[package]] name = "encoding_rs" -version = "0.8.33" +version = "0.8.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" dependencies = [ "cfg-if", ] @@ -936,7 +935,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.58", + "syn", ] [[package]] @@ -1052,9 +1051,9 @@ dependencies = [ [[package]] name = "figment" -version = "0.10.15" +version = "0.10.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7270677e7067213e04f323b55084586195f18308cd7546cfac9f873344ccceb6" +checksum = "d032832d74006f99547004d49410a4b4218e4c33382d56ca3ff89df74f86b953" dependencies = [ "atomic 0.6.0", "pear", @@ -1066,9 +1065,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.28" +version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "4556222738635b7a3417ae6130d8f52201e45a0c4d1a907f0826383adb5f85e7" dependencies = [ "crc32fast", "miniz_oxide", @@ -1188,7 +1187,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn", ] [[package]] @@ -1237,7 +1236,7 @@ dependencies = [ "libc", "log", "rustversion", - "windows", + "windows 0.48.0", ] [[package]] @@ -1252,9 +1251,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06fddc2749e0528d2813f95e050e87e52c8cbbae56223b9babf73b3e53b0cc6" +checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" dependencies = [ "cfg-if", "js-sys", @@ -1390,9 +1389,9 @@ checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hickory-proto" -version = "0.24.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "091a6fbccf4860009355e3efc52ff4acf37a63489aad7435372d44ceeb6fbbcf" +checksum = "07698b8420e2f0d6447a436ba999ec85d8fbf2a398bbd737b82cac4a2e96e512" dependencies = [ "async-trait", "cfg-if", @@ -1414,9 +1413,9 @@ dependencies = [ [[package]] name = "hickory-resolver" -version = "0.24.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35b8f021164e6a984c9030023544c57789c51760065cd510572fedcfb04164e8" +checksum = "28757f23aa75c98f254cf0405e6d8c25b831b32921b050a66692427679b1f243" dependencies = [ "cfg-if", "futures-util", @@ -1462,6 +1461,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "hostname" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9c7c7c8ac16c798734b8a24560c1362120597c40d5e1459f09498f8f6c8f2ba" +dependencies = [ + "cfg-if", + "libc", + "windows 0.52.0", +] + [[package]] name = "html5gum" version = "0.5.7" @@ -1565,9 +1575,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.2.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a" +checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" dependencies = [ "bytes", "futures-channel", @@ -1604,7 +1614,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper 1.2.0", + "hyper 1.3.1", "hyper-util", "native-tls", "tokio", @@ -1623,7 +1633,7 @@ dependencies = [ "futures-util", "http 1.1.0", "http-body 1.0.0", - "hyper 1.2.0", + "hyper 1.3.1", "pin-project-lite", "socket2 0.5.6", "tokio", @@ -1771,9 +1781,9 @@ checksum = "47f142fe24a9c9944451e8349de0a56af5f3e7226dc46f3ed4d4ecc0b85af75e" [[package]] name = "job_scheduler_ng" -version = "2.0.4" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10bbdf445513bbe53f4666218b7057d265c76fa0b30475e121a6bf05dbaacaae" +checksum = "87c252207f323e2996d087759ebdcff8f608cd3eaa9896909a0c2dd3050a3c6a" dependencies = [ "chrono", "cron", @@ -1821,9 +1831,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "lettre" -version = "0.11.6" +version = "0.11.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47460276655930189e0919e4fbf46e46476b14f934f18a63dd726a5fb7b60e2e" +checksum = "1a62049a808f1c4e2356a2a380bd5f2aca3b011b0b482cf3b914ba1731426969" dependencies = [ "async-std", "async-trait", @@ -1834,7 +1844,7 @@ dependencies = [ "fastrand 2.0.2", "futures-io", "futures-util", - "hostname", + "hostname 0.4.0", "httpdate", "idna 0.5.0", "mime", @@ -1864,9 +1874,9 @@ checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] name = "libmimalloc-sys" -version = "0.1.35" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3979b5c37ece694f1f5e51e7ecc871fdb0f517ed04ee45f88d15d6d553cb9664" +checksum = "81eb4061c0582dedea1cbc7aff2240300dd6982e0239d1c99e65c1dbf4a30ba7" dependencies = [ "cc", "libc", @@ -1903,9 +1913,9 @@ checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -1988,9 +1998,9 @@ dependencies = [ [[package]] name = "mimalloc" -version = "0.1.39" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa01922b5ea280a911e323e4d2fd24b7fe5cc4042e0d2cda3c40775cdc4bdc9c" +checksum = "9f41a2280ded0da56c8cf898babb86e8f10651a34adcfff190ae9a1159c6908d" dependencies = [ "libmimalloc-sys", ] @@ -2132,7 +2142,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn", ] [[package]] @@ -2210,7 +2220,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn", ] [[package]] @@ -2255,9 +2265,9 @@ checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb" dependencies = [ "lock_api", "parking_lot_core", @@ -2265,15 +2275,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets 0.48.5", + "windows-targets 0.52.5", ] [[package]] @@ -2322,16 +2332,16 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.58", + "syn", ] [[package]] name = "pem" -version = "3.0.3" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8fcc794035347fb64beda2d3b462595dd2753e3f268d89c5aae77e8cf2c310" +checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" dependencies = [ - "base64 0.21.7", + "base64 0.22.0", "serde", ] @@ -2372,7 +2382,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.58", + "syn", ] [[package]] @@ -2447,7 +2457,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn", ] [[package]] @@ -2497,15 +2507,15 @@ dependencies = [ [[package]] name = "polling" -version = "3.6.0" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0c976a60b2d7e99d6f229e414670a9b85d13ac305cc6d1e9c134de58c5aaaf6" +checksum = "645493cf344456ef24219d02a768cf1fb92ddf8c92161679ae3d91b91a637be3" dependencies = [ "cfg-if", "concurrent-queue", "hermit-abi", "pin-project-lite", - "rustix 0.38.32", + "rustix 0.38.34", "tracing", "windows-sys 0.52.0", ] @@ -2539,9 +2549,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.79" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" dependencies = [ "unicode-ident", ] @@ -2554,7 +2564,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn", "version_check", "yansi", ] @@ -2607,9 +2617,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -2672,11 +2682,11 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.5.0", ] [[package]] @@ -2696,7 +2706,7 @@ checksum = "5fddb4f8d99b0a2ebafc65a87a69a7b9875e4b1ae1f00db265d300ef7f28bccc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn", ] [[package]] @@ -2796,9 +2806,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e6cc1e89e689536eb5aeede61520e874df5a4707df811cd5da4aa5fbb2aae19" +checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" dependencies = [ "async-compression", "base64 0.22.0", @@ -2813,7 +2823,7 @@ dependencies = [ "http 1.1.0", "http-body 1.0.0", "http-body-util", - "hyper 1.2.0", + "hyper 1.3.1", "hyper-tls 0.6.0", "hyper-util", "ipnet", @@ -2824,7 +2834,7 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls-pemfile 2.1.1", + "rustls-pemfile 2.1.2", "serde", "serde_json", "serde_urlencoded", @@ -2849,7 +2859,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" dependencies = [ - "hostname", + "hostname 0.3.1", "quick-error", ] @@ -2870,9 +2880,9 @@ dependencies = [ [[package]] name = "rmp" -version = "0.8.12" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9860a6cc38ed1da53456442089b4dfa35e7cedaa326df63017af88385e6b20" +checksum = "228ed7c16fa39782c3b3468e974aec2795e9089153cd08ee2e9aefb3613334c4" dependencies = [ "byteorder", "num-traits", @@ -2881,9 +2891,9 @@ dependencies = [ [[package]] name = "rmpv" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e0e0214a4a2b444ecce41a4025792fc31f77c7bb89c46d253953ea8c65701ec" +checksum = "e540282f11751956c82bc5529a7fb71b871b998fbf9cf06c2419b22e1b4350df" dependencies = [ "num-traits", "rmp", @@ -2939,7 +2949,7 @@ dependencies = [ "proc-macro2", "quote", "rocket_http", - "syn 2.0.58", + "syn", "unicode-xid", "version_check", ] @@ -3027,9 +3037,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.32" +version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ "bitflags 2.5.0", "errno", @@ -3040,9 +3050,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.10" +version = "0.21.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", "ring", @@ -3061,19 +3071,19 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f48172685e6ff52a556baa527774f61fcaa884f59daf3375c62a3f1cd2549dab" +checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" dependencies = [ - "base64 0.21.7", + "base64 0.22.0", "rustls-pki-types", ] [[package]] name = "rustls-pki-types" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecd36cc4259e3e4514335c4a138c6b43171a8d61d8f5c9348f9fc7529416f247" +checksum = "beb461507cee2c2ff151784c52762cf4d9ff6a61f3e80968600ed24fa837fa54" [[package]] name = "rustls-webpki" @@ -3087,9 +3097,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +checksum = "80af6f9131f277a45a3fba6ce8e2258037bb0477a67e610d3c1fe046ab31de47" [[package]] name = "ryu" @@ -3177,9 +3187,9 @@ checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" [[package]] name = "serde" -version = "1.0.197" +version = "1.0.198" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc" dependencies = [ "serde_derive", ] @@ -3196,20 +3206,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.198" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn", ] [[package]] name = "serde_json" -version = "1.0.115" +version = "1.0.116" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" +checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" dependencies = [ "itoa", "ryu", @@ -3280,9 +3290,9 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] @@ -3400,20 +3410,9 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "syn" -version = "1.0.109" +version = "2.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.58" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" +checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" dependencies = [ "proc-macro2", "quote", @@ -3428,12 +3427,12 @@ checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" [[package]] name = "syslog" -version = "6.1.0" +version = "6.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7434e95bcccce1215d30f4bf84fe8c00e8de1b9be4fb736d747ca53d36e7f96f" +checksum = "dfc7e95b5b795122fafe6519e27629b5ab4232c73ebb2428f568e82b1a457ad3" dependencies = [ "error-chain", - "hostname", + "hostname 0.3.1", "libc", "log", "time", @@ -3468,28 +3467,28 @@ checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", "fastrand 2.0.2", - "rustix 0.38.32", + "rustix 0.38.34", "windows-sys 0.52.0", ] [[package]] name = "thiserror" -version = "1.0.58" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" +checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.58" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" +checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn", ] [[package]] @@ -3513,9 +3512,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.34" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", @@ -3536,9 +3535,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ "num-conv", "time-core", @@ -3586,7 +3585,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn", ] [[package]] @@ -3679,7 +3678,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.9", + "toml_edit 0.22.12", ] [[package]] @@ -3706,15 +3705,15 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.9" +version = "0.22.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e40bb779c5187258fd7aad0eb68cb8706a0a81fa712fbea808ab43c4b8374c4" +checksum = "d3328d4f68a705b2a4498da1d580585d39a6510f98318a2cec3018a7ec61ddef" dependencies = [ "indexmap", "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.5", + "winnow 0.6.7", ] [[package]] @@ -3777,7 +3776,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn", ] [[package]] @@ -3987,7 +3986,7 @@ dependencies = [ "pico-args", "rand", "regex", - "reqwest 0.12.3", + "reqwest 0.12.4", "ring", "rmpv", "rocket", @@ -4072,7 +4071,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.58", + "syn", "wasm-bindgen-shared", ] @@ -4106,7 +4105,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4167,15 +4166,15 @@ checksum = "8211e4f58a2b2805adfbefbc07bab82958fc91e3836339b1ab7ae32465dce0d7" dependencies = [ "either", "home", - "rustix 0.38.32", + "rustix 0.38.34", "winsafe", ] [[package]] name = "widestring" -version = "1.0.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8" +checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" [[package]] name = "winapi" @@ -4195,11 +4194,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" dependencies = [ - "winapi", + "windows-sys 0.52.0", ] [[package]] @@ -4217,13 +4216,23 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "windows" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" +dependencies = [ + "windows-core", + "windows-targets 0.52.5", +] + [[package]] name = "windows-core" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -4241,7 +4250,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -4261,17 +4270,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" dependencies = [ - "windows_aarch64_gnullvm 0.52.4", - "windows_aarch64_msvc 0.52.4", - "windows_i686_gnu 0.52.4", - "windows_i686_msvc 0.52.4", - "windows_x86_64_gnu 0.52.4", - "windows_x86_64_gnullvm 0.52.4", - "windows_x86_64_msvc 0.52.4", + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", ] [[package]] @@ -4282,9 +4292,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" [[package]] name = "windows_aarch64_msvc" @@ -4294,9 +4304,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" [[package]] name = "windows_i686_gnu" @@ -4306,9 +4316,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" [[package]] name = "windows_i686_msvc" @@ -4318,9 +4334,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" [[package]] name = "windows_x86_64_gnu" @@ -4330,9 +4346,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" [[package]] name = "windows_x86_64_gnullvm" @@ -4342,9 +4358,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" [[package]] name = "windows_x86_64_msvc" @@ -4354,9 +4370,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "winnow" @@ -4369,9 +4385,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.6.5" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8" +checksum = "14b9415ee827af173ebb3f15f9083df5a122eb93572ec28741fb153356ea2578" dependencies = [ "memchr", ] @@ -4444,5 +4460,5 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn", ] diff --git a/Cargo.toml b/Cargo.toml index 16546a7f..4f2af4f5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,7 +36,7 @@ unstable = [] [target."cfg(not(windows))".dependencies] # Logging -syslog = "6.1.0" +syslog = "6.1.1" [dependencies] # Logging @@ -60,7 +60,7 @@ rocket = { version = "0.5.0", features = ["tls", "json"], default-features = fal rocket_ws = { version ="0.1.0" } # WebSockets libraries -rmpv = "1.0.1" # MessagePack library +rmpv = "1.0.2" # MessagePack library # Concurrent HashMap used for WebSocket messaging and favicons dashmap = "5.5.3" @@ -70,11 +70,11 @@ futures = "0.3.30" tokio = { version = "1.37.0", features = ["rt-multi-thread", "fs", "io-util", "parking_lot", "time", "signal"] } # A generic serialization/deserialization framework -serde = { version = "1.0.197", features = ["derive"] } -serde_json = "1.0.115" +serde = { version = "1.0.198", features = ["derive"] } +serde_json = "1.0.116" # A safe, extensible ORM and Query builder -diesel = { version = "2.1.5", features = ["chrono", "r2d2", "numeric"] } +diesel = { version = "2.1.6", features = ["chrono", "r2d2", "numeric"] } diesel_migrations = "2.1.0" diesel_logger = { version = "0.3.0", optional = true } @@ -89,12 +89,12 @@ ring = "0.17.8" uuid = { version = "1.8.0", features = ["v4"] } # Date and time libraries -chrono = { version = "0.4.37", features = ["clock", "serde"], default-features = false } +chrono = { version = "0.4.38", features = ["clock", "serde"], default-features = false } chrono-tz = "0.9.0" -time = "0.3.34" +time = "0.3.36" # Job scheduler -job_scheduler_ng = "2.0.4" +job_scheduler_ng = "2.0.5" # Data encoding library Hex/Base32/Base64 data-encoding = "2.5.0" @@ -115,7 +115,7 @@ webauthn-rs = "0.3.2" url = "2.5.0" # Email libraries -lettre = { version = "0.11.6", features = ["smtp-transport", "sendmail-transport", "builder", "serde", "tokio1-native-tls", "hostname", "tracing", "tokio1"], default-features = false } +lettre = { version = "0.11.7", features = ["smtp-transport", "sendmail-transport", "builder", "serde", "tokio1-native-tls", "hostname", "tracing", "tokio1"], default-features = false } percent-encoding = "2.3.1" # URL encoding library used for URL's in the emails email_address = "0.2.4" @@ -123,7 +123,7 @@ email_address = "0.2.4" handlebars = { version = "5.1.2", features = ["dir_source"] } # HTTP client (Used for favicons, version check, DUO and HIBP API) -reqwest = { version = "0.12.3", features = ["native-tls-alpn", "stream", "json", "gzip", "brotli", "socks", "cookies", "hickory-dns"] } +reqwest = { version = "0.12.4", features = ["native-tls-alpn", "stream", "json", "gzip", "brotli", "socks", "cookies", "hickory-dns"] } # Favicon extraction libraries html5gum = "0.5.7" @@ -132,7 +132,7 @@ data-url = "0.3.1" bytes = "1.6.0" # Cache function results (Used for version check and favicon fetching) -cached = { version = "0.49.2", features = ["async"] } +cached = { version = "0.50.0", features = ["async"] } # Used for custom short lived cookie jar during favicon extraction cookie = "0.18.1" @@ -153,7 +153,7 @@ semver = "1.0.22" # Allow overriding the default memory allocator # Mainly used for the musl builds, since the default musl malloc is very slow -mimalloc = { version = "0.1.39", features = ["secure"], default-features = false, optional = true } +mimalloc = { version = "0.1.41", features = ["secure"], default-features = false, optional = true } which = "6.0.1" # Argon2 library with support for the PHC format diff --git a/docker/DockerSettings.yaml b/docker/DockerSettings.yaml index 1034816d..f4eab726 100644 --- a/docker/DockerSettings.yaml +++ b/docker/DockerSettings.yaml @@ -1,10 +1,10 @@ --- vault_version: "v2024.3.1" vault_image_digest: "sha256:689b1e706f29e1858a5c7e0ec82e40fac793322e5e0ac9102ab09c2620207cd5" -# Cross Compile Docker Helper Scripts v1.3.0 +# Cross Compile Docker Helper Scripts v1.4.0 # We use the linux/amd64 platform shell scripts since there is no difference between the different platform scripts -xx_image_digest: "sha256:c9609ace652bbe51dd4ce90e0af9d48a4590f1214246da5bc70e46f6dd586edc" -rust_version: 1.77.0 # Rust version to be used +xx_image_digest: "sha256:0cd3f05c72d6c9b038eb135f91376ee1169ef3a330d34e418e65e2a5c2e9c0d4" +rust_version: 1.77.2 # Rust version to be used debian_version: bookworm # Debian release name to be used alpine_version: 3.19 # Alpine version to be used # For which platforms/architectures will we try to build images diff --git a/docker/Dockerfile.alpine b/docker/Dockerfile.alpine index b173a2fd..c8d2cc02 100644 --- a/docker/Dockerfile.alpine +++ b/docker/Dockerfile.alpine @@ -31,10 +31,10 @@ FROM --platform=linux/amd64 docker.io/vaultwarden/web-vault@sha256:689b1e706f29e ########################## ALPINE BUILD IMAGES ########################## ## NOTE: The Alpine Base Images do not support other platforms then linux/amd64 ## And for Alpine we define all build images here, they will only be loaded when actually used -FROM --platform=linux/amd64 ghcr.io/blackdex/rust-musl:x86_64-musl-stable-1.77.0 as build_amd64 -FROM --platform=linux/amd64 ghcr.io/blackdex/rust-musl:aarch64-musl-stable-1.77.0 as build_arm64 -FROM --platform=linux/amd64 ghcr.io/blackdex/rust-musl:armv7-musleabihf-stable-1.77.0 as build_armv7 -FROM --platform=linux/amd64 ghcr.io/blackdex/rust-musl:arm-musleabi-stable-1.77.0 as build_armv6 +FROM --platform=linux/amd64 ghcr.io/blackdex/rust-musl:x86_64-musl-stable-1.77.2 as build_amd64 +FROM --platform=linux/amd64 ghcr.io/blackdex/rust-musl:aarch64-musl-stable-1.77.2 as build_arm64 +FROM --platform=linux/amd64 ghcr.io/blackdex/rust-musl:armv7-musleabihf-stable-1.77.2 as build_armv7 +FROM --platform=linux/amd64 ghcr.io/blackdex/rust-musl:arm-musleabi-stable-1.77.2 as build_armv6 ########################## BUILD IMAGE ########################## # hadolint ignore=DL3006 diff --git a/docker/Dockerfile.debian b/docker/Dockerfile.debian index 42e475b5..9e55c07d 100644 --- a/docker/Dockerfile.debian +++ b/docker/Dockerfile.debian @@ -31,11 +31,11 @@ FROM --platform=linux/amd64 docker.io/vaultwarden/web-vault@sha256:689b1e706f29e ########################## Cross Compile Docker Helper Scripts ########################## ## We use the linux/amd64 no matter which Build Platform, since these are all bash scripts ## And these bash scripts do not have any significant difference if at all -FROM --platform=linux/amd64 docker.io/tonistiigi/xx@sha256:c9609ace652bbe51dd4ce90e0af9d48a4590f1214246da5bc70e46f6dd586edc AS xx +FROM --platform=linux/amd64 docker.io/tonistiigi/xx@sha256:0cd3f05c72d6c9b038eb135f91376ee1169ef3a330d34e418e65e2a5c2e9c0d4 AS xx ########################## BUILD IMAGE ########################## # hadolint ignore=DL3006 -FROM --platform=$BUILDPLATFORM docker.io/library/rust:1.77.0-slim-bookworm as build +FROM --platform=$BUILDPLATFORM docker.io/library/rust:1.77.2-slim-bookworm as build COPY --from=xx / / ARG TARGETARCH ARG TARGETVARIANT diff --git a/rust-toolchain.toml b/rust-toolchain.toml index d39770b2..2fa00154 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "1.77.0" +channel = "1.77.2" components = [ "rustfmt", "clippy" ] profile = "minimal" From 27dc67fadd3d45b9f7d8d37407cef9453b8f5802 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Sat, 27 Apr 2024 20:25:34 +0200 Subject: [PATCH 09/14] Implement custom DNS resolver (#3988) --- Cargo.lock | 10 +- Cargo.toml | 5 +- src/api/icons.rs | 320 +++++++++++++---------------------------------- src/api/mod.rs | 2 +- src/main.rs | 6 +- src/util.rs | 257 +++++++++++++++++++++++++++++++++++-- 6 files changed, 345 insertions(+), 255 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 23406ed3..09cb81f7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2819,7 +2819,6 @@ dependencies = [ "futures-core", "futures-util", "h2 0.4.4", - "hickory-resolver", "http 1.1.0", "http-body 1.0.0", "http-body-util", @@ -3187,9 +3186,9 @@ checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" [[package]] name = "serde" -version = "1.0.198" +version = "1.0.199" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc" +checksum = "0c9f6e76df036c77cd94996771fb40db98187f096dd0b9af39c6c6e452ba966a" dependencies = [ "serde_derive", ] @@ -3206,9 +3205,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.198" +version = "1.0.199" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9" +checksum = "11bd257a6541e141e42ca6d24ae26f7714887b47e89aa739099104c7e4d3b7fc" dependencies = [ "proc-macro2", "quote", @@ -3970,6 +3969,7 @@ dependencies = [ "futures", "governor", "handlebars", + "hickory-resolver", "html5gum", "job_scheduler_ng", "jsonwebtoken", diff --git a/Cargo.toml b/Cargo.toml index 4f2af4f5..82071435 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -67,7 +67,7 @@ dashmap = "5.5.3" # Async futures futures = "0.3.30" -tokio = { version = "1.37.0", features = ["rt-multi-thread", "fs", "io-util", "parking_lot", "time", "signal"] } +tokio = { version = "1.37.0", features = ["rt-multi-thread", "fs", "io-util", "parking_lot", "time", "signal", "net"] } # A generic serialization/deserialization framework serde = { version = "1.0.198", features = ["derive"] } @@ -123,7 +123,8 @@ email_address = "0.2.4" handlebars = { version = "5.1.2", features = ["dir_source"] } # HTTP client (Used for favicons, version check, DUO and HIBP API) -reqwest = { version = "0.12.4", features = ["native-tls-alpn", "stream", "json", "gzip", "brotli", "socks", "cookies", "hickory-dns"] } +reqwest = { version = "0.12.4", features = ["native-tls-alpn", "stream", "json", "gzip", "brotli", "socks", "cookies"] } +hickory-resolver = "0.24.1" # Favicon extraction libraries html5gum = "0.5.7" diff --git a/src/api/icons.rs b/src/api/icons.rs index 2f76b86a..94fab3f8 100644 --- a/src/api/icons.rs +++ b/src/api/icons.rs @@ -1,6 +1,6 @@ use std::{ net::IpAddr, - sync::Arc, + sync::{Arc, Mutex}, time::{Duration, SystemTime}, }; @@ -16,14 +16,13 @@ use rocket::{http::ContentType, response::Redirect, Route}; use tokio::{ fs::{create_dir_all, remove_file, symlink_metadata, File}, io::{AsyncReadExt, AsyncWriteExt}, - net::lookup_host, }; use html5gum::{Emitter, HtmlString, InfallibleTokenizer, Readable, StringReader, Tokenizer}; use crate::{ error::Error, - util::{get_reqwest_client_builder, Cached}, + util::{get_reqwest_client_builder, Cached, CustomDnsResolver, CustomResolverError}, CONFIG, }; @@ -49,48 +48,32 @@ static CLIENT: Lazy = Lazy::new(|| { let icon_download_timeout = Duration::from_secs(CONFIG.icon_download_timeout()); let pool_idle_timeout = Duration::from_secs(10); // Reuse the client between requests - let client = get_reqwest_client_builder() + get_reqwest_client_builder() .cookie_provider(Arc::clone(&cookie_store)) .timeout(icon_download_timeout) .pool_max_idle_per_host(5) // Configure the Hyper Pool to only have max 5 idle connections .pool_idle_timeout(pool_idle_timeout) // Configure the Hyper Pool to timeout after 10 seconds - .hickory_dns(true) - .default_headers(default_headers.clone()); - - match client.build() { - Ok(client) => client, - Err(e) => { - error!("Possible trust-dns error, trying with trust-dns disabled: '{e}'"); - get_reqwest_client_builder() - .cookie_provider(cookie_store) - .timeout(icon_download_timeout) - .pool_max_idle_per_host(5) // Configure the Hyper Pool to only have max 5 idle connections - .pool_idle_timeout(pool_idle_timeout) // Configure the Hyper Pool to timeout after 10 seconds - .hickory_dns(false) - .default_headers(default_headers) - .build() - .expect("Failed to build client") - } - } + .dns_resolver(CustomDnsResolver::instance()) + .default_headers(default_headers.clone()) + .build() + .expect("Failed to build client") }); // Build Regex only once since this takes a lot of time. static ICON_SIZE_REGEX: Lazy = Lazy::new(|| Regex::new(r"(?x)(\d+)\D*(\d+)").unwrap()); -// Special HashMap which holds the user defined Regex to speedup matching the regex. -static ICON_BLACKLIST_REGEX: Lazy> = Lazy::new(dashmap::DashMap::new); - -async fn icon_redirect(domain: &str, template: &str) -> Option { +#[get("//icon.png")] +fn icon_external(domain: &str) -> Option { if !is_valid_domain(domain) { warn!("Invalid domain: {}", domain); return None; } - if check_domain_blacklist_reason(domain).await.is_some() { + if is_domain_blacklisted(domain) { return None; } - let url = template.replace("{}", domain); + let url = CONFIG._icon_service_url().replace("{}", domain); match CONFIG.icon_redirect_code() { 301 => Some(Redirect::moved(url)), // legacy permanent redirect 302 => Some(Redirect::found(url)), // legacy temporary redirect @@ -103,11 +86,6 @@ async fn icon_redirect(domain: &str, template: &str) -> Option { } } -#[get("//icon.png")] -async fn icon_external(domain: &str) -> Option { - icon_redirect(domain, &CONFIG._icon_service_url()).await -} - #[get("//icon.png")] async fn icon_internal(domain: &str) -> Cached<(ContentType, Vec)> { const FALLBACK_ICON: &[u8] = include_bytes!("../static/images/fallback-icon.png"); @@ -166,153 +144,28 @@ fn is_valid_domain(domain: &str) -> bool { true } -/// TODO: This is extracted from IpAddr::is_global, which is unstable: -/// https://doc.rust-lang.org/nightly/std/net/enum.IpAddr.html#method.is_global -/// Remove once https://github.com/rust-lang/rust/issues/27709 is merged -#[allow(clippy::nonminimal_bool)] -#[cfg(not(feature = "unstable"))] -fn is_global(ip: IpAddr) -> bool { - match ip { - IpAddr::V4(ip) => { - // check if this address is 192.0.0.9 or 192.0.0.10. These addresses are the only two - // globally routable addresses in the 192.0.0.0/24 range. - if u32::from(ip) == 0xc0000009 || u32::from(ip) == 0xc000000a { - return true; - } - !ip.is_private() - && !ip.is_loopback() - && !ip.is_link_local() - && !ip.is_broadcast() - && !ip.is_documentation() - && !(ip.octets()[0] == 100 && (ip.octets()[1] & 0b1100_0000 == 0b0100_0000)) - && !(ip.octets()[0] == 192 && ip.octets()[1] == 0 && ip.octets()[2] == 0) - && !(ip.octets()[0] & 240 == 240 && !ip.is_broadcast()) - && !(ip.octets()[0] == 198 && (ip.octets()[1] & 0xfe) == 18) - // Make sure the address is not in 0.0.0.0/8 - && ip.octets()[0] != 0 - } - IpAddr::V6(ip) => { - if ip.is_multicast() && ip.segments()[0] & 0x000f == 14 { - true - } else { - !ip.is_multicast() - && !ip.is_loopback() - && !((ip.segments()[0] & 0xffc0) == 0xfe80) - && !((ip.segments()[0] & 0xfe00) == 0xfc00) - && !ip.is_unspecified() - && !((ip.segments()[0] == 0x2001) && (ip.segments()[1] == 0xdb8)) - } - } - } -} +pub fn is_domain_blacklisted(domain: &str) -> bool { + let Some(config_blacklist) = CONFIG.icon_blacklist_regex() else { + return false; + }; -#[cfg(feature = "unstable")] -fn is_global(ip: IpAddr) -> bool { - ip.is_global() -} + // Compiled domain blacklist + static COMPILED_BLACKLIST: Mutex> = Mutex::new(None); + let mut guard = COMPILED_BLACKLIST.lock().unwrap(); -/// These are some tests to check that the implementations match -/// The IPv4 can be all checked in 5 mins or so and they are correct as of nightly 2020-07-11 -/// The IPV6 can't be checked in a reasonable time, so we check about ten billion random ones, so far correct -/// Note that the is_global implementation is subject to change as new IP RFCs are created -/// -/// To run while showing progress output: -/// cargo test --features sqlite,unstable -- --nocapture --ignored -#[cfg(test)] -#[cfg(feature = "unstable")] -mod tests { - use super::*; - - #[test] - #[ignore] - fn test_ipv4_global() { - for a in 0..u8::MAX { - println!("Iter: {}/255", a); - for b in 0..u8::MAX { - for c in 0..u8::MAX { - for d in 0..u8::MAX { - let ip = IpAddr::V4(std::net::Ipv4Addr::new(a, b, c, d)); - assert_eq!(ip.is_global(), is_global(ip)) - } - } - } + // If the stored regex is up to date, use it + if let Some((value, regex)) = &*guard { + if value == &config_blacklist { + return regex.is_match(domain); } } - #[test] - #[ignore] - fn test_ipv6_global() { - use ring::rand::{SecureRandom, SystemRandom}; - let mut v = [0u8; 16]; - let rand = SystemRandom::new(); - for i in 0..1_000 { - println!("Iter: {}/1_000", i); - for _ in 0..10_000_000 { - rand.fill(&mut v).expect("Error generating random values"); - let ip = IpAddr::V6(std::net::Ipv6Addr::new( - (v[14] as u16) << 8 | v[15] as u16, - (v[12] as u16) << 8 | v[13] as u16, - (v[10] as u16) << 8 | v[11] as u16, - (v[8] as u16) << 8 | v[9] as u16, - (v[6] as u16) << 8 | v[7] as u16, - (v[4] as u16) << 8 | v[5] as u16, - (v[2] as u16) << 8 | v[3] as u16, - (v[0] as u16) << 8 | v[1] as u16, - )); - assert_eq!(ip.is_global(), is_global(ip)) - } - } - } -} + // If we don't have a regex stored, or it's not up to date, recreate it + let regex = Regex::new(&config_blacklist).unwrap(); + let is_match = regex.is_match(domain); + *guard = Some((config_blacklist, regex)); -#[derive(Clone)] -enum DomainBlacklistReason { - Regex, - IP, -} - -use cached::proc_macro::cached; -#[cached(key = "String", convert = r#"{ domain.to_string() }"#, size = 16, time = 60)] -async fn check_domain_blacklist_reason(domain: &str) -> Option { - // First check the blacklist regex if there is a match. - // This prevents the blocked domain(s) from being leaked via a DNS lookup. - if let Some(blacklist) = CONFIG.icon_blacklist_regex() { - // Use the pre-generate Regex stored in a Lazy HashMap if there's one, else generate it. - let is_match = if let Some(regex) = ICON_BLACKLIST_REGEX.get(&blacklist) { - regex.is_match(domain) - } else { - // Clear the current list if the previous key doesn't exists. - // To prevent growing of the HashMap after someone has changed it via the admin interface. - if ICON_BLACKLIST_REGEX.len() >= 1 { - ICON_BLACKLIST_REGEX.clear(); - } - - // Generate the regex to store in too the Lazy Static HashMap. - let blacklist_regex = Regex::new(&blacklist).unwrap(); - let is_match = blacklist_regex.is_match(domain); - ICON_BLACKLIST_REGEX.insert(blacklist.clone(), blacklist_regex); - - is_match - }; - - if is_match { - debug!("Blacklisted domain: {} matched ICON_BLACKLIST_REGEX", domain); - return Some(DomainBlacklistReason::Regex); - } - } - - if CONFIG.icon_blacklist_non_global_ips() { - if let Ok(s) = lookup_host((domain, 0)).await { - for addr in s { - if !is_global(addr.ip()) { - debug!("IP {} for domain '{}' is not a global IP!", addr.ip(), domain); - return Some(DomainBlacklistReason::IP); - } - } - } - } - - None + is_match } async fn get_icon(domain: &str) -> Option<(Vec, String)> { @@ -342,6 +195,13 @@ async fn get_icon(domain: &str) -> Option<(Vec, String)> { Some((icon.to_vec(), icon_type.unwrap_or("x-icon").to_string())) } Err(e) => { + // If this error comes from the custom resolver, this means this is a blacklisted domain + // or non global IP, don't save the miss file in this case to avoid leaking it + if let Some(error) = CustomResolverError::downcast_ref(&e) { + warn!("{error}"); + return None; + } + warn!("Unable to download icon: {:?}", e); let miss_indicator = path + ".miss"; save_icon(&miss_indicator, &[]).await; @@ -491,42 +351,48 @@ async fn get_icon_url(domain: &str) -> Result { let ssldomain = format!("https://{domain}"); let httpdomain = format!("http://{domain}"); - // First check the domain as given during the request for both HTTPS and HTTP. - let resp = match get_page(&ssldomain).or_else(|_| get_page(&httpdomain)).await { - Ok(c) => Ok(c), - Err(e) => { - let mut sub_resp = Err(e); + // First check the domain as given during the request for HTTPS. + let resp = match get_page(&ssldomain).await { + Err(e) if CustomResolverError::downcast_ref(&e).is_none() => { + // If we get an error that is not caused by the blacklist, we retry with HTTP + match get_page(&httpdomain).await { + mut sub_resp @ Err(_) => { + // When the domain is not an IP, and has more then one dot, remove all subdomains. + let is_ip = domain.parse::(); + if is_ip.is_err() && domain.matches('.').count() > 1 { + let mut domain_parts = domain.split('.'); + let base_domain = format!( + "{base}.{tld}", + tld = domain_parts.next_back().unwrap(), + base = domain_parts.next_back().unwrap() + ); + if is_valid_domain(&base_domain) { + let sslbase = format!("https://{base_domain}"); + let httpbase = format!("http://{base_domain}"); + debug!("[get_icon_url]: Trying without subdomains '{base_domain}'"); - // When the domain is not an IP, and has more then one dot, remove all subdomains. - let is_ip = domain.parse::(); - if is_ip.is_err() && domain.matches('.').count() > 1 { - let mut domain_parts = domain.split('.'); - let base_domain = format!( - "{base}.{tld}", - tld = domain_parts.next_back().unwrap(), - base = domain_parts.next_back().unwrap() - ); - if is_valid_domain(&base_domain) { - let sslbase = format!("https://{base_domain}"); - let httpbase = format!("http://{base_domain}"); - debug!("[get_icon_url]: Trying without subdomains '{base_domain}'"); + sub_resp = get_page(&sslbase).or_else(|_| get_page(&httpbase)).await; + } - sub_resp = get_page(&sslbase).or_else(|_| get_page(&httpbase)).await; - } - - // When the domain is not an IP, and has less then 2 dots, try to add www. infront of it. - } else if is_ip.is_err() && domain.matches('.').count() < 2 { - let www_domain = format!("www.{domain}"); - if is_valid_domain(&www_domain) { - let sslwww = format!("https://{www_domain}"); - let httpwww = format!("http://{www_domain}"); - debug!("[get_icon_url]: Trying with www. prefix '{www_domain}'"); - - sub_resp = get_page(&sslwww).or_else(|_| get_page(&httpwww)).await; + // When the domain is not an IP, and has less then 2 dots, try to add www. infront of it. + } else if is_ip.is_err() && domain.matches('.').count() < 2 { + let www_domain = format!("www.{domain}"); + if is_valid_domain(&www_domain) { + let sslwww = format!("https://{www_domain}"); + let httpwww = format!("http://{www_domain}"); + debug!("[get_icon_url]: Trying with www. prefix '{www_domain}'"); + + sub_resp = get_page(&sslwww).or_else(|_| get_page(&httpwww)).await; + } + } + sub_resp } + res => res, } - sub_resp } + + // If we get a result or a blacklist error, just continue + res => res, }; // Create the iconlist @@ -573,21 +439,12 @@ async fn get_page(url: &str) -> Result { } async fn get_page_with_referer(url: &str, referer: &str) -> Result { - match check_domain_blacklist_reason(url::Url::parse(url).unwrap().host_str().unwrap_or_default()).await { - Some(DomainBlacklistReason::Regex) => warn!("Favicon '{}' is from a blacklisted domain!", url), - Some(DomainBlacklistReason::IP) => warn!("Favicon '{}' is hosted on a non-global IP!", url), - None => (), - } - let mut client = CLIENT.get(url); if !referer.is_empty() { client = client.header("Referer", referer) } - match client.send().await { - Ok(c) => c.error_for_status().map_err(Into::into), - Err(e) => err_silent!(format!("{e}")), - } + Ok(client.send().await?.error_for_status()?) } /// Returns a Integer with the priority of the type of the icon which to prefer. @@ -670,12 +527,6 @@ fn parse_sizes(sizes: &str) -> (u16, u16) { } async fn download_icon(domain: &str) -> Result<(Bytes, Option<&str>), Error> { - match check_domain_blacklist_reason(domain).await { - Some(DomainBlacklistReason::Regex) => err_silent!("Domain is blacklisted", domain), - Some(DomainBlacklistReason::IP) => err_silent!("Host resolves to a non-global IP", domain), - None => (), - } - let icon_result = get_icon_url(domain).await?; let mut buffer = Bytes::new(); @@ -711,22 +562,19 @@ async fn download_icon(domain: &str) -> Result<(Bytes, Option<&str>), Error> { _ => debug!("Extracted icon from data:image uri is invalid"), }; } else { - match get_page_with_referer(&icon.href, &icon_result.referer).await { - Ok(res) => { - buffer = stream_to_bytes_limit(res, 5120 * 1024).await?; // 5120KB/5MB for each icon max (Same as icons.bitwarden.net) + let res = get_page_with_referer(&icon.href, &icon_result.referer).await?; - // Check if the icon type is allowed, else try an icon from the list. - icon_type = get_icon_type(&buffer); - if icon_type.is_none() { - buffer.clear(); - debug!("Icon from {}, is not a valid image type", icon.href); - continue; - } - info!("Downloaded icon from {}", icon.href); - break; - } - Err(e) => debug!("{:?}", e), - }; + buffer = stream_to_bytes_limit(res, 5120 * 1024).await?; // 5120KB/5MB for each icon max (Same as icons.bitwarden.net) + + // Check if the icon type is allowed, else try an icon from the list. + icon_type = get_icon_type(&buffer); + if icon_type.is_none() { + buffer.clear(); + debug!("Icon from {}, is not a valid image type", icon.href); + continue; + } + info!("Downloaded icon from {}", icon.href); + break; } } diff --git a/src/api/mod.rs b/src/api/mod.rs index c6838aaa..de81630d 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -20,7 +20,7 @@ pub use crate::api::{ core::two_factor::send_incomplete_2fa_notifications, core::{emergency_notification_reminder_job, emergency_request_timeout_job}, core::{event_cleanup_job, events_routes as core_events_routes}, - icons::routes as icons_routes, + icons::{is_domain_blacklisted, routes as icons_routes}, identity::routes as identity_routes, notifications::routes as notifications_routes, notifications::{AnonymousNotify, Notify, UpdateType, WS_ANONYMOUS_SUBSCRIPTIONS, WS_USERS}, diff --git a/src/main.rs b/src/main.rs index 12953979..c20ecfe1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -211,8 +211,8 @@ fn launch_info() { } fn init_logging(level: log::LevelFilter) -> Result<(), fern::InitError> { - // Depending on the main log level we either want to disable or enable logging for trust-dns. - // Else if there are timeouts it will clutter the logs since trust-dns uses warn for this. + // Depending on the main log level we either want to disable or enable logging for hickory. + // Else if there are timeouts it will clutter the logs since hickory uses warn for this. let hickory_level = if level >= log::LevelFilter::Debug { level } else { @@ -266,7 +266,7 @@ fn init_logging(level: log::LevelFilter) -> Result<(), fern::InitError> { .level_for("handlebars::render", handlebars_level) // Prevent cookie_store logs .level_for("cookie_store", log::LevelFilter::Off) - // Variable level for trust-dns used by reqwest + // Variable level for hickory used by reqwest .level_for("hickory_resolver::name_server::name_server", hickory_level) .level_for("hickory_proto::xfer", hickory_level) .level_for("diesel_logger", diesel_logger_level) diff --git a/src/util.rs b/src/util.rs index 8aae4bd1..e96a1741 100644 --- a/src/util.rs +++ b/src/util.rs @@ -4,6 +4,7 @@ use std::{collections::HashMap, io::Cursor, ops::Deref, path::Path}; use num_traits::ToPrimitive; +use once_cell::sync::Lazy; use rocket::{ fairing::{Fairing, Info, Kind}, http::{ContentType, Header, HeaderMap, Method, Status}, @@ -701,14 +702,9 @@ where use reqwest::{header, Client, ClientBuilder}; -pub fn get_reqwest_client() -> Client { - match get_reqwest_client_builder().build() { - Ok(client) => client, - Err(e) => { - error!("Possible trust-dns error, trying with trust-dns disabled: '{e}'"); - get_reqwest_client_builder().hickory_dns(false).build().expect("Failed to build client") - } - } +pub fn get_reqwest_client() -> &'static Client { + static INSTANCE: Lazy = Lazy::new(|| get_reqwest_client_builder().build().expect("Failed to build client")); + &INSTANCE } pub fn get_reqwest_client_builder() -> ClientBuilder { @@ -767,3 +763,248 @@ pub fn parse_experimental_client_feature_flags(experimental_client_feature_flags feature_states } + +mod dns_resolver { + use std::{ + fmt, + net::{IpAddr, SocketAddr}, + sync::Arc, + }; + + use hickory_resolver::{system_conf::read_system_conf, TokioAsyncResolver}; + use once_cell::sync::Lazy; + use reqwest::dns::{Name, Resolve, Resolving}; + + use crate::{util::is_global, CONFIG}; + + #[derive(Debug, Clone)] + pub enum CustomResolverError { + Blacklist { + domain: String, + }, + NonGlobalIp { + domain: String, + ip: IpAddr, + }, + } + + impl CustomResolverError { + pub fn downcast_ref(e: &dyn std::error::Error) -> Option<&Self> { + let mut source = e.source(); + + while let Some(err) = source { + source = err.source(); + if let Some(err) = err.downcast_ref::() { + return Some(err); + } + } + None + } + } + + impl fmt::Display for CustomResolverError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Blacklist { + domain, + } => write!(f, "Blacklisted domain: {domain} matched ICON_BLACKLIST_REGEX"), + Self::NonGlobalIp { + domain, + ip, + } => write!(f, "IP {ip} for domain '{domain}' is not a global IP!"), + } + } + } + + impl std::error::Error for CustomResolverError {} + + #[derive(Debug, Clone)] + pub enum CustomDnsResolver { + Default(), + Hickory(Arc), + } + type BoxError = Box; + + impl CustomDnsResolver { + pub fn instance() -> Arc { + static INSTANCE: Lazy> = Lazy::new(CustomDnsResolver::new); + Arc::clone(&*INSTANCE) + } + + fn new() -> Arc { + match read_system_conf() { + Ok((config, opts)) => { + let resolver = TokioAsyncResolver::tokio(config.clone(), opts.clone()); + Arc::new(Self::Hickory(Arc::new(resolver))) + } + Err(e) => { + warn!("Error creating Hickory resolver, falling back to default: {e:?}"); + Arc::new(Self::Default()) + } + } + } + + // Note that we get an iterator of addresses, but we only grab the first one for convenience + async fn resolve_domain(&self, name: &str) -> Result, BoxError> { + pre_resolve(name)?; + + let result = match self { + Self::Default() => tokio::net::lookup_host(name).await?.next(), + Self::Hickory(r) => r.lookup_ip(name).await?.iter().next().map(|a| SocketAddr::new(a, 0)), + }; + + if let Some(addr) = &result { + post_resolve(name, addr.ip())?; + } + + Ok(result) + } + } + + fn pre_resolve(name: &str) -> Result<(), CustomResolverError> { + if crate::api::is_domain_blacklisted(name) { + return Err(CustomResolverError::Blacklist { + domain: name.to_string(), + }); + } + + Ok(()) + } + + fn post_resolve(name: &str, ip: IpAddr) -> Result<(), CustomResolverError> { + if CONFIG.icon_blacklist_non_global_ips() && !is_global(ip) { + Err(CustomResolverError::NonGlobalIp { + domain: name.to_string(), + ip, + }) + } else { + Ok(()) + } + } + + impl Resolve for CustomDnsResolver { + fn resolve(&self, name: Name) -> Resolving { + let this = self.clone(); + Box::pin(async move { + let name = name.as_str(); + let result = this.resolve_domain(name).await?; + Ok::(Box::new(result.into_iter())) + }) + } + } +} + +pub use dns_resolver::{CustomDnsResolver, CustomResolverError}; + +/// TODO: This is extracted from IpAddr::is_global, which is unstable: +/// https://doc.rust-lang.org/nightly/std/net/enum.IpAddr.html#method.is_global +/// Remove once https://github.com/rust-lang/rust/issues/27709 is merged +#[allow(clippy::nonminimal_bool)] +#[cfg(any(not(feature = "unstable"), test))] +pub fn is_global_hardcoded(ip: std::net::IpAddr) -> bool { + match ip { + std::net::IpAddr::V4(ip) => { + !(ip.octets()[0] == 0 // "This network" + || ip.is_private() + || (ip.octets()[0] == 100 && (ip.octets()[1] & 0b1100_0000 == 0b0100_0000)) //ip.is_shared() + || ip.is_loopback() + || ip.is_link_local() + // addresses reserved for future protocols (`192.0.0.0/24`) + ||(ip.octets()[0] == 192 && ip.octets()[1] == 0 && ip.octets()[2] == 0) + || ip.is_documentation() + || (ip.octets()[0] == 198 && (ip.octets()[1] & 0xfe) == 18) // ip.is_benchmarking() + || (ip.octets()[0] & 240 == 240 && !ip.is_broadcast()) //ip.is_reserved() + || ip.is_broadcast()) + } + std::net::IpAddr::V6(ip) => { + !(ip.is_unspecified() + || ip.is_loopback() + // IPv4-mapped Address (`::ffff:0:0/96`) + || matches!(ip.segments(), [0, 0, 0, 0, 0, 0xffff, _, _]) + // IPv4-IPv6 Translat. (`64:ff9b:1::/48`) + || matches!(ip.segments(), [0x64, 0xff9b, 1, _, _, _, _, _]) + // Discard-Only Address Block (`100::/64`) + || matches!(ip.segments(), [0x100, 0, 0, 0, _, _, _, _]) + // IETF Protocol Assignments (`2001::/23`) + || (matches!(ip.segments(), [0x2001, b, _, _, _, _, _, _] if b < 0x200) + && !( + // Port Control Protocol Anycast (`2001:1::1`) + u128::from_be_bytes(ip.octets()) == 0x2001_0001_0000_0000_0000_0000_0000_0001 + // Traversal Using Relays around NAT Anycast (`2001:1::2`) + || u128::from_be_bytes(ip.octets()) == 0x2001_0001_0000_0000_0000_0000_0000_0002 + // AMT (`2001:3::/32`) + || matches!(ip.segments(), [0x2001, 3, _, _, _, _, _, _]) + // AS112-v6 (`2001:4:112::/48`) + || matches!(ip.segments(), [0x2001, 4, 0x112, _, _, _, _, _]) + // ORCHIDv2 (`2001:20::/28`) + || matches!(ip.segments(), [0x2001, b, _, _, _, _, _, _] if (0x20..=0x2F).contains(&b)) + )) + || ((ip.segments()[0] == 0x2001) && (ip.segments()[1] == 0xdb8)) // ip.is_documentation() + || ((ip.segments()[0] & 0xfe00) == 0xfc00) //ip.is_unique_local() + || ((ip.segments()[0] & 0xffc0) == 0xfe80)) //ip.is_unicast_link_local() + } + } +} + +#[cfg(not(feature = "unstable"))] +pub use is_global_hardcoded as is_global; + +#[cfg(feature = "unstable")] +#[inline(always)] +pub fn is_global(ip: std::net::IpAddr) -> bool { + ip.is_global() +} + +/// These are some tests to check that the implementations match +/// The IPv4 can be all checked in 30 seconds or so and they are correct as of nightly 2023-07-17 +/// The IPV6 can't be checked in a reasonable time, so we check over a hundred billion random ones, so far correct +/// Note that the is_global implementation is subject to change as new IP RFCs are created +/// +/// To run while showing progress output: +/// cargo +nightly test --release --features sqlite,unstable -- --nocapture --ignored +#[cfg(test)] +#[cfg(feature = "unstable")] +mod tests { + use super::*; + use std::net::IpAddr; + + #[test] + #[ignore] + fn test_ipv4_global() { + for a in 0..u8::MAX { + println!("Iter: {}/255", a); + for b in 0..u8::MAX { + for c in 0..u8::MAX { + for d in 0..u8::MAX { + let ip = IpAddr::V4(std::net::Ipv4Addr::new(a, b, c, d)); + assert_eq!(ip.is_global(), is_global_hardcoded(ip), "IP mismatch: {}", ip) + } + } + } + } + } + + #[test] + #[ignore] + fn test_ipv6_global() { + use rand::Rng; + + std::thread::scope(|s| { + for t in 0..16 { + let handle = s.spawn(move || { + let mut v = [0u8; 16]; + let mut rng = rand::thread_rng(); + + for i in 0..20 { + println!("Thread {t} Iter: {i}/50"); + for _ in 0..500_000_000 { + rng.fill(&mut v); + let ip = IpAddr::V6(std::net::Ipv6Addr::from(v)); + assert_eq!(ip.is_global(), is_global_hardcoded(ip), "IP mismatch: {ip}"); + } + } + }); + } + }); + } +} From ca9234ed869a3c2bbe2d340d18224179f4ad1d6b Mon Sep 17 00:00:00 2001 From: Mathijs van Veluw Date: Sat, 27 Apr 2024 21:51:14 +0200 Subject: [PATCH 10/14] Add extra (unsupported) container build arch's (#4524) There was a PR (#4370) to add i686/i386 support for Vaultwarden. That specific PR was not a viable way of adding this. This PR adds extra architectures for Debian based containers which we will not support by default. Those images will not be build and pushed to our container registries. Added the following architectures: - linux/386 - linux/ppc64le - linux/s390x Again, there will be no major support for these architectures, but it will allow people who use these architectures to build a Debian based binary more easily --- docker/Dockerfile.alpine | 3 ++- docker/Dockerfile.debian | 10 +++++++++- docker/Dockerfile.j2 | 13 +++++++++++-- docker/README.md | 5 +++++ docker/docker-bake.hcl | 34 ++++++++++++++++++++++++++++++++++ 5 files changed, 61 insertions(+), 4 deletions(-) diff --git a/docker/Dockerfile.alpine b/docker/Dockerfile.alpine index c8d2cc02..baa41817 100644 --- a/docker/Dockerfile.alpine +++ b/docker/Dockerfile.alpine @@ -65,13 +65,14 @@ RUN mkdir -pv "${CARGO_HOME}" \ RUN USER=root cargo new --bin /app WORKDIR /app -# Shared variables across Debian and Alpine +# Environment variables for Cargo on Alpine based builds RUN echo "export CARGO_TARGET=${RUST_MUSL_CROSS_TARGET}" >> /env-cargo && \ # To be able to build the armv6 image with mimalloc we need to tell the linker to also look for libatomic if [[ "${TARGETARCH}${TARGETVARIANT}" == "armv6" ]] ; then echo "export RUSTFLAGS='-Clink-arg=-latomic'" >> /env-cargo ; fi && \ # Output the current contents of the file cat /env-cargo +# Configure the DB ARG as late as possible to not invalidate the cached layers above # Enable MiMalloc to improve performance on Alpine builds ARG DB=sqlite,mysql,postgresql,enable_mimalloc diff --git a/docker/Dockerfile.debian b/docker/Dockerfile.debian index 9e55c07d..1505e5fc 100644 --- a/docker/Dockerfile.debian +++ b/docker/Dockerfile.debian @@ -88,9 +88,17 @@ RUN mkdir -pv "${CARGO_HOME}" \ RUN USER=root cargo new --bin /app WORKDIR /app -# Environment variables for cargo across Debian and Alpine +# Environment variables for Cargo on Debian based builds +ARG ARCH_OPENSSL_LIB_DIR \ + ARCH_OPENSSL_INCLUDE_DIR + RUN source /env-cargo && \ if xx-info is-cross ; then \ + # Some special variables if needed to override some build paths + if [[ -n "${ARCH_OPENSSL_LIB_DIR}" && -n "${ARCH_OPENSSL_INCLUDE_DIR}" ]]; then \ + echo "export $(echo "${CARGO_TARGET}" | tr '[:lower:]' '[:upper:]' | tr - _)_OPENSSL_LIB_DIR=${ARCH_OPENSSL_LIB_DIR}" >> /env-cargo && \ + echo "export $(echo "${CARGO_TARGET}" | tr '[:lower:]' '[:upper:]' | tr - _)_OPENSSL_INCLUDE_DIR=${ARCH_OPENSSL_INCLUDE_DIR}" >> /env-cargo ; \ + fi && \ # We can't use xx-cargo since that uses clang, which doesn't work for our libraries. # Because of this we generate the needed environment variables here which we can load in the needed steps. echo "export CC_$(echo "${CARGO_TARGET}" | tr '[:upper:]' '[:lower:]' | tr - _)=/usr/bin/$(xx-info)-gcc" >> /env-cargo && \ diff --git a/docker/Dockerfile.j2 b/docker/Dockerfile.j2 index e8f81469..73a9c2a5 100644 --- a/docker/Dockerfile.j2 +++ b/docker/Dockerfile.j2 @@ -108,9 +108,17 @@ RUN USER=root cargo new --bin /app WORKDIR /app {% if base == "debian" %} -# Environment variables for cargo across Debian and Alpine +# Environment variables for Cargo on Debian based builds +ARG ARCH_OPENSSL_LIB_DIR \ + ARCH_OPENSSL_INCLUDE_DIR + RUN source /env-cargo && \ if xx-info is-cross ; then \ + # Some special variables if needed to override some build paths + if [[ -n "${ARCH_OPENSSL_LIB_DIR}" && -n "${ARCH_OPENSSL_INCLUDE_DIR}" ]]; then \ + echo "export $(echo "${CARGO_TARGET}" | tr '[:lower:]' '[:upper:]' | tr - _)_OPENSSL_LIB_DIR=${ARCH_OPENSSL_LIB_DIR}" >> /env-cargo && \ + echo "export $(echo "${CARGO_TARGET}" | tr '[:lower:]' '[:upper:]' | tr - _)_OPENSSL_INCLUDE_DIR=${ARCH_OPENSSL_INCLUDE_DIR}" >> /env-cargo ; \ + fi && \ # We can't use xx-cargo since that uses clang, which doesn't work for our libraries. # Because of this we generate the needed environment variables here which we can load in the needed steps. echo "export CC_$(echo "${CARGO_TARGET}" | tr '[:upper:]' '[:lower:]' | tr - _)=/usr/bin/$(xx-info)-gcc" >> /env-cargo && \ @@ -126,13 +134,14 @@ RUN source /env-cargo && \ # Configure the DB ARG as late as possible to not invalidate the cached layers above ARG DB=sqlite,mysql,postgresql {% elif base == "alpine" %} -# Shared variables across Debian and Alpine +# Environment variables for Cargo on Alpine based builds RUN echo "export CARGO_TARGET=${RUST_MUSL_CROSS_TARGET}" >> /env-cargo && \ # To be able to build the armv6 image with mimalloc we need to tell the linker to also look for libatomic if [[ "${TARGETARCH}${TARGETVARIANT}" == "armv6" ]] ; then echo "export RUSTFLAGS='-Clink-arg=-latomic'" >> /env-cargo ; fi && \ # Output the current contents of the file cat /env-cargo +# Configure the DB ARG as late as possible to not invalidate the cached layers above # Enable MiMalloc to improve performance on Alpine builds ARG DB=sqlite,mysql,postgresql,enable_mimalloc {% endif %} diff --git a/docker/README.md b/docker/README.md index 3c74043c..2e78f534 100644 --- a/docker/README.md +++ b/docker/README.md @@ -11,6 +11,11 @@ With just these two files we can build both Debian and Alpine images for the fol - armv7 (linux/arm/v7) - armv6 (linux/arm/v6) +Some unsupported platforms for Debian based images. These are not built and tested by default and are only provided to make it easier for users to build for these architectures. +- 386 (linux/386) +- ppc64le (linux/ppc64le) +- s390x (linux/s390x) + To build these containers you need to enable QEMU binfmt support to be able to run/emulate architectures which are different then your host.
This ensures the container build process can run binaries from other architectures.
diff --git a/docker/docker-bake.hcl b/docker/docker-bake.hcl index e7f6a94b..38e7ef97 100644 --- a/docker/docker-bake.hcl +++ b/docker/docker-bake.hcl @@ -125,6 +125,40 @@ target "debian-armv6" { tags = generate_tags("", "-armv6") } +// ==== Start of unsupported Debian architecture targets === +// These are provided just to help users build for these rare platforms +// They will not be built by default +target "debian-386" { + inherits = ["debian"] + platforms = ["linux/386"] + tags = generate_tags("", "-386") + args = { + ARCH_OPENSSL_LIB_DIR = "/usr/lib/i386-linux-gnu" + ARCH_OPENSSL_INCLUDE_DIR = "/usr/include/i386-linux-gnu" + } +} + +target "debian-ppc64le" { + inherits = ["debian"] + platforms = ["linux/ppc64le"] + tags = generate_tags("", "-ppc64le") + args = { + ARCH_OPENSSL_LIB_DIR = "/usr/lib/powerpc64le-linux-gnu" + ARCH_OPENSSL_INCLUDE_DIR = "/usr/include/powerpc64le-linux-gnu" + } +} + +target "debian-s390x" { + inherits = ["debian"] + platforms = ["linux/s390x"] + tags = generate_tags("", "-s390x") + args = { + ARCH_OPENSSL_LIB_DIR = "/usr/lib/s390x-linux-gnu" + ARCH_OPENSSL_INCLUDE_DIR = "/usr/include/s390x-linux-gnu" + } +} +// ==== End of unsupported Debian architecture targets === + // A Group to build all platforms individually for local testing group "debian-all" { targets = ["debian-amd64", "debian-arm64", "debian-armv7", "debian-armv6"] From 84a7c7da5dc838a4e5b35695fa3fade4c6b84c37 Mon Sep 17 00:00:00 2001 From: Kristof Mattei <864376+kristof-mattei@users.noreply.github.com> Date: Sat, 27 Apr 2024 12:53:10 -0700 Subject: [PATCH 11/14] Pass in collection ids to notifier when sharing cipher. (#4517) --- src/api/core/accounts.rs | 2 +- src/api/core/ciphers.rs | 27 +++++++++++++++++---------- src/api/core/organizations.rs | 2 +- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/api/core/accounts.rs b/src/api/core/accounts.rs index ff74c84f..b2afe905 100644 --- a/src/api/core/accounts.rs +++ b/src/api/core/accounts.rs @@ -568,7 +568,7 @@ async fn post_rotatekey(data: JsonUpcase, headers: Headers, mut conn: D // Prevent triggering cipher updates via WebSockets by settings UpdateType::None // The user sessions are invalidated because all the ciphers were re-encrypted and thus triggering an update could cause issues. // We force the users to logout after the user has been saved to try and prevent these issues. - update_cipher_from_data(&mut saved_cipher, cipher_data, &headers, false, &mut conn, &nt, UpdateType::None) + update_cipher_from_data(&mut saved_cipher, cipher_data, &headers, None, &mut conn, &nt, UpdateType::None) .await? } } diff --git a/src/api/core/ciphers.rs b/src/api/core/ciphers.rs index 51a9589d..5a955d17 100644 --- a/src/api/core/ciphers.rs +++ b/src/api/core/ciphers.rs @@ -321,7 +321,7 @@ async fn post_ciphers(data: JsonUpcase, headers: Headers, mut conn: data.LastKnownRevisionDate = None; let mut cipher = Cipher::new(data.Type, data.Name.clone()); - update_cipher_from_data(&mut cipher, data, &headers, false, &mut conn, &nt, UpdateType::SyncCipherCreate).await?; + update_cipher_from_data(&mut cipher, data, &headers, None, &mut conn, &nt, UpdateType::SyncCipherCreate).await?; Ok(Json(cipher.to_json(&headers.host, &headers.user.uuid, None, CipherSyncType::User, &mut conn).await)) } @@ -352,7 +352,7 @@ pub async fn update_cipher_from_data( cipher: &mut Cipher, data: CipherData, headers: &Headers, - shared_to_collection: bool, + shared_to_collections: Option>, conn: &mut DbConn, nt: &Notify<'_>, ut: UpdateType, @@ -391,7 +391,7 @@ pub async fn update_cipher_from_data( match UserOrganization::find_by_user_and_org(&headers.user.uuid, &org_id, conn).await { None => err!("You don't have permission to add item to organization"), Some(org_user) => { - if shared_to_collection + if shared_to_collections.is_some() || org_user.has_full_access() || cipher.is_write_accessible_to_user(&headers.user.uuid, conn).await { @@ -518,8 +518,15 @@ pub async fn update_cipher_from_data( ) .await; } - nt.send_cipher_update(ut, cipher, &cipher.update_users_revision(conn).await, &headers.device.uuid, None, conn) - .await; + nt.send_cipher_update( + ut, + cipher, + &cipher.update_users_revision(conn).await, + &headers.device.uuid, + shared_to_collections, + conn, + ) + .await; } Ok(()) } @@ -580,7 +587,7 @@ async fn post_ciphers_import( cipher_data.FolderId = folder_uuid; let mut cipher = Cipher::new(cipher_data.Type, cipher_data.Name.clone()); - update_cipher_from_data(&mut cipher, cipher_data, &headers, false, &mut conn, &nt, UpdateType::None).await?; + update_cipher_from_data(&mut cipher, cipher_data, &headers, None, &mut conn, &nt, UpdateType::None).await?; } let mut user = headers.user; @@ -648,7 +655,7 @@ async fn put_cipher( err!("Cipher is not write accessible") } - update_cipher_from_data(&mut cipher, data, &headers, false, &mut conn, &nt, UpdateType::SyncCipherUpdate).await?; + update_cipher_from_data(&mut cipher, data, &headers, None, &mut conn, &nt, UpdateType::SyncCipherUpdate).await?; Ok(Json(cipher.to_json(&headers.host, &headers.user.uuid, None, CipherSyncType::User, &mut conn).await)) } @@ -898,7 +905,7 @@ async fn share_cipher_by_uuid( None => err!("Cipher doesn't exist"), }; - let mut shared_to_collection = false; + let mut shared_to_collections = vec![]; if let Some(organization_uuid) = &data.Cipher.OrganizationId { for uuid in &data.CollectionIds { @@ -907,7 +914,7 @@ async fn share_cipher_by_uuid( Some(collection) => { if collection.is_writable_by_user(&headers.user.uuid, conn).await { CollectionCipher::save(&cipher.uuid, &collection.uuid, conn).await?; - shared_to_collection = true; + shared_to_collections.push(collection.uuid); } else { err!("No rights to modify the collection") } @@ -923,7 +930,7 @@ async fn share_cipher_by_uuid( UpdateType::SyncCipherCreate }; - update_cipher_from_data(&mut cipher, data.Cipher, headers, shared_to_collection, conn, nt, ut).await?; + update_cipher_from_data(&mut cipher, data.Cipher, headers, Some(shared_to_collections), conn, nt, ut).await?; Ok(Json(cipher.to_json(&headers.host, &headers.user.uuid, None, CipherSyncType::User, conn).await)) } diff --git a/src/api/core/organizations.rs b/src/api/core/organizations.rs index 840ae6ea..38657ef6 100644 --- a/src/api/core/organizations.rs +++ b/src/api/core/organizations.rs @@ -1618,7 +1618,7 @@ async fn post_org_import( let mut ciphers = Vec::new(); for cipher_data in data.Ciphers { let mut cipher = Cipher::new(cipher_data.Type, cipher_data.Name.clone()); - update_cipher_from_data(&mut cipher, cipher_data, &headers, false, &mut conn, &nt, UpdateType::None).await.ok(); + update_cipher_from_data(&mut cipher, cipher_data, &headers, None, &mut conn, &nt, UpdateType::None).await.ok(); ciphers.push(cipher); } From 9dcc738f856d818b261507376290c544bf712d47 Mon Sep 17 00:00:00 2001 From: Stefan Melmuk <509385+stefan0xC@users.noreply.github.com> Date: Sat, 27 Apr 2024 22:09:00 +0200 Subject: [PATCH 12/14] improve access to collections via groups (#4441) * refactor get_org_collections_details * improve access to collection check * fix get_org_collection_detail too --- src/api/core/organizations.rs | 30 +++++++----------------------- src/auth.rs | 8 ++------ src/db/models/collection.rs | 26 ++++++++++++++------------ 3 files changed, 23 insertions(+), 41 deletions(-) diff --git a/src/api/core/organizations.rs b/src/api/core/organizations.rs index 38657ef6..c6556f77 100644 --- a/src/api/core/organizations.rs +++ b/src/api/core/organizations.rs @@ -329,27 +329,19 @@ async fn get_org_collections_details(org_id: &str, headers: ManagerHeadersLoose, && GroupUser::has_full_access_by_member(org_id, &user_org.uuid, &mut conn).await); for col in Collection::find_by_organization(org_id, &mut conn).await { - // assigned indicates whether the current user has access to the given collection - let mut assigned = has_full_access_to_org; + // check whether the current user has access to the given collection + let assigned = has_full_access_to_org + || CollectionUser::has_access_to_collection_by_user(&col.uuid, &user_org.user_uuid, &mut conn).await + || (CONFIG.org_groups_enabled() + && GroupUser::has_access_to_collection_by_member(&col.uuid, &user_org.uuid, &mut conn).await); // get the users assigned directly to the given collection let users: Vec = coll_users .iter() .filter(|collection_user| collection_user.collection_uuid == col.uuid) - .map(|collection_user| { - // check if the current user is assigned to this collection directly - if collection_user.user_uuid == user_org.uuid { - assigned = true; - } - SelectionReadOnly::to_collection_user_details_read_only(collection_user).to_json() - }) + .map(|collection_user| SelectionReadOnly::to_collection_user_details_read_only(collection_user).to_json()) .collect(); - // check if the current user has access to the given collection via a group - if !assigned && CONFIG.org_groups_enabled() { - assigned = GroupUser::has_access_to_collection_by_member(&col.uuid, &user_org.uuid, &mut conn).await; - } - // get the group details for the given collection let groups: Vec = if CONFIG.org_groups_enabled() { CollectionGroup::find_by_collection(&col.uuid, &mut conn) @@ -672,24 +664,16 @@ async fn get_org_collection_detail( Vec::with_capacity(0) }; - let mut assigned = false; let users: Vec = CollectionUser::find_by_collection_swap_user_uuid_with_org_user_uuid(&collection.uuid, &mut conn) .await .iter() .map(|collection_user| { - // Remember `user_uuid` is swapped here with the `user_org.uuid` with a join during the `find_by_collection_swap_user_uuid_with_org_user_uuid` call. - // We check here if the current user is assigned to this collection or not. - if collection_user.user_uuid == user_org.uuid { - assigned = true; - } SelectionReadOnly::to_collection_user_details_read_only(collection_user).to_json() }) .collect(); - if user_org.access_all { - assigned = true; - } + let assigned = Collection::can_access_collection(&user_org, &collection.uuid, &mut conn).await; let mut json_object = collection.to_json(); json_object["Assigned"] = json!(assigned); diff --git a/src/auth.rs b/src/auth.rs index 3f92be76..f05eba65 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -689,7 +689,7 @@ impl<'r> FromRequest<'r> for ManagerHeaders { _ => err_handler!("Error getting DB"), }; - if !can_access_collection(&headers.org_user, &col_id, &mut conn).await { + if !Collection::can_access_collection(&headers.org_user, &col_id, &mut conn).await { err_handler!("The current user isn't a manager for this collection") } } @@ -762,10 +762,6 @@ impl From for Headers { } } } -async fn can_access_collection(org_user: &UserOrganization, col_id: &str, conn: &mut DbConn) -> bool { - org_user.has_full_access() - || Collection::has_access_by_collection_and_user_uuid(col_id, &org_user.user_uuid, conn).await -} impl ManagerHeaders { pub async fn from_loose( @@ -777,7 +773,7 @@ impl ManagerHeaders { if uuid::Uuid::parse_str(col_id).is_err() { err!("Collection Id is malformed!"); } - if !can_access_collection(&h.org_user, col_id, conn).await { + if !Collection::can_access_collection(&h.org_user, col_id, conn).await { err!("You don't have access to all collections!"); } } diff --git a/src/db/models/collection.rs b/src/db/models/collection.rs index 4d3ccd2e..ae70c76c 100644 --- a/src/db/models/collection.rs +++ b/src/db/models/collection.rs @@ -1,6 +1,6 @@ use serde_json::Value; -use super::{CollectionGroup, User, UserOrgStatus, UserOrgType, UserOrganization}; +use super::{CollectionGroup, GroupUser, User, UserOrgStatus, UserOrgType, UserOrganization}; use crate::CONFIG; db_object! { @@ -102,6 +102,15 @@ impl Collection { json_object["HidePasswords"] = json!(hide_passwords); json_object } + + pub async fn can_access_collection(org_user: &UserOrganization, col_id: &str, conn: &mut DbConn) -> bool { + org_user.has_status(UserOrgStatus::Confirmed) + && (org_user.has_full_access() + || CollectionUser::has_access_to_collection_by_user(col_id, &org_user.user_uuid, conn).await + || (CONFIG.org_groups_enabled() + && (GroupUser::has_full_access_by_member(&org_user.org_uuid, &org_user.uuid, conn).await + || GroupUser::has_access_to_collection_by_member(col_id, &org_user.uuid, conn).await))) + } } use crate::db::DbConn; @@ -252,17 +261,6 @@ impl Collection { } } - // Check if a user has access to a specific collection - // FIXME: This needs to be reviewed. The query used by `find_by_user_uuid` could be adjusted to filter when needed. - // For now this is a good solution without making to much changes. - pub async fn has_access_by_collection_and_user_uuid( - collection_uuid: &str, - user_uuid: &str, - conn: &mut DbConn, - ) -> bool { - Self::find_by_user_uuid(user_uuid.to_owned(), conn).await.into_iter().any(|c| c.uuid == collection_uuid) - } - pub async fn find_by_organization_and_user_uuid(org_uuid: &str, user_uuid: &str, conn: &mut DbConn) -> Vec { Self::find_by_user_uuid(user_uuid.to_owned(), conn) .await @@ -644,6 +642,10 @@ impl CollectionUser { Ok(()) }} } + + pub async fn has_access_to_collection_by_user(col_id: &str, user_uuid: &str, conn: &mut DbConn) -> bool { + Self::find_by_collection_and_user(col_id, user_uuid, conn).await.is_some() + } } /// Database methods From e9aa5a545eda43e2e868f76115a3cc9c13d4cc30 Mon Sep 17 00:00:00 2001 From: Stefan Melmuk <509385+stefan0xC@users.noreply.github.com> Date: Sat, 27 Apr 2024 22:16:05 +0200 Subject: [PATCH 13/14] fix emergency access invites (#4337) * fix emergency access invites with no mail when mail is disabled instead of accepting emergency access for all invited users automatically, we only accept if the user already exists on registration of a new account any open emergency access invitations will be accepted, if mail is disabled also prevent invited emergency access contacts to register if emergency access is disabled (this is only relevant for when mail is enabled, if mail is disabled they should have an Invitation entry) * delete emergency access invitations if an invited user is deleted in the /admin panel their emergency access invitation will remain in the database which causes the to_json_grantee_details fn to panic * improve missing emergency access grantees instead of returning an empty emergency access contact the entry should not be added to the list. also the error handling can be improved a bit. --- src/api/core/accounts.rs | 12 +++++- src/api/core/emergency_access.rs | 69 +++++++++---------------------- src/db/models/emergency_access.rs | 56 +++++++++++++++++++++---- src/db/models/user.rs | 1 + 4 files changed, 78 insertions(+), 60 deletions(-) diff --git a/src/api/core/accounts.rs b/src/api/core/accounts.rs index b2afe905..5b947b85 100644 --- a/src/api/core/accounts.rs +++ b/src/api/core/accounts.rs @@ -166,7 +166,8 @@ pub async fn _register(data: JsonUpcase, mut conn: DbConn) -> Json } user } else if CONFIG.is_signup_allowed(&email) - || EmergencyAccess::find_invited_by_grantee_email(&email, &mut conn).await.is_some() + || (CONFIG.emergency_access_allowed() + && EmergencyAccess::find_invited_by_grantee_email(&email, &mut conn).await.is_some()) { user } else { @@ -217,7 +218,6 @@ pub async fn _register(data: JsonUpcase, mut conn: DbConn) -> Json if let Err(e) = mail::send_welcome_must_verify(&user.email, &user.uuid).await { error!("Error sending welcome email: {:#?}", e); } - user.last_verifying_at = Some(user.created_at); } else if let Err(e) = mail::send_welcome(&user.email).await { error!("Error sending welcome email: {:#?}", e); @@ -229,6 +229,14 @@ pub async fn _register(data: JsonUpcase, mut conn: DbConn) -> Json } user.save(&mut conn).await?; + + // accept any open emergency access invitations + if !CONFIG.mail_enabled() && CONFIG.emergency_access_allowed() { + for mut emergency_invite in EmergencyAccess::find_all_invited_by_grantee_email(&user.email, &mut conn).await { + let _ = emergency_invite.accept_invite(&user.uuid, &user.email, &mut conn).await; + } + } + Ok(Json(json!({ "Object": "register", "CaptchaBypassToken": "", diff --git a/src/api/core/emergency_access.rs b/src/api/core/emergency_access.rs index 5f64cde0..5d522c61 100644 --- a/src/api/core/emergency_access.rs +++ b/src/api/core/emergency_access.rs @@ -61,7 +61,9 @@ async fn get_contacts(headers: Headers, mut conn: DbConn) -> Json { let emergency_access_list = EmergencyAccess::find_all_by_grantor_uuid(&headers.user.uuid, &mut conn).await; let mut emergency_access_list_json = Vec::with_capacity(emergency_access_list.len()); for ea in emergency_access_list { - emergency_access_list_json.push(ea.to_json_grantee_details(&mut conn).await); + if let Some(grantee) = ea.to_json_grantee_details(&mut conn).await { + emergency_access_list_json.push(grantee) + } } Json(json!({ @@ -95,7 +97,9 @@ async fn get_emergency_access(emer_id: &str, mut conn: DbConn) -> JsonResult { check_emergency_access_enabled()?; match EmergencyAccess::find_by_uuid(emer_id, &mut conn).await { - Some(emergency_access) => Ok(Json(emergency_access.to_json_grantee_details(&mut conn).await)), + Some(emergency_access) => Ok(Json( + emergency_access.to_json_grantee_details(&mut conn).await.expect("Grantee user should exist but does not!"), + )), None => err!("Emergency access not valid."), } } @@ -209,7 +213,7 @@ async fn send_invite(data: JsonUpcase, headers: Heade err!("You can not set yourself as an emergency contact.") } - let grantee_user = match User::find_by_mail(&email, &mut conn).await { + let (grantee_user, new_user) = match User::find_by_mail(&email, &mut conn).await { None => { if !CONFIG.invitations_allowed() { err!(format!("Grantee user does not exist: {}", &email)) @@ -226,9 +230,10 @@ async fn send_invite(data: JsonUpcase, headers: Heade let mut user = User::new(email.clone()); user.save(&mut conn).await?; - user + (user, true) } - Some(user) => user, + Some(user) if user.password_hash.is_empty() => (user, true), + Some(user) => (user, false), }; if EmergencyAccess::find_by_grantor_uuid_and_grantee_uuid_or_email( @@ -256,15 +261,9 @@ async fn send_invite(data: JsonUpcase, headers: Heade &grantor_user.email, ) .await?; - } else { - // Automatically mark user as accepted if no email invites - match User::find_by_mail(&email, &mut conn).await { - Some(user) => match accept_invite_process(&user.uuid, &mut new_emergency_access, &email, &mut conn).await { - Ok(v) => v, - Err(e) => err!(e.to_string()), - }, - None => err!("Grantee user not found."), - } + } else if !new_user { + // if mail is not enabled immediately accept the invitation for existing users + new_emergency_access.accept_invite(&grantee_user.uuid, &email, &mut conn).await?; } Ok(()) @@ -308,17 +307,12 @@ async fn resend_invite(emer_id: &str, headers: Headers, mut conn: DbConn) -> Emp &grantor_user.email, ) .await?; - } else { - if Invitation::find_by_mail(&email, &mut conn).await.is_none() { - let invitation = Invitation::new(&email); - invitation.save(&mut conn).await?; - } - - // Automatically mark user as accepted if no email invites - match accept_invite_process(&grantee_user.uuid, &mut emergency_access, &email, &mut conn).await { - Ok(v) => v, - Err(e) => err!(e.to_string()), - } + } else if !grantee_user.password_hash.is_empty() { + // accept the invitation for existing user + emergency_access.accept_invite(&grantee_user.uuid, &email, &mut conn).await?; + } else if CONFIG.invitations_allowed() && Invitation::find_by_mail(&email, &mut conn).await.is_none() { + let invitation = Invitation::new(&email); + invitation.save(&mut conn).await?; } Ok(()) @@ -367,10 +361,7 @@ async fn accept_invite(emer_id: &str, data: JsonUpcase, headers: Hea && grantor_user.name == claims.grantor_name && grantor_user.email == claims.grantor_email { - match accept_invite_process(&grantee_user.uuid, &mut emergency_access, &grantee_user.email, &mut conn).await { - Ok(v) => v, - Err(e) => err!(e.to_string()), - } + emergency_access.accept_invite(&grantee_user.uuid, &grantee_user.email, &mut conn).await?; if CONFIG.mail_enabled() { mail::send_emergency_access_invite_accepted(&grantor_user.email, &grantee_user.email).await?; @@ -382,26 +373,6 @@ async fn accept_invite(emer_id: &str, data: JsonUpcase, headers: Hea } } -async fn accept_invite_process( - grantee_uuid: &str, - emergency_access: &mut EmergencyAccess, - grantee_email: &str, - conn: &mut DbConn, -) -> EmptyResult { - if emergency_access.email.is_none() || emergency_access.email.as_ref().unwrap() != grantee_email { - err!("User email does not match invite."); - } - - if emergency_access.status == EmergencyAccessStatus::Accepted as i32 { - err!("Emergency contact already accepted."); - } - - emergency_access.status = EmergencyAccessStatus::Accepted as i32; - emergency_access.grantee_uuid = Some(String::from(grantee_uuid)); - emergency_access.email = None; - emergency_access.save(conn).await -} - #[derive(Deserialize)] #[allow(non_snake_case)] struct ConfirmData { diff --git a/src/db/models/emergency_access.rs b/src/db/models/emergency_access.rs index c3682920..a0f07e7f 100644 --- a/src/db/models/emergency_access.rs +++ b/src/db/models/emergency_access.rs @@ -81,25 +81,32 @@ impl EmergencyAccess { }) } - pub async fn to_json_grantee_details(&self, conn: &mut DbConn) -> Value { + pub async fn to_json_grantee_details(&self, conn: &mut DbConn) -> Option { let grantee_user = if let Some(grantee_uuid) = self.grantee_uuid.as_deref() { - Some(User::find_by_uuid(grantee_uuid, conn).await.expect("Grantee user not found.")) + User::find_by_uuid(grantee_uuid, conn).await.expect("Grantee user not found.") } else if let Some(email) = self.email.as_deref() { - Some(User::find_by_mail(email, conn).await.expect("Grantee user not found.")) + match User::find_by_mail(email, conn).await { + Some(user) => user, + None => { + // remove outstanding invitations which should not exist + let _ = Self::delete_all_by_grantee_email(email, conn).await; + return None; + } + } } else { - None + return None; }; - json!({ + Some(json!({ "Id": self.uuid, "Status": self.status, "Type": self.atype, "WaitTimeDays": self.wait_time_days, - "GranteeId": grantee_user.as_ref().map_or("", |u| &u.uuid), - "Email": grantee_user.as_ref().map_or("", |u| &u.email), - "Name": grantee_user.as_ref().map_or("", |u| &u.name), + "GranteeId": grantee_user.uuid, + "Email": grantee_user.email, + "Name": grantee_user.name, "Object": "emergencyAccessGranteeDetails", - }) + })) } } @@ -214,6 +221,13 @@ impl EmergencyAccess { Ok(()) } + pub async fn delete_all_by_grantee_email(grantee_email: &str, conn: &mut DbConn) -> EmptyResult { + for ea in Self::find_all_invited_by_grantee_email(grantee_email, conn).await { + ea.delete(conn).await?; + } + Ok(()) + } + pub async fn delete(self, conn: &mut DbConn) -> EmptyResult { User::update_uuid_revision(&self.grantor_uuid, conn).await; @@ -285,6 +299,15 @@ impl EmergencyAccess { }} } + pub async fn find_all_invited_by_grantee_email(grantee_email: &str, conn: &mut DbConn) -> Vec { + db_run! { conn: { + emergency_access::table + .filter(emergency_access::email.eq(grantee_email)) + .filter(emergency_access::status.eq(EmergencyAccessStatus::Invited as i32)) + .load::(conn).expect("Error loading emergency_access").from_db() + }} + } + pub async fn find_all_by_grantor_uuid(grantor_uuid: &str, conn: &mut DbConn) -> Vec { db_run! { conn: { emergency_access::table @@ -292,6 +315,21 @@ impl EmergencyAccess { .load::(conn).expect("Error loading emergency_access").from_db() }} } + + pub async fn accept_invite(&mut self, grantee_uuid: &str, grantee_email: &str, conn: &mut DbConn) -> EmptyResult { + if self.email.is_none() || self.email.as_ref().unwrap() != grantee_email { + err!("User email does not match invite."); + } + + if self.status == EmergencyAccessStatus::Accepted as i32 { + err!("Emergency contact already accepted."); + } + + self.status = EmergencyAccessStatus::Accepted as i32; + self.grantee_uuid = Some(String::from(grantee_uuid)); + self.email = None; + self.save(conn).await + } } // endregion diff --git a/src/db/models/user.rs b/src/db/models/user.rs index feb09438..bf7dad32 100644 --- a/src/db/models/user.rs +++ b/src/db/models/user.rs @@ -311,6 +311,7 @@ impl User { Send::delete_all_by_user(&self.uuid, conn).await?; EmergencyAccess::delete_all_by_user(&self.uuid, conn).await?; + EmergencyAccess::delete_all_by_grantee_email(&self.email, conn).await?; UserOrganization::delete_all_by_user(&self.uuid, conn).await?; Cipher::delete_all_by_user(&self.uuid, conn).await?; Favorite::delete_all_by_user(&self.uuid, conn).await?; From 0fe93edea6cb8d4b30416a6d319164f8828ad8b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Sat, 27 Apr 2024 23:24:04 +0200 Subject: [PATCH 14/14] Some fixes for the new mobile apps (#4526) --- src/api/core/ciphers.rs | 9 +++++--- src/api/identity.rs | 7 +++++- src/db/models/organization.rs | 41 +++++++++++++++++------------------ src/db/models/user.rs | 2 ++ src/main.rs | 2 +- 5 files changed, 35 insertions(+), 26 deletions(-) diff --git a/src/api/core/ciphers.rs b/src/api/core/ciphers.rs index 5a955d17..18d1b998 100644 --- a/src/api/core/ciphers.rs +++ b/src/api/core/ciphers.rs @@ -10,6 +10,7 @@ use rocket::{ }; use serde_json::Value; +use crate::util::NumberOrString; use crate::{ api::{self, core::log_event, EmptyResult, JsonResult, JsonUpcase, Notify, PasswordOrOtpData, UpdateType}, auth::Headers, @@ -964,7 +965,7 @@ async fn get_attachment(uuid: &str, attachment_id: &str, headers: Headers, mut c struct AttachmentRequestData { Key: String, FileName: String, - FileSize: i64, + FileSize: NumberOrString, AdminRequest: Option, // true when attaching from an org vault view } @@ -994,12 +995,14 @@ async fn post_attachment_v2( } let data: AttachmentRequestData = data.into_inner().data; - if data.FileSize < 0 { + let file_size = data.FileSize.into_i64()?; + + if file_size < 0 { err!("Attachment size can't be negative") } let attachment_id = crypto::generate_attachment_id(); let attachment = - Attachment::new(attachment_id.clone(), cipher.uuid.clone(), data.FileName, data.FileSize, Some(data.Key)); + Attachment::new(attachment_id.clone(), cipher.uuid.clone(), data.FileName, file_size, Some(data.Key)); attachment.save(&mut conn).await.expect("Error saving attachment"); let url = format!("/ciphers/{}/attachment/{}", cipher.uuid, attachment_id); diff --git a/src/api/identity.rs b/src/api/identity.rs index 9f3cd1bf..ad51d664 100644 --- a/src/api/identity.rs +++ b/src/api/identity.rs @@ -295,7 +295,12 @@ async fn _password_login( "KdfIterations": user.client_kdf_iter, "KdfMemory": user.client_kdf_memory, "KdfParallelism": user.client_kdf_parallelism, - "ResetMasterPassword": false,// TODO: Same as above + "ResetMasterPassword": false, // TODO: Same as above + "ForcePasswordReset": false, + "MasterPasswordPolicy": { + "object": "masterPasswordPolicy", + }, + "scope": scope, "unofficialServer": true, "UserDecryptionOptions": { diff --git a/src/db/models/organization.rs b/src/db/models/organization.rs index 180b1c1d..59d66856 100644 --- a/src/db/models/organization.rs +++ b/src/db/models/organization.rs @@ -344,6 +344,25 @@ impl UserOrganization { pub async fn to_json(&self, conn: &mut DbConn) -> Value { let org = Organization::find_by_uuid(&self.org_uuid, conn).await.unwrap(); + let permissions = json!({ + // TODO: Add support for Custom User Roles + // See: https://bitwarden.com/help/article/user-types-access-control/#custom-role + "accessEventLogs": false, + "accessImportExport": false, + "accessReports": false, + "createNewCollections": false, + "editAnyCollection": false, + "deleteAnyCollection": false, + "editAssignedCollections": false, + "deleteAssignedCollections": false, + "manageGroups": false, + "managePolicies": false, + "manageSso": false, // Not supported + "manageUsers": false, + "manageResetPassword": false, + "manageScim": false // Not supported (Not AGPLv3 Licensed) + }); + // https://github.com/bitwarden/server/blob/13d1e74d6960cf0d042620b72d85bf583a4236f7/src/Api/Models/Response/ProfileOrganizationResponseModel.cs json!({ "Id": self.org_uuid, @@ -371,27 +390,7 @@ impl UserOrganization { // "KeyConnectorEnabled": false, // "KeyConnectorUrl": null, - // TODO: Add support for Custom User Roles - // See: https://bitwarden.com/help/article/user-types-access-control/#custom-role - // "Permissions": { - // "AccessEventLogs": false, - // "AccessImportExport": false, - // "AccessReports": false, - // "ManageAllCollections": false, - // "CreateNewCollections": false, - // "EditAnyCollection": false, - // "DeleteAnyCollection": false, - // "ManageAssignedCollections": false, - // "editAssignedCollections": false, - // "deleteAssignedCollections": false, - // "ManageCiphers": false, - // "ManageGroups": false, - // "ManagePolicies": false, - // "ManageResetPassword": false, - // "ManageSso": false, // Not supported - // "ManageUsers": false, - // "ManageScim": false, // Not supported (Not AGPLv3 Licensed) - // }, + "permissions": permissions, "MaxStorageGb": 10, // The value doesn't matter, we don't check server-side diff --git a/src/db/models/user.rs b/src/db/models/user.rs index bf7dad32..d87defd0 100644 --- a/src/db/models/user.rs +++ b/src/db/models/user.rs @@ -246,6 +246,7 @@ impl User { "Email": self.email, "EmailVerified": !CONFIG.mail_enabled() || self.verified_at.is_some(), "Premium": true, + "PremiumFromOrganization": false, "MasterPasswordHint": self.password_hint, "Culture": "en-US", "TwoFactorEnabled": twofactor_enabled, @@ -257,6 +258,7 @@ impl User { "ProviderOrganizations": [], "ForcePasswordReset": false, "AvatarColor": self.avatar_color, + "UsesKeyConnector": false, "Object": "profile", }) } diff --git a/src/main.rs b/src/main.rs index c20ecfe1..c7726a87 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,7 @@ // The more key/value pairs there are the more recursion occurs. // We want to keep this as low as possible, but not higher then 128. // If you go above 128 it will cause rust-analyzer to fail, -#![recursion_limit = "87"] +#![recursion_limit = "90"] // When enabled use MiMalloc as malloc instead of the default malloc #[cfg(feature = "enable_mimalloc")]