mirror of
https://github.com/dani-garcia/vaultwarden.git
synced 2025-05-28 06:23:56 +00:00
Several updates and fixes
- Removed all `thread::sleep` and use `tokio::time::sleep` now. This solves an issue with updating to Bullseye ( Resolves #1998 ) - Updated all Debian images to Bullseye - Added MiMalloc feature and enabled it by default for Alpine based images This increases performance for the Alpine images because the default memory allocator for MUSL based binaries isn't that fast - Updated `dotenv` to `dotenvy` a maintained and updated fork - Fixed an issue with a newer jslib (not fully released yet) That version uses a different endpoint for `prelogin` Resolves #2378 )
This commit is contained in:
parent
8d06d9c111
commit
b0faaf2527
27 changed files with 197 additions and 99 deletions
|
@ -599,12 +599,11 @@ async fn password_hint(data: JsonUpcase<PasswordHintData>, conn: DbConn) -> Empt
|
|||
// There is still a timing side channel here in that the code
|
||||
// paths that send mail take noticeably longer than ones that
|
||||
// don't. Add a randomized sleep to mitigate this somewhat.
|
||||
use rand::{thread_rng, Rng};
|
||||
let mut rng = thread_rng();
|
||||
let base = 1000;
|
||||
use rand::{rngs::SmallRng, Rng, SeedableRng};
|
||||
let mut rng = SmallRng::from_entropy();
|
||||
let delta: i32 = 100;
|
||||
let sleep_ms = (base + rng.gen_range(-delta..=delta)) as u64;
|
||||
std::thread::sleep(std::time::Duration::from_millis(sleep_ms));
|
||||
let sleep_ms = (1_000 + rng.gen_range(-delta..=delta)) as u64;
|
||||
tokio::time::sleep(tokio::time::Duration::from_millis(sleep_ms)).await;
|
||||
Ok(())
|
||||
} else {
|
||||
err!(NO_HINT);
|
||||
|
@ -626,12 +625,16 @@ async fn password_hint(data: JsonUpcase<PasswordHintData>, conn: DbConn) -> Empt
|
|||
|
||||
#[derive(Deserialize)]
|
||||
#[allow(non_snake_case)]
|
||||
struct PreloginData {
|
||||
pub struct PreloginData {
|
||||
Email: String,
|
||||
}
|
||||
|
||||
#[post("/accounts/prelogin", data = "<data>")]
|
||||
async fn prelogin(data: JsonUpcase<PreloginData>, conn: DbConn) -> Json<Value> {
|
||||
_prelogin(data, conn).await
|
||||
}
|
||||
|
||||
pub async fn _prelogin(data: JsonUpcase<PreloginData>, conn: DbConn) -> Json<Value> {
|
||||
let data: PreloginData = data.into_inner().data;
|
||||
|
||||
let (kdf_type, kdf_iter) = match User::find_by_mail(&data.Email, &conn).await {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
mod accounts;
|
||||
pub mod accounts;
|
||||
mod ciphers;
|
||||
mod emergency_access;
|
||||
mod folders;
|
||||
|
|
|
@ -9,8 +9,9 @@ use serde_json::Value;
|
|||
|
||||
use crate::{
|
||||
api::{
|
||||
core::accounts::{PreloginData, _prelogin},
|
||||
core::two_factor::{duo, email, email::EmailTokenData, yubikey},
|
||||
ApiResult, EmptyResult, JsonResult,
|
||||
ApiResult, EmptyResult, JsonResult, JsonUpcase,
|
||||
},
|
||||
auth::ClientIp,
|
||||
db::{models::*, DbConn},
|
||||
|
@ -19,7 +20,7 @@ use crate::{
|
|||
};
|
||||
|
||||
pub fn routes() -> Vec<Route> {
|
||||
routes![login]
|
||||
routes![login, prelogin]
|
||||
}
|
||||
|
||||
#[post("/connect/token", data = "<data>")]
|
||||
|
@ -449,6 +450,11 @@ async fn _json_err_twofactor(providers: &[i32], user_uuid: &str, conn: &DbConn)
|
|||
Ok(result)
|
||||
}
|
||||
|
||||
#[post("/accounts/prelogin", data = "<data>")]
|
||||
async fn prelogin(data: JsonUpcase<PreloginData>, conn: DbConn) -> Json<Value> {
|
||||
_prelogin(data, conn).await
|
||||
}
|
||||
|
||||
// https://github.com/bitwarden/jslib/blob/master/common/src/models/request/tokenRequest.ts
|
||||
// https://github.com/bitwarden/mobile/blob/master/src/Core/Models/Request/TokenRequest.cs
|
||||
#[derive(Debug, Clone, Default, FromForm)]
|
||||
|
|
|
@ -59,13 +59,13 @@ macro_rules! make_config {
|
|||
impl ConfigBuilder {
|
||||
#[allow(clippy::field_reassign_with_default)]
|
||||
fn from_env() -> Self {
|
||||
match dotenv::from_path(get_env("ENV_FILE").unwrap_or_else(|| String::from(".env"))) {
|
||||
match dotenvy::from_path(get_env("ENV_FILE").unwrap_or_else(|| String::from(".env"))) {
|
||||
Ok(_) => (),
|
||||
Err(e) => match e {
|
||||
dotenv::Error::LineParse(msg, pos) => {
|
||||
dotenvy::Error::LineParse(msg, pos) => {
|
||||
panic!("Error loading the .env file:\nNear {:?} on position {}\nPlease fix and restart!\n", msg, pos);
|
||||
},
|
||||
dotenv::Error::Io(ioerr) => match ioerr.kind() {
|
||||
dotenvy::Error::Io(ioerr) => match ioerr.kind() {
|
||||
std::io::ErrorKind::NotFound => {
|
||||
println!("[INFO] No .env file found.\n");
|
||||
},
|
||||
|
@ -955,7 +955,8 @@ impl Config {
|
|||
handle.shutdown().ok();
|
||||
}
|
||||
// Wait a bit before stopping the web server
|
||||
std::thread::sleep(std::time::Duration::from_secs(1));
|
||||
tokio::runtime::Handle::current()
|
||||
.block_on(async move { tokio::time::sleep(tokio::time::Duration::from_secs(1)).await });
|
||||
if let Some(handle) = c.rocket_shutdown_handle.clone() {
|
||||
handle.notify();
|
||||
}
|
||||
|
|
18
src/main.rs
18
src/main.rs
|
@ -8,6 +8,13 @@
|
|||
// If you go above 128 it will cause rust-analyzer to fail,
|
||||
#![recursion_limit = "87"]
|
||||
|
||||
// When enabled use MiMalloc as malloc instead of the default malloc
|
||||
#[cfg(feature = "enable_mimalloc")]
|
||||
use mimalloc::MiMalloc;
|
||||
#[cfg(feature = "enable_mimalloc")]
|
||||
#[cfg_attr(feature = "enable_mimalloc", global_allocator)]
|
||||
static GLOBAL: MiMalloc = MiMalloc;
|
||||
|
||||
#[macro_use]
|
||||
extern crate rocket;
|
||||
#[macro_use]
|
||||
|
@ -28,7 +35,6 @@ use std::{
|
|||
process::exit,
|
||||
str::FromStr,
|
||||
thread,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
#[macro_use]
|
||||
|
@ -71,7 +77,7 @@ async fn main() -> Result<(), Error> {
|
|||
create_dir(&CONFIG.sends_folder(), "sends folder");
|
||||
create_dir(&CONFIG.attachments_folder(), "attachments folder");
|
||||
|
||||
let pool = create_db_pool();
|
||||
let pool = create_db_pool().await;
|
||||
schedule_jobs(pool.clone()).await;
|
||||
crate::db::models::TwoFactor::migrate_u2f_to_webauthn(&pool.get().await.unwrap()).await.unwrap();
|
||||
|
||||
|
@ -315,8 +321,8 @@ fn check_web_vault() {
|
|||
}
|
||||
}
|
||||
|
||||
fn create_db_pool() -> db::DbPool {
|
||||
match util::retry_db(db::DbPool::from_config, CONFIG.db_connection_retries()) {
|
||||
async fn create_db_pool() -> db::DbPool {
|
||||
match util::retry_db(db::DbPool::from_config, CONFIG.db_connection_retries()).await {
|
||||
Ok(p) => p,
|
||||
Err(e) => {
|
||||
error!("Error creating database pool: {:?}", e);
|
||||
|
@ -430,7 +436,9 @@ async fn schedule_jobs(pool: db::DbPool) {
|
|||
// tick, the one that was added earlier will run first.
|
||||
loop {
|
||||
sched.tick();
|
||||
thread::sleep(Duration::from_millis(CONFIG.job_poll_interval_ms()));
|
||||
runtime.block_on(async move {
|
||||
tokio::time::sleep(tokio::time::Duration::from_millis(CONFIG.job_poll_interval_ms())).await
|
||||
});
|
||||
}
|
||||
})
|
||||
.expect("Error spawning job scheduler thread");
|
||||
|
|
13
src/util.rs
13
src/util.rs
|
@ -11,8 +11,10 @@ use rocket::{
|
|||
Data, Orbit, Request, Response, Rocket,
|
||||
};
|
||||
|
||||
use std::thread::sleep;
|
||||
use std::time::Duration;
|
||||
use tokio::{
|
||||
runtime::Handle,
|
||||
time::{sleep, Duration},
|
||||
};
|
||||
|
||||
use crate::CONFIG;
|
||||
|
||||
|
@ -581,14 +583,13 @@ where
|
|||
if tries >= max_tries {
|
||||
return err;
|
||||
}
|
||||
|
||||
sleep(Duration::from_millis(500));
|
||||
Handle::current().block_on(async move { sleep(Duration::from_millis(500)).await });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn retry_db<F, T, E>(func: F, max_tries: u32) -> Result<T, E>
|
||||
pub async fn retry_db<F, T, E>(func: F, max_tries: u32) -> Result<T, E>
|
||||
where
|
||||
F: Fn() -> Result<T, E>,
|
||||
E: std::error::Error,
|
||||
|
@ -607,7 +608,7 @@ where
|
|||
|
||||
warn!("Can't connect to database, retrying: {:?}", e);
|
||||
|
||||
sleep(Duration::from_millis(1_000));
|
||||
sleep(Duration::from_millis(1_000)).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue